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

2025-03-13

Last modified: 2025-03-13 17:09:51

< 2025-03-12 2025-03-14 >

Showing 2d SDFs flat

In the night I worked out how to do this.

So the issue is that if we make the 2d SDF give a correct distance to a "thin" shape then all of the interior distances are 0 because the shape has no thickness, which means when you extrude it you get a broken 3d SDF.

But if you ignore the Z coordinate and just give a 2d distance, then the sketch itself appears as an infinite extrusion.

So the solution is to make the Extrude node set Z=0 before evaluating the sketch node, and make the sketch give a 2d distance within some short Z distance around Z=0, and give a 3d distance to the surface otherwise. So technically this gives us a broken 3d SDF, but the only time the sketch will be used directly as a 3d SDF is when we temporarily view it before Extrude/Revolve, and the output of Extrude/Revolve will be a correct SDF.

Good.

Filleting the top/bottom of an extrusion

How would you do this? Use smax() instead of max() for the distance to the closest surface? Seems to work.

It does mean we now get a "lowerbound" instead of "exact" function, but that's life.

It is bad because it breaks roughness at the ends:

Oh, actually, easily fixed if I delete the special case code for the inside of the object! Great success.

Quality drops when you tab away

The issue is that it's not rendering any frames, so the frame rate drops towards 0, so the adaptive quality makes a big adjustment.

It would come back within 2 seconds, but the frame rate is capped at 60 fps, so it can't tell that the scene is rendering any faster than that.

I think I want Cursor to notice whether the window gets focused and reset the adaptive quality start time.

Done on the first try, easy.

Domain repetition for Linear Pattern

It looks like this is mostly working but we get infinitely many copies.

OK, limiting the number of copies works. I also added a toggle for allowDomainRepetition so that we can see the frame rate difference. With domain repetition disabled, and 200 copies of a torus, I got resolution scale dropping by 75%, so only 1/16 as many pixels. So this is a good improvement.

Next up is doing domain repetition of a union of a small number of objects when they have overlapping bounding spheres (also adding bounding sphere calculation to more node types).

Great success, seems to be working well.

Chamfering

I think my chmax() is not quite as good as it could be:

Dividing the chmax() answer by 2 in the chamfer region makes it work better, unsure if that is sound or not, but it's an improvement for now. Do I need the same thing on chmin()? May as well.

Should it be 1/sqrt(2) instead of 0.5? Unsure.

Here it is thicknessed and with a box subtracted:

So yeah this is definitely wrong.

Ah! The problem is that I was checking the distances and then selecting the calculation accordingly, I should do both calculations and then take the min/max. Grok wrote this for me, and looks like it is working now.

Sketch planes

Next thing is to fix worldToScreen() and screenToWorld() so that sketch planes work properly.

Inverting the Y coordinate was enough to make worldToScreen() work.

claude-3.7-sonnet-thinking has got most of the way to a screenToWorld() that works with arbitrary rotations. It just had the Y coordinate inverted. It's not got it exactly right but it is close enough to live with.

Ah, my fault, I needed to invert the incoming screen-space Y coordinate rather than the outgoing world-space Y coordinate. Looks good now!

Draft angle on Extrude

Is this easy to do? I could basically add the Z coordinate (multiplied by some factor) to the 2d distance, and then it would get narrower as it goes up?

Yes, that does seem to work, but it interacts badly with chamfered ends.

Maybe simply clamp the Z coordinate to be within the extrusion range?

Seems to be working!

That is meant to be 1 degree, is it actually 1 degree? Check with gimp.

Yet again I need the image measuring tool.

Ah, I think it is because the SDF is meant to give the distance to the nearest point, which if you have a draft angle is no longer the in-plane distance to the 2d SDF. The direction also has to rotate around by whatever the draft angle is.

Which then means the distance to the 2d surface is the in-plane distance multiplied by the cosine of the angle.

Actually looks like that may have worked?

Sketcher improvements

The most obvious thing is to draw the sketch's local X/Y axis.

And maybe some grid lines?

And now the grid scale is adaptive, so it changes with zoom.

Next thing is I want to be able to pan/rotate/zoom while inside the sketch editor.

I've made it so that panning and rotating don't require the mouse button, and then I probably just need the mouse events to reach the GL canvas even while the sketcher canvas is open.

OK, done, it works!

A few things though:

  1. the sketcher doesn't seem to redraw until you move the mouse again, which makes the sketch be in the wrong place while panning around etc.
  2. the sketcher drawing code is super inefficient, severely drops the framerate

I'll fix the framerate problem first and then try to make it redraw more frequently.

Cool, works much better now. I made the "camera" module tell the "main" module when the coordinate system changes, and "main" tells ui.sketchEditor to redraw, if there is any ui.sketchEditor.

The redraw is quite slow on zooming out, etc., I should make it set a 10ms timer before redrawing? Or, just queue the render call and call it from the main app render()? So now it only draws once per frame. Much better.

Maybe the next thing is to be able to add extra polygons? And where they overlap each other we actually don't want to combine them with union, we probably want "xor"?

Blend radius on Linear Pattern

I did the straightforward thing, but domain repetition confuses it.

One issue is that smooth union of an object with itself is not identity!

But actually, why would we be doing that? We have a loop over the copies we're making, there should never be duplicates.

It was because I was doing an initial child generation outside the loop, so that one was getting duplicated.

I have it working now!

That's a smooth blend of 8 overlapping roughened boxes.

Domain repetition on Mirror

When the bounding sphere doesn't intersect the mirroring plane, we can work out which side of the plane the object is in and mirror it by taking either abs(p.z) or -abs(p.z).

If it does intersect the mirroring plane then we need the explicit union.

Not too hard, done, also added blendRadius and chamfer options.

rotateToAxis

I think rotateToAxis() is not working properly.

If I try to do a LinearPattern along the Y axis the frame rate drops precipitously and it doesn't draw anything.

It works correctly if I mix in just a little bit of X axis, e.g. (0.0001, 1, 0).

I have it fixed now but... the coordinate system is left-handed again! How has this happened?

Oh no, I actually think it's not. I think it's fine. I think the axis indicator graphic is just very confusing.

Todo

< 2025-03-12 2025-03-14 >