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

2025-04-01

Last modified: 2025-04-02 07:35:10

< 2025-03-31 2025-04-02 >

Tests

I've fixed all the broken Peptide unit tests, and added some TreeNode tests.

Overall I don't really like the test suite. Seems like the "harness" should be a bit more abstracted, instead of implemented inside the same file that has 2000 lines of tests. And the page that runs tests should be unified between Isoform tests and Peptide tests. And maybe let you pick a subset of tests to run, because tests are only getting slower and it is annoying to wait for them all.

Leaked volume on MeshNode

A couple of issues:

The VoxelNode of the Mesh has holes in it:

And if I increase the resolution it has "sticks" coming out.

You can also see the normals are bad.

The normals are improved if I add at least 1 layer of empty voxels around the the outside of the part.

Lol, I fixed the issues with both the holes and the sticks by making the "ray direction" for the intersection test go to some random direction instead of (0,0,1). That way we don't have numbers lying exactly on 0 etc. and it all works.

However autodiff normals are still bad. I think because the derivative of the 3d texture is hardcoded as (0,0,0) and that is not right. Maybe we do central differences on the texture?

My first thought was that wouldn't work very well unless the step size was very big - but actually because of the trilinear filtering it will work perfectly!

And indeed it does, although the surface looks grainy, which suggests numerical issues. I guess because the texture is only R16F? Maybe use bigger step size?

Yep, golden.

One issue is ridges on the edges:

I don't know if that means I am doing something wrong, or that is just a fundamental problem of using distance voxels.

I think the Valve paper is saying that linear interpolation of a distance field gives you smooth edges?

Forget about this for now.

Next thing is the mesh being clipped because the bounding box is apparently wrong.

The bounding box goes from z=0 to z=10, but the object seems to stop at z=5.

Ah, the thing that works out the distance to the bounding box doesn't translate the box to the right place! Fixed, good.

STL import

Now that I have a working VoxelNode, I want STL import to use it by default.

I tried importing the mesh with 2000 triangles at 128x128x128. It is taking a very long time.

Would it be better to just directly populate the voxels with the distance to the triangles, instead of going through Peptide? Probably not.

I'll try again at 32x32x32. It took 3m8s.

I can't work out how to profile this, it seems to be invisible to the Firefox profiler, maybe because it is running in a single event callback instead of every frame?

Maybe leave it for now.

Edge detection

The issue with edge detection is that we don't just want to know if there is a sharp edge at the point under the pixel, we want to know if there is one anywhere within a few pixels, so that we can draw lines that have non-zero thickness.

One thing I could do is comment out all the lighting code and instead plot the magnitude of the second derivative? Just to see what we're playing with.

Plotting the abs of the normal gives stuff like:

The second derivative is 3 vec3s, how do I plot that?

That is from:

vec3 mapSecondDerivative(vec3 p) {
    float eps = 0.0001;
    vec3 nx = mapNormal(p + vec3(eps, 0.0, 0.0)) - mapNormal(p);
    vec3 ny = mapNormal(p + vec3(0.0, eps, 0.0)) - mapNormal(p);
    vec3 nz = mapNormal(p + vec3(0.0, 0.0, eps)) - mapNormal(p);
    return 10000.0 * vec3(abs(nx.x), abs(ny.y), abs(nz.z));
}

Not sure how legit that is. But it does very clearly show that we don't get a nice large second derivative around the discontinuity. Part of that is just the difference between a discontinuity and a rapid change. A discontinuity doesn't have any region that has a rapid change, it just instantly changes.

So the idea of using analytical 2nd and 3rd derivatives to find edges is fundamentally broken I think, even if you could solve the problem of needing to know if there is a high rate of change "nearby". Finite differences has the big advantage that it actually can detect high rates of change around discontinuities.

If not automatic differentiation, is there another analytical method that can detect discontinuities?

By increasing eps from 0.0001 to 0.1, we get:

Which now actually is showing larger values near edges, but they aren't "stable", they sort of shift and change as you rotate the object. They also don't have a consistent thickness.

Now with eps=0.01, and showing the "length" of the change in the normal:

The edges get thicker where the material is thinner:

What if we use a really small eps, and then take max() of the second derivative at several other places in some neighbourhood?

The edges get thicker where the material is thinner because the neighbourhood passes out the other side of the material. If we're saying we want to draw edges with 0.1mm thickness, then anywhere that is less than 0.1mm thick will be considered an edge.

The edges would at least become stable if we kept a consistent coordinate system for finite differences Apply the rotation only when evaluating the distance to the object, then work out the hit position in object coordinates, and then do second derivatives etc. from the object coordinates without any rotation. That way the neighbourhood stays the same regardless of the orientation.

Another idea is when you turn on "show edges" or whatever, it secretly turns min/max into smoothmin/smoothmax! And then there actually will be a large second derivative at the edges.

We could even go as far as saying that we don't even support non-smooth min/max ever.

But then what? Just drawing edges isn't enough to allow selecting them. For selecting them we maybe do want genuine discontinuities.

< 2025-03-31 2025-04-02 >