VoxelHash::Cell/Pair, legacy Cellular3D and the shared Core cellular hash added 0x7FFFFFFF to a signed int32 before casting to uint32; overflow is undefined, so Clang and GCC placed cave passage 1 differently (first differing sample at LOD1 tile (0,64,-512)). The bias is now done in unsigned arithmetic, in both the standalone copy and the Unreal plugin header (Source/VoxelForge/Public/VoxelCaveMorphology.h). Native caves, motifs and lattice now stream LOD0-8 with skirts and cross-level transitions. New verify.py --speed-matrix runs every generator on one asserted-identical view (5 interleaved runs): motifs 1.33, profiles 1.30-1.32, caves 1.41, natural SW 1.67, lattice 1.70, FI 4.93 s whole view. fast/medium/full PASS, Clang/GCC peer hashes equal. Research R29 (open-edge ledge) and R30 (compiler-divergence suspects). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
78 lines
6.8 KiB
Markdown
78 lines
6.8 KiB
Markdown
# Research29 — L59 open shaft rim
|
||
|
||
## Mechanism
|
||
|
||
The L59 dimensions make the ramp’s inner boundary exactly coincide with the core boundary: `6.0 m` centerline radius minus `1.5 m` passage radius equals the `4.5 m` core radius. The ramp has a `1.0 m` support depth and a `5.0 m` pitch. ([Linux59 report](https://example.invalid) records these dimensions; `Standalone/Research/WorldAssemblerM3/Linux59/REPORT.md:5`.)
|
||
|
||
The core void is a hard intersection:
|
||
|
||
```cpp
|
||
radial = hypot(dx, dy) - radius;
|
||
bottom = floor - point[2];
|
||
featureVoid = max(radial, bottom);
|
||
```
|
||
|
||
`wip/l59-open-shaft:Standalone/Core/src/ShapeWorldInternal.h:7340–47`
|
||
|
||
The ramp void is an annular tube intersected with the floor/ceiling interval. The interval uses a hard `max`, then the tube and interval use cubic smooth-max:
|
||
|
||
```cpp
|
||
corridorSdf = max((floorZ-point[2])*scale,
|
||
(point[2]-(floorZ+height))*scale);
|
||
featureVoid = SmoothMaxMetres(tube, openHelixVerticalSdf, width);
|
||
```
|
||
|
||
`ShapeWorldInternal.h:7410–17, 7522–25`. Core and ramp voids are then combined by smooth-min, falling back from `unionWidth` to `smoothWidth`, before subtraction from constant host rock: `ShapeWorldInternal.h:7532–50`.
|
||
|
||
The leading suspect is the **coincident, oppositely directed zero surfaces** at the core/ramp contact. With zero or insufficient union width, the touching voids form a sharp or pinched seam. Marching Cubes samples that off-grid feature with its ordinary cell topology; the resulting aliasing is consistent with the torn shards. Kobbelt et al. describe severe alias artifacts at sharp features in regular-grid surface extraction and explain that grid refinement alone does not resolve the normal error ([paper](https://people.eecs.berkeley.edu/~jrs/meshpapers/KBSS.pdf)). The ramp floor/tube intersection is smooth-max blended, but its actual width and the feature-union width are absent from the tracked L59 report.
|
||
|
||
There is also a likely support-field defect. The open-helix support uses:
|
||
|
||
```cpp
|
||
vertical = max((floorZ-point[2])*scale,
|
||
(point[2]-(floorZ-supportDepth))*scale);
|
||
supportSdf = max(nearestRadial-radius, vertical);
|
||
composed = min(composed, latticeFloorSupportMinimum);
|
||
```
|
||
|
||
`ShapeWorldInternal.h:7497–15, 7551–55`
|
||
|
||
With VoxelForge’s negative-solid, positive-air convention, this vertical expression is nonnegative everywhere; it is positive inside the intended below-floor slab. The final `min` therefore cannot add negative solid there. A negative-inside support slab would reverse both vertical terms. This is a high-confidence sign concern from the equations, but I cannot isolate its visual effect without field samples. The hard support cap can also distort field values after the smooth feature union.
|
||
|
||
The reported `1 m` support is four LOD0 cell steps at `0.25 m`, so support thickness alone is unlikely to explain the LOD0 capture. It is only two steps at `0.5 m` and falls below one cell at a `2 m` step. Relief noise is unlikely to be the cause: the open-shaft path bypasses the legacy cap path, where the noise evaluation lives (`ShapeWorldInternal.h:7187–91, 7249–55`).
|
||
|
||
## Construction and numbers
|
||
|
||
Build one continuous core-plus-ramp void, smooth-union its components, then subtract that void from the host once. Encode the ledge floor in the void definition and remove the post-union support cap; preserve the support as negative solid in the composed field. Verify that smoothing keeps the intended `4.5 m` core opening.
|
||
|
||
For the current cubic smooth-max, Research16 estimates a local fillet radius `R ≈ W/(2√2)` for perpendicular unit-gradient fields (`Research16/REPORT.md:29–31`). Applied as a sizing guide:
|
||
|
||
| Mesh step `h` | Minimum bullnose `R=2h` | Approx. width `W=2√2R` | Slab thickness `T≥2R`* |
|
||
|---:|---:|---:|---:|
|
||
| 0.25 m | 0.50 m | 1.41 m | 1 m |
|
||
| 0.50 m | 1.00 m | 2.83 m | 2 m |
|
||
| 2.00 m | 4.00 m | 11.31 m | 8 m |
|
||
|
||
\*For a bullnose that rounds both the top and underside. A preferred `R=3h` increases the required width and thickness by 50%. These are sampling targets, not guarantees; measure the composed field because its gradients and intersection angles vary.
|
||
|
||
At LOD0, the existing `1 m` support only meets the minimum two-sided bullnose thickness, with no margin. A `0.75 m` radius is a safer preferred LOD0 target and calls for at least `1.5 m` of slab.
|
||
|
||
## Far LODs
|
||
|
||
The L59 capture command forces `--max-level=0` (`CaptureNativeLatticeL59.py:78–85`), so it provides no evidence for coarser meshes. With the owner defaults (`0.25 m` Core voxels, `full_res_clip_levels=2`, `coarse_tile_cells=16`) and the mesher’s extent/cell calculation (`VoxelForgeCore.cpp:2121–22`), nominal steps are `0.25 m` at LOD0, `0.5 m` at LOD1, then `2, 4, 8, 16, 32, 64, 128 m` at LOD2–8. The ramp is a resolved cavern edge; the separate fine-resolution override checks type-4 world-assembly shelf features (`VoxelForgeCore.cpp:2124–49`).
|
||
|
||
A fixed `1 m` ledge cannot survive those far steps. Keep the detailed ledge in near LODs, refining ramp tiles where needed. At far LODs, fade it into a broad, rounded wall bump and then out of the silhouette. Do not keep thickening the walkable slab: at LOD2 the two-sided bullnose sizing already asks for an `8 m` slab and an `11.3 m` smooth width against a `3 m` passage.
|
||
|
||
## Audit and slice plan
|
||
|
||
The L59 audit uses a `0.25 m` corridor margin and excludes the shaft-core room from its room ROI (`AuditLatticeSurfaceL59.py:82–91, 159–205, 229–48`). That leaves only a one-voxel allowance for shards protruding into the core. Expand the ROI and its bounds to cover at least a `1 m` band on both sides of each free edge, plus the full `1 m` underside and headroom. Add edge-specific coverage and roughness measurements so the free rim is scored even when its triangles cannot serve as smooth reference terrain.
|
||
|
||
Run the raw L59 mesh as a negative control with `expect=fail`; require the edge defect to be detected. Require the corrected candidate and plain-native control to pass. Include all four turns, both free edges, and the support underside.
|
||
|
||
Proposed slices: sample radial/vertical sections through the core and ledge at quarter-turn intervals and multiple azimuths, at `0.0625 m` increments. Record the core, ramp, support, union, and final density values. Then compare current and corrected LOD0 meshes across half-cell grid phases; inspect LOD1 and LOD2 transitions, followed by the far-LOD bump/fade through LOD8. The existing audit phase option shifts its analytical reference; it does not remesh a shifted grid.
|
||
|
||
## Uncertainty
|
||
|
||
The tracked L59 report does not give the resolved `smoothWidth` or `unionWidth`, and the branch has no raw mesh/audit JSON here to localize the shard triangles. The tangent-seam diagnosis is therefore likely, not proven. The support sign reversal is directly visible in the equations and deserves field-level confirmation.
|
||
|
||
Read-only inspection only; no files were changed and no tests or binaries were run. |