research(R16): why hard SDF intersections alias under marching cubes; fillet sizing per LOD

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-24 15:44:49 +02:00
1 parent 3073d1b2fd
commit 6110f118e3
1 file changed
+45
@@ -0,0 +1,45 @@
# Key recommendations
- Build the bore and sloped floor as one void field with a rounded intersection, then apply the passage carve and stamps. Remove the trailing hard cap; constrain later stamps to the intended floor profile so they cannot reopen space below it.
- Use **geometric fillet radius** \(R \ge 2h\) as a practical minimum, with \(R \approx 3h\) preferred, where \(h\) is the current mesh spacing. At 25 cm spacing, that means **0.5 m minimum, 0.75 m preferred**. This is a rule of thumb, not a guarantee of alias-free output.
- A fixed fillet does not keep that resolution at coarser LODs. At step 8, the corresponding radii are **4 m minimum, 6 m preferred**. Use coarser-LOD filtering or feature-aware meshing if that much rounding changes the look.
- Judge the fix with the L48 **wall-foot cluster area and severe-edge measures**, not only the floor rails. The candidate had 7.095 m² of flagged clusters, 65.5 severe edges, and 303 flagged triangles. Those should fall toward the plain-native control, which had no clusters.
## Why the junction aliases
A hard intersection is `max(d_bore, d_floor)` under the usual inside-negative convention. It preserves the intended zero set and inside/outside signs, but makes a crease where the two fields are equal. That feature line is generally off the voxel grid. Marching Cubes sees corner samples and emits its standard cell topology; it does not explicitly track that line. As the line crosses cells, the selected topology and vertex positions change, producing teeth. Kobbelt et al. describe severe aliasing at sharp features in sampled volumes; Extended Marching Cubes adds feature-sensitive handling. Botsch and Kobbelt likewise show that poor alignment between samples and features causes aliasing. [Kobbelt et al., *Feature Sensitive Surface Extraction from Volume Data*](https://people.eecs.berkeley.edu/~jrs/meshpapers/KBSS.pdf), [Botsch & Kobbelt, *Resampling Feature and Blend Regions…*](https://onlinelibrary.wiley.com/doi/10.1111/1467-8659.00533)
MC’s basic edge-root placement linearly interpolates the two endpoint densities. A hard max can switch which input field controls the value partway along an edge, so the field there is piecewise smooth rather than linear. The interpolated root can miss the actual zero crossing. VoxelForge has a midpoint re-query for some LOD0 edge roots, but that only improves selected edges; it does not track an off-grid crease through cells. [Mesher interpolation](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Source/VoxelForge/Private/VoxelMarchingCubesMesher.cpp:1721>)
The max field is also not generally a true Euclidean SDF near the crease. For two perpendicular half-spaces, at a point equally outside both, `max(d1,d2)` reports distance \(q\), while the distance to their shared corner is \(\sqrt{2}q\). Its gradient changes discontinuously at equal distances. Near-tangent surfaces make the seam especially sensitive: a small field or sampling error can move the intersection substantially. This is consistent with the known loss of exact distance properties under CSG max/min operations. [Bálint, Valasek & Gergó, *Operations on Signed Distance Function Estimates*](https://www.cad-journal.net/files/vol_20/CAD_20%286%29_2023_1154-1174.pdf)
The L48 evidence implicates the cap but does not prove it was the only cause: the rounded-cap trial reduced visible tooth height yet worsened the whole-surface gate. The source currently has a hard floor clamp inside the cavern graph and another post-pass cap after passages and stamps. [Cavern graph and cap](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:6006>) [Post-pass order](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:1787>)
## Fillet sizing
There is no universal finite radius that guarantees no aliasing for every grid phase, intersection angle, and field. The \(2h\) minimum and \(3h\) preferred values are practical sampling targets; they follow the same need for feature-sensitive treatment described in the meshing literature. A zero-radius hard crease is unresolved at every finite grid spacing. [CGAL’s isosurfacing documentation](https://cgal.github.io/9465/doc/Isosurfacing_3/index.html) also notes that standard MC does not preserve sharp features.
| Mesh step | Spacing \(h\) | Minimum \(R=2h\) | Preferred \(R=3h\) |
|---|---:|---:|---:|
| 1 voxel | 0.25 m | 2 voxels / 0.5 m | 3 / 0.75 m |
| 2 voxels | 0.5 m | 4 / 1 m | 6 / 1.5 m |
| 4 voxels | 1 m | 8 / 2 m | 12 / 3 m |
| 8 voxels | 2 m | 16 / 4 m | 24 / 6 m |
Treat smooth-max parameters as **field-space widths**, not geometric radii. Quilez presents several polynomial, exponential, and other smooth-min variants; their transition parameters do not produce identical fillets. [Quilez, *Modeling with Distance Functions*](https://iquilezles.org/articles/distfunctions/), [Quilez, *Smooth Minimum*](https://iquilezles.org/articles/smin/)
For the current VoxelForge formula, `SmoothMinDistance` uses a cubic \(H^3 W/6\) correction. In a local cross-section of two perpendicular unit-distance planes, its minimum radius of curvature is about \(W/(2\sqrt{2})\). The landmark’s `smoothWidthMicrometres` is 0.30 m, or 1.2 base voxels, which corresponds to only about **0.42 voxel** of radius in that simplified case. Reaching a 2-voxel radius would take \(W \approx 5.7\) voxels at LOD0; the conversion changes with intersection angle and field gradients. [Smooth-max formula](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:5717>) [Landmark width](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Source/StreamBenchmarkHeadless.cpp:480>)
## Composition order
Compose the bore and floor into one void SDF first, with relief incorporated into the intended surface and tapered as needed at the junction. Carve that void from the host field, then apply passages and stamps. Give later stamps floor-aware bounds or a smooth floor constraint in their own field. A final hard clamp slices through the already-composed shapes and creates another crease. Moving the clamp earlier without constraining later carves can reopen the floor; the floor belongs in the shape definitions, not in a trailing repair pass.
## Alternatives and cost
**Dual Contouring** uses edge intersection points and normals (Hermite data) to place cell vertices with a quadratic error function, which can represent sharp features away from grid edges. **Manifold Dual Contouring** adds topology-preserving clustering and manifold guarantees. These methods require different vertex/topology handling, plus work for attributes, tile borders, and LOD transitions; they are not a small change to the MC triangle table. [Ju et al., *Dual Contouring of Hermite Data*](https://dl.acm.org/doi/10.1145/566654.566586), [Schaefer, Ju & Warren, *Manifold Dual Contouring*](https://doi.org/10.1109/TVCG.2007.1012)
VoxelForge’s earlier sharp-feature experiments found LOD-transition failures for both hybrid and DC approaches. The first production hybrid cost 5.6–6.7× MC on tagged sharp fixtures; a later feature-aware MC vertex snap cost 1.17–1.27× there. That snap handles tagged planar features, so a curved bore/floor seam needs its own feature description and root placement logic. [M2 report](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM2/REPORT.md:261>)
## How to check the change
Run the existing whole-surface audit over the same corridor and chamber, including the wall-foot region and floor profile; ideally sweep grid phase as well as checking the existing alignment. The target is for the connected wall-foot hot clusters, flagged area, and severe-edge density to shrink substantially and approach the native control. Keep floor ripple and adjacent-step checks as cross-checks: the L48 candidate had the same 34.5 mm / 57.6 mm floor profile as its control while the wall-foot clusters worsened. [L48 audit results](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux48/REPORT.md:3>)