fix: signed-overflow UB in VoxelHash made cave placement compiler-dependent; all generators LOD0-8; speed matrix (L60)
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
This commit is contained in:
1 parent
fbae82e024
commit
c0c204ba50
15 files changed
+938
-65
No files matched your search
@@ -0,0 +1,114 @@
|
||||
# VoxelForge R29 — revised self-check
|
||||
|
||||
## Mechanism in the L59 field
|
||||
|
||||
I read the L59 implementation on `wip/l59-open-shaft`. It constructs the shaft and ramp as cavity fields, then applies a support cap. The source gives a specific reason to investigate the support and the touching cavity surfaces; it does not prove which one produced each visible shard.
|
||||
|
||||
The core void is a radial cylinder clipped at the room floor:
|
||||
|
||||
```cpp
|
||||
const double radial = hypot(point[0]-center[0], point[1]-center[1])-radius;
|
||||
const double bottom = floor-point[2];
|
||||
featureVoid = std::max(radial,bottom);
|
||||
```
|
||||
|
||||
`wip/l59-open-shaft:Standalone/Core/src/ShapeWorldInternal.h:7340–7346`
|
||||
|
||||
The open ramp’s radial tube is centered at 6 m with a 1.5 m bore radius:
|
||||
|
||||
```cpp
|
||||
nearestRadial = abs(shaftRadial-centerlineRadius);
|
||||
tube = nearestRadial-radius;
|
||||
```
|
||||
|
||||
Its vertical corridor runs from each turn’s floor to `floorZ+height`; adjacent turns are combined with a minimum:
|
||||
|
||||
```cpp
|
||||
return max((floorZ-point[2])*openHelixVerticalScale,
|
||||
(point[2]-(floorZ+height))*openHelixVerticalScale);
|
||||
openHelixVerticalSdf = min(corridorSdf(turnA),corridorSdf(turnB));
|
||||
```
|
||||
|
||||
`wip/l59-open-shaft:Standalone/Core/src/ShapeWorldInternal.h:7380–7385, 7410–7417`
|
||||
|
||||
The tube and corridor are intersected with a smooth max. The core and ramp voids are then unioned with a smooth min, followed by one subtraction from the host field:
|
||||
|
||||
```cpp
|
||||
featureVoid = SmoothMaxMetres(tube,openHelixVerticalSdf,width);
|
||||
caveVoid = SmoothMinMetres(caveVoid,featureVoid,...);
|
||||
composed = SmoothMaxMetres(hostDistance,-caveVoid,0.0);
|
||||
```
|
||||
|
||||
`wip/l59-open-shaft:Standalone/Core/src/ShapeWorldInternal.h:7522–7524, 7533–7541, 7547–7550`
|
||||
|
||||
The geometry report gives a 4.5 m core radius, 6 m ramp centerline, 3 m ramp width, and 1 m support depth. Thus, at the inner edge, the core’s radial zero is `r−4.5`; the ramp tube’s inner zero is `6−r−1.5 = 4.5−r`. Their zero surfaces coincide at 4.5 m with opposite radial gradients. The code smooths the ramp intersection and cavity union, but the tracked L59 report does not record the actual smooth or union widths. I can’t establish that the live edge used a hard intersection; that depends on those values.
|
||||
|
||||
There is a more concrete issue in the support field. Its vertical terms are:
|
||||
|
||||
```cpp
|
||||
const double vertical = max((floorZ-point[2])*scale,
|
||||
(point[2]-(floorZ-supportDepth))*scale);
|
||||
return max(nearestRadial-radius,vertical);
|
||||
...
|
||||
composed = min(composed,latticeFloorSupportMinimum);
|
||||
```
|
||||
|
||||
`wip/l59-open-shaft:Standalone/Core/src/ShapeWorldInternal.h:7502–7515, 7551–7555`
|
||||
|
||||
At mid-depth below the floor, both vertical terms are positive. With this field’s sign convention—host rock is `-32 m`, and cavity interior is positive—the cap therefore cannot force the nominal support volume solid. It may leave rock solid where the host already does so, but it cannot restore solid under an overlapping cavity. This is my strongest code-specific suspect, though the source alone cannot prove it caused the photographed shards.
|
||||
|
||||
The nominal 1 m depth is four LOD0 cell intervals, so simple under-sampling is a weaker explanation at the captured LOD. The free edge has no explicit bullnose radius. A hard or too-narrow crease remains possible if the configured widths are zero or small. Relief noise is unlikely on this path: the open-helix branch returns before the legacy edge relief code (`ShapeWorldInternal.h:7187–7191, 7249–7255`).
|
||||
|
||||
The geometry and reported route measurements are in `wip/l59-open-shaft:Standalone/Research/WorldAssemblerM3/Linux59/REPORT.md:5–7`.
|
||||
|
||||
## Construction and dimensions
|
||||
|
||||
Use the 25 cm LOD0 spacing as the baseline. The practical minimum `R=2h` and preferred `R=3h` are sampling targets, not guarantees for every field gradient or grid phase. For VoxelForge’s cubic smooth-min/max, `W≈2√2·R` applies to a local cross-section of perpendicular unit-gradient planes; the ramp’s coincident radial surfaces need slice validation. See `Research16/REPORT.md:20–31`.
|
||||
|
||||
The L59 owner uses 25 cm Core voxels, 32 cells at full resolution, two full-resolution LOD levels, and 16 cells per coarse tile. Applying the mesher’s `extent=32<<LOD` and cell-count rule gives these normal steps (`VoxelForgeCore.cpp:2058, 2121–2122`; `owner_world.json:1`):
|
||||
|
||||
| LOD | Step `h` | Current 1 m depth in steps | Minimum `R=2h` | `W≈2√2R` | Full two-sided bullnose thickness `T≥2R` |
|
||||
|---:|---:|---:|---:|---:|---:|
|
||||
| 0 | 0.25 m | 4 | 0.5 m | 1.41 m | 1 m |
|
||||
| 1 | 0.5 m | 2 | 1 m | 2.83 m | 2 m |
|
||||
| 2 | 2 m | 0.5 | 4 m | 11.31 m | 8 m |
|
||||
| 3 | 4 m | 0.25 | 8 m | 22.63 m | 16 m |
|
||||
| 4 | 8 m | 0.125 | 16 m | 45.25 m | 32 m |
|
||||
| 5 | 16 m | 0.0625 | 32 m | 90.51 m | 64 m |
|
||||
| 6 | 32 m | 0.03125 | 64 m | 181.02 m | 128 m |
|
||||
| 7 | 64 m | 0.015625 | 128 m | 362.04 m | 256 m |
|
||||
| 8 | 128 m | 0.0078125 | 256 m | 724.08 m | 512 m |
|
||||
|
||||
A basic two-interval slab needs `T≥2h`; roundovers on both top and underside require `T≥2R=4h`. The table shows the latter. The current 1 m support is four intervals at LOD0, two at LOD1, and only half a cell at LOD2.
|
||||
|
||||
**Near-LOD proposal:** give the open edge an explicit 0.5 m geometric bullnose (`R=2h` at LOD0), with `W≈1.41 m`. Set support depth to **1.5 m**: that is six LOD0 intervals, enough for two 0.5 m roundovers and a 0.5 m web. Build the support as negative solid in its intended volume; for the vertical band, the inside terms should be `(z-floorZ)` and `(floorZ-supportDepth-z)` before taking their maximum.
|
||||
|
||||
Keep the bullnose below the walk-floor plane and into the open-core side, leaving the floor edge at `r=4.5 m`. The 6 m route centerline then remains 1.5 m from that edge, and the 3 m radial tread remains `r=4.5–7.5 m`. A smooth-max width is a field-space parameter, so `W<3 m` alone does not prove that the 3 m walking surface survives; the zero contour must be checked in slices. If the finished floor edge moves into the tread, this construction fails the stated route margin.
|
||||
|
||||
At LOD1, the normal 0.5 m step makes a 0.5 m radius only one interval. I would refine ramp-intersecting LOD1 tiles to the 0.25 m Core step, keeping the same bullnose and support geometry. The current refinement in `VoxelForgeCore.cpp:2124–2149` applies to a different feature type; it does not show that resolved shaft-ramp edges already receive this treatment.
|
||||
|
||||
With the top floor unchanged, the reported maximum grade stays 10.028°, below 15°. Thickening only downward leaves the measured 2.20 m headroom unchanged. At 5 m pitch, a 1.5 m support leaves **3.5 m** from the lower floor to the next tread’s underside, so it does not intrude into the 2.20 m clearance.
|
||||
|
||||
## Far LOD and seams
|
||||
|
||||
The LOD numbers in the actual L59 fixture are coarser than “0.5–2 m at LOD2–8”: LOD1 is 0.5 m, LOD2 is 2 m, and LOD3–8 run from 4 m to 128 m.
|
||||
|
||||
At LOD2, a compliant bullnose would need `R=4 m`, `W≈11.31 m`, and `T≥8 m`. That exceeds the 3 m tread width and 5 m pitch. **Do not thicken the ledge.** My concrete proxy is:
|
||||
|
||||
- LOD0–1: the rounded helix ledge, with ramp tiles sampled at 0.25 m.
|
||||
- LOD2–3: remove the helical ledge and support; retain a smooth cylindrical core subtraction. Its 9 m diameter spans 4.5 LOD2 steps and 2.25 LOD3 steps.
|
||||
- LOD4–8: fade the local core opening into the surrounding host field. At LOD4 its 9 m diameter is only about 1.1 steps.
|
||||
|
||||
A field switch alone does **not** establish closed seams. The regular LOD1-to-LOD2 sampling ratio is 4:1; local LOD1 refinement makes it 8:1 at this feature. Both sides need a shared LOD morph evaluated at the same world positions, plus transition cells or a verified skirt stitch for that ratio. The owner requests skirts, but the branch has no L59 captures above LOD0 to demonstrate that this ledge-to-cylinder or cylinder-to-host transition stays closed. The far-LOD proposal is therefore a specific representation plan, not a proven seam result.
|
||||
|
||||
## Audit and slice plan
|
||||
|
||||
The L59 audit excluded the shaft-core room (`AuditLatticeSurfaceL59.py:82–91`) and set a 0.25 m corridor margin (`:229–248`). Its bounds and corridor test expand by that margin (`:159–199`). Shard triangles protruding farther into the core fall outside that ROI.
|
||||
|
||||
Extend an edge-focused ROI along the full helix, including the free edge and an apron on both the core and tread sides. At each LOD, use an edge band of at least `max(1 m, 4h, W_edge+W_union)` from the nominal edge; include the full floor, support underside, and headroom in the vertical bounds. Add edge-specific shard, normal-discontinuity, and open-boundary checks instead of relying only on the corridor’s broad surface score.
|
||||
|
||||
Keep the original L59 LOD0 mesh as a negative control: its free edge must fail the expanded edge checks; the repaired edge must pass; retain a plain-native pass control. Slice the analytic field radially through the edge at several azimuths and turn phases, then unwrap the full four-turn edge. Check the 0.5 m bullnose and 1.5 m support at sub-voxel resolution, including half-cell grid offsets. Recheck the 883 route stations and the reported capsule, support, and headroom samples, with gates of grade ≤15°, headroom ≥2.2 m, and route-centerline distance to the finished edge ≥1.5 m. Inspect LOD1/2 and LOD3/4 transition boundaries separately.
|
||||
|
||||
## Assumptions and skipped evidence
|
||||
|
||||
The tracked L59 report contains the visual diagnosis, but the branch’s `Linux59` directory does not include the resolved-layout JSON or exported `.vfmesh`. The capture script explicitly exports `--max-level=0` (`CaptureNativeLatticeL59.py:78–85`). I therefore do not know the recorded smooth and union widths, and I did not inspect triangle normals or re-view the JPEG pixels. Those gaps prevent me from proving which field term made the observed shards. I did not run scripts, tests, builds, or binaries, and made no source edits.
|
||||
@@ -0,0 +1,78 @@
|
||||
# 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.
|
||||
Reference in new issue
Block a user