The flagged SW demo's ramp (57 carves + 107 support pillars, visibly ribbed) becomes one cubic-Bezier sweep: closest point by 17-point seed plus 5 Newton steps, a cubic floor profile, a rounded 2.6 m bore, and a hard floor cap applied after unions and relief that only adds support where the field is air. Optional resolved cavern-graph records (one room, one edge) enter canonical identity only when present; their bounds extend World::isTileShapeFree. Reachability passes (L43 control fails), headroom 2.8 m, floor ripple 1.8 mm (L45 ramp control fails at 17.9 mm), shape limits met; demo off: owner hashes identical to L45. fast/medium/full PASS. Research R13 (read-only): continuous SDF sweeps along curves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
44 lines
8.3 KiB
Markdown
44 lines
8.3 KiB
Markdown
## Key recommendations
|
||
|
||
1. **Add one shared curve sweep evaluator** for passage bores, the L45 ramp and R12 graph edges. Evaluate a smooth spline over global arc length, rather than taking a minimum over piecewise-linear capsules or discrete ramp stamps.
|
||
2. **Accelerate the global search with a conservative BVH.** Seed each surviving spline span from its chord projection, refine with a safeguarded solver, and compare all candidates whose bounds could beat the current best. One Newton solve from one seed is not a global closest-point solve.
|
||
3. **Keep the floor cap separate from tube ownership.** Use an explicit floor profile and R3’s floor-near candidate rule for overlapping bends and coils; keep relief and smooth unions away from the floor zero set.
|
||
4. **Use a sphere sweep as the fast, bounded field.** A general framed cross-section sweep is not guaranteed to be a true distance field on tight curves. Use rotation-minimising frames for its orientation, but validate curvature and retain conservative bounds for culling.
|
||
|
||
## Math and exactness
|
||
|
||
Represent the spine as a C1 or preferably C2 cubic spline \(C(s)\), parameterised by arc length \(s\). Interpolate radius \(r(s)\) and floor height \(h(s)\) as explicit route attributes. The round sweep is:
|
||
|
||
\[
|
||
\phi_{\text{tube}}(p)=\min_{s\in[0,L]} \left(\|p-C(s)\|-r(s)\right)
|
||
\]
|
||
|
||
This gives a continuous field with the correct zero set for the union of swept balls. It is exact distance outside that union; inside overlapping spheres it is only a distance bound, as the swept-volume literature cautions. The exact nearest-point equation for a cubic Bezier has degree five; Iñigo Quílez’s compact Bezier distance function is for a quadratic curve, so it is a useful small-case reference, not a complete cubic-tube solution. [IQ’s 2D distance functions](https://iquilezles.org/articles/distfunctions2d/), [point-to-NURBS distance paper](https://doi.org/10.1016/j.cad.2008.06.008), [swept-volume SDF analysis](https://doi.org/10.1145/3610548.3618196)
|
||
|
||
For the floor, define a separate cap from the selected route branch. For a single-valued floor graph \(h(x,y)\), a useful field is \((h(x,y)-z)/\sqrt{1+\lambda^2}\), where \(\lambda\) bounds the floor slope. Its zero set is the authored floor; it is exact distance for a planar floor and a conservative bound otherwise. Combine the tube and cap as an intersection, then carve using Core’s positive-air convention. Do not smooth-blend the floor edge or apply wall relief at the floor: either can shift the walk surface. The cave-network paper uses this slope-bounded height-field form and notes that arbitrary cross-section sweeps along high-curvature curves do not generally yield a continuous SDF. [Paris et al., *Synthesizing Geologically Coherent Cave Networks*](https://diglib.eg.org/items/a4e7985c-af52-4b55-bd1a-eeeff6c47422)
|
||
|
||
A circular sweep needs no frame. For an asymmetric cross-section, precompute a rotation-minimising frame along the arc-length table; the double-reflection method is a practical low-cost choice and avoids the Frenet frame’s flips at inflections. [Wang et al., *Computation of Rotation Minimizing Frames*](https://doi.org/10.1145/1330511.1330513)
|
||
|
||
## Cost and culling
|
||
|
||
Build an arc-length lookup table, spline-span bounds and optional frames once when resolving the layout. At sample time, traverse a BVH ordered by the conservative lower bound `distance(point, spanBounds) - maxRadius`. The current passage BVH already uses the analogous `AABB distance - maximum radius` bound; spline bounds must include each cubic span’s control hull, not just its endpoints.
|
||
|
||
Use the chord projection to seed a bracketed Newton or similar local solve on each promising span, include span endpoints, and retain the lowest result globally. A single seed can converge to the wrong local minimum near a bend or helix. For exact refinement, isolate all roots of the quintic stationary equation on the few surviving spans; variable radius adds a derivative term and makes the solve more costly. [The NURBS distance method](https://doi.org/10.1016/j.cad.2008.06.008) is a relevant example of clipping candidate regions before numerical refinement.
|
||
|
||
The exact minimum of 1-Lipschitz sphere fields is itself 1-Lipschitz. An *approximate* solver’s sampled value is not automatically a safe culling bound: it may overestimate the minimum. Keep a certified lower bound from the BVH/subdivision search for skip decisions, or stop with a known error gap and subtract that error. Report node visits, candidate spans, refinements and bound gaps per sample; a 256-span curve has about eight BVH levels before pruning, but tight overlapping coils may leave many candidates alive. Unreal’s spline API exposes closest-key queries, distance-along-spline queries and a reparameterisation table, matching the useful precomputed lookup pattern for game workloads. [Epic’s `USplineComponent` API](https://dev.epicgames.com/documentation/unreal-engine/API/Runtime/Engine/USplineComponent)
|
||
|
||
## Floor ownership and code fit
|
||
|
||
For overlapping coils, do **not** use the closest 3D centerline to choose the floor. R3 recommends considering only floor candidates within half a voxel (0.125 m) vertically and inside the bore radius, then choosing the nearest floor point with a stable ID tie-break. Its synthetic helix showed roughly 3.37 m peak-to-peak error for closest-centerline ownership versus 0.029 m for floor-near ownership; it did not prove the rule fixes the real L38 ripple, so the real FI Style 2 route still needs measurement. [R3 floor ownership](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Research3/REPORT.md:5>) · [R12 graph-field recommendation](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Research12/REPORT.md:13>)
|
||
|
||
Put a shared evaluator in a Core internal sweep helper, with a resolved curve record carrying stable ID, cubic controls, arc-length attributes, floor/radius profiles and conservative bounds.
|
||
|
||
- **Passages:** adapt [`ApplyResolvedStratePassageCarves`](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:906>) to call it; retain bridge, mouth and support policy around the shared geometry query. Update [`BuildPassageNearestNode`](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:3349>) and its lower bounds for spline hulls.
|
||
- **L45 ramp:** replace the repeated ramp carve/support requests in [`MakeLandmarkChamberDemoRequests`](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Source/StreamBenchmarkHeadless.cpp:113>) with one floor-capped curve record. Route its evaluation through the shared composition/stamp path in [`ShapeWorldInternal.h`](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:1781>).
|
||
- **R12 graph edges:** store the same curve/floor data on each resolved edge and evaluate it from [`BindResolvedStratumFields`](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:286>); include blend, relief and floor-support reach in tile and shape-free bounds.
|
||
|
||
## Failure modes and suggested checks
|
||
|
||
The main risks are missed local minima, spline overshoot, curvature causing a swept cross-section to fold or overlap, variable radius changing the floor, frame flips, and hard floor-owner changes across nearby branches. Validate radius slope and curvature; use monotone floor interpolation where route height must not overshoot. Sphere-swept canal surfaces also become degenerate when radius changes as fast as the spine advances. [Canal surface conditions](https://mathworld.wolfram.com/CanalSurface.html)
|
||
|
||
For a zero-relief tight S-bend with nonuniform knot spacing, sample the floor crossing every 0.125 m of arc length against its analytic \(h(s)\): the analytic ripple should be 0, with measured error only from the solver/voxel tolerance and no peak at the knot spacing. Then run an overlapping helix with floor-near ownership, and the real L35/L36/L45 controls. Track floor peak-to-peak error, the 0.5–8 m ripple spectrum, culling false negatives, solver gaps and candidate counts. L35 and L36 documented the passage wall/floor beats, while L45 records the 57-carve/107-support ramp ribs. [L35](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux35/REPORT.md>) · [L36](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux36/REPORT.md>) · [L45](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux45/REPORT.md>) |