jes notes Index Gallery . Signed Distance Functions Shaft passers Snap issues

2025-04-12

Last modified: 2025-04-13 10:07:28

< 2025-04-10 2025-04-13 >

Better intersections performance

So I think the current status is the "better intersections idea" is:

And then the distance to surface is min of [max of initial distances] and the distance that the settled point is from the start point.

And it only works for convex shapes that have non-zero intersection.

And I can only do 1 iteration because my derivatives have awful performance for some reason. So next step is working out why. I'm going to dump the generated code for a box, and then the (simple) intersection of two boxes, and then one iteration of following gradients, and see what seems to be growing.

Box is:

add(vlength(vmax(vsub(vabs(p), vdiv(u_Box_1_size, 2)), Vec3(0, 0, 0))), min(max(vecX(vsub(vabs(p), vdiv(u_Box_1_size, 2))), max(vecY(vsub(vabs(p), vdiv(u_Box_1_size, 2))), vecZ(vsub(vabs(p), vdiv(u_Box_1_size, 2))))), 0))

Derivative of Box is absolutely enormous (6869 bytes, when dumped in the same format).

Why is it so big?

One thing I've noticed is the derivative of vmin has:

P.mix(bDerivative[0].vecX, aDerivative[0].vecX, P.step(P.vecX(b), P.vecX(a)))

But foo.vecX is not how you do it! Why does this work? I think it doesn't, I think there's no test for vmin. I'll add one now. It also had the arguments to step the wrong way around.

So the derivative of Box should be the derivative of add where the arguments are a vlength(...) and min(...). Derivative of a+b is equal to derivative of a plus derivative of b.

OK, here's why it is getting so big. When you take the derivative of a function you get an expression somewhere between maybe 3x and 6x as large as what you started with.

Looking at the amount of generated JS code:

So maybe our derivative gains about 6 lines of code for every line of code we add to the base object? If it is linear.

So if the "BetterIntersection" is 724 lines longer than the simple intersection, then the derivative should be 4344 lines longer than the simple intersection derivative derivative, or about 4600 lines.

So yeah that is pretty long.

How do I figure out why it is running out of memory?

Firefox seems to have some thing where if a page hangs and then you close the tab and open the same page in a new tab it doesn't load? I don't really understand why.

Oh! I see the problem. The problem is that we're calling derivative() before simplify(). Which means it has to calculate and recalculate the same expressions over and over again. I could make Peptide cache the results?

With that solved, I get the derivative of the "Better Intersection" almost instantly! It is 2635 lines of JavaScript, or about 10x larger than the derivative of the simple intersection.

Should Peptide do "expression interning" more generally? So we'd basically do simplify() automatically as the expression is being built, instead of in one big pass at the end.

Adding more and more iterations of gradient following, I got a new error from the shader compiler:

Internal error: assembly compile error for fragment shader at offset 1972813:
-- error message --
line 65583, column 1:  error: too many instructions

And I still haven't got an intersection SDF that is "correct" even for convex overlapping shapes. Maybe the idea just doesn't work.

But I have made derivative calculation more efficient and fixed vmin, so there's that.

Core problems

Remaining core problems:

Propagating distance fields in grids

I want an efficient algorithm to propagate distances, it feels like if at each pixel/voxel you store not just the distance to the nearest point, but also the coordinates of that point, then you can propagate distances from a neighbour by checking for each of the neighbours' closest points, which one is closest to you.

So initialise the grid only along the boundary of the surface, and then propagate the rest with a BFS?

This would be useful for more efficiently importing both meshes and images.

Helical extrusion

Let's assume opTwist works properly.

Is there a way to transform a sketch according to the helical extrusion parameters, so that when you do opTwist on it you get a helical extrusion?

So a helical extrusion would be:

  1. "helical skew" or whatever
  2. linear extrude
  3. opTwist

To get some examples I can make helical extrusions in FreeCAD and then look at their cross sections.

This is what a 60-degree V-thread looks like:

The cross section of the sketch is just a triangle, and the "skewed" version has the edges smeared around a circle.

Does that just mean we interpret the sketch as polar coordinates?

X axis of sketch is radius axis of polar coordinates, Y axis of sketch is angle axis of polar coordinates, normalised by the pitch?

I could test this out by having a PolarSkewNode that does this remapping.

Interestingly that gives us an extra degree of freedom compared to a normal helical extrusion. We can change the pitch of the twist and the pitch of the "Polar Skew" independently.

Weighting blends by normal alignment

To fix the issue where blends "bulge out" on parallel surfaces, can we weight the blend by the dot product of one normal and the negation of the other normal? So that it is 0 if they point in opposite directions.

That is slightly wrong. The dot product is 0 when they are perpendicular, 1 when parallel, and -1 when antiparallel.

So take 1-abs(dotProduct) and you get a value that is highest for perpendicular surfaces, and lowest for parallel surfaces.

But it still has a bit of a bulge out at the regions of the object that don't overlap with the other object, because there the normals are not perfectly parallel/antiparallel.

< 2025-04-10 2025-04-13 >