Files
VoxelForge/Standalone/Research/WorldAssemblerM3/Research21/REPORT.md
T
Fr0zkaandClaude Opus 5.5 408c14baff perf(mesher): shared proof-driven sampling skips certified-uniform blocks (L52); FI 7.1 -> 5.6 s; R21
The shared marching-cubes mesher applies its 8-cell block proofs at step 2 for standalone shape contexts
and skips density-grid fills outside certified-uniform blocks (plus a one-sample normal halo); mixed and
unknown blocks still sample exactly. FI certified-air boxes 1,959 -> 14,119; FI LOD1 samples -63%. FI whole
view 7.08 -> 5.61 s (-21%), moving p50 about -33%; SW unchanged. Geometry hashes identical (no version
bump); proof audit 36.9 M samples, 0 violations, Clang and GCC. Source stamp now covers the standalone
mesher copy. Research R21 (deepened): native Core cave generator design.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
2026-10-24 23:53:43 +02:00

129 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# VoxelForge R21 — native Core cave generator
**Recommendation:** add `caves` as a versioned, metre-native Core field. Plan its required arrival-to-departure spine before optional rooms and branches. Build room and tunnel floors into the same rounded void fields as their walls, then use conservative intervals from the first slice.
**Scope:** read-only research. No source changes, scripts, tests, builds, or binaries were run.
## 1. Legacy cave generation
`UVoxelGenerator::GetDensityWithParams` is the scalar `TunnelNetwork` field. It starts with solid density, scales Z, warps the room/tunnel query, carves the room graph and shafts, then applies roughness and terrain details, worms, boundary seals, passages, and the XY edge seal. Its internal convention is positive rock; it negates for Marching Cubes. The canonical stack, `BuildTunnelNetworkStack`, has the same stages and selects a fused evaluator; fusion removes operator-dispatch overhead, not the feature and noise work. [GetDensityWithParams](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:4041>) · [BuildTunnelNetworkStack](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelDensityOpStack.cpp:9422>)
| Piece | What it computes and per-sample work | Range and route notes |
|---|---|---|
| **Room and tunnel graph** — `BuildChunkCache`, `EvaluateSDFCached` | `BuildChunkCache` hashes rooms and bakes topology, floors, and tunnel chains once per cache window, not once per voxel. Room-neighbor selection is O(N²) in that build, followed by connection, player-fit, and chain work. At a sample, each active room evaluates one primitive SDF; each eligible tunnel can evaluate up to 32 tapered-capsule segments. Each room-floor join adds one capsule SDF. Cache bounds use a wide collect region to keep graph decisions stable across windows. [BuildChunkCache](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelCaveMorphology.cpp:7203>) · [hash-placed rooms](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelCaveMorphology.cpp:7430>) · [EvaluateSDFCached](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelCaveMorphology.cpp:8990>) | Each graph feature has finite bounds when parameters are finite; smooth-union reach must be included. Per-room floor relief costs up to two noise octaves on a relief-column cache miss. Room and feature candidates are distance-culled, but the LOD0 path does not use the spatial index, so per-sample work can still scale with traversed candidates. |
| **Primitive SDFs and joins** | Sphere: `|p-c|-r`; ellipsoid: `(sqrt(Σ((p-c)/r)²)-1)·mean(r)`; capsule: distance to the clamped segment minus radius; rounded box: `length(max(q,0))+min(max(q),0)-round`. The ellipsoid is a pseudo-distance: its zero set is useful, but values are not exact Euclidean distances. Smooth union is `min(a,b)-h³k/6`, `h=max(k-|a-b|,0)/k`; smooth intersection is the dual. [VoxelCaveMorphology.h](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelCaveMorphology.h:78>) · [smooth min/max](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelCaveMorphology.h:166>) | These primitives admit conservative box bounds. The smooth-min correction is bounded by `k/6`; include that margin in feature bounds and intervals. |
| **Cave warp** | Three independent Perlin channels are evaluated per sample by `Perlin3D_x3`. They perturb the room/tunnel query coordinates only; pits, details, and hash-placed features use the unwarped frame. The code comment says “two octaves,” but the implementation is three channels, not a two-octave stack. [warp](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:4129>) | Perlin is proven within ±1.5. With `VOXEL_NOISE_SCALE=1.25`, the per-axis displacement bound is `1.875 × abs(CaveWarpStrength)` old voxels. Default strength 16 is a 2 m authored value at the old 0.125 m voxel, but requires up to 3.75 m of conservative margin per axis. |
| **Pits and chimneys, then SDF carve** | Each active shaft uses one XY square root and a finite tapered vertical profile; it is smooth-minned into the graph. The carve then converts the graph SDF to density: within the blend band, `f=smoothstep(clamp((k-SDF)/max(2k,1),0,1))`, and `Density -= 2·BaseDensity·f`. This is a density field, not a metre-valued signed distance. [pit/chimney SDFs](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:4427>) · [carve conversion](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:4499>) | Shafts have finite support and bounded blend correction. Density amplitude is bounded for finite parameters, but the conversion does not preserve metric SDF magnitude. |
| **Wall roughness** | Runs near the surface. At LOD0, fBM or ridged uses 3 main plus 2 fine Perlin octaves; Mixed doubles those to 10. Optional domain warp adds 3 Perlin evaluations. Cellular roughness makes two Cellular3D calls, each probing a 3×3×3 cell neighborhood. Roughness is faded within `2×SurfaceRoughness`; in known cave air it is clamped so it cannot fill rock back in. [roughness](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:4558>) | Finite band and amplitude for valid parameters; use proven Perlin/Cellular bounds. The effective octave counts vary with LOD, so the legacy field is not LOD-invariant. |
| **Terrace, lines, ribs, overhang, cliff, scallop** | Terrace adds **two extra SDF evaluations** at Z±1 and optional two-octave noise. Layer lines and ribs use deterministic sine, with no noise or extra SDF. Overhang uses two Perlin octaves. Cliff uses one Perlin call; despite the comment describing finite differences, the implementation uses a noise proxy. Scallop uses one Cellular3D call. [terraces](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:4729>) · [lines and ribs](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:4826>) · [overhang](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:4885>) · [cliff](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:4921>) · [scallop](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:4965>) | All have finite support fades and bounded noise for finite parameters. Per-room overrides need per-feature bounds; the generic classifier conservatively gives up in some override cases. |
| **Arches, columns, domes, pinches, floor bias** | Up to 3 capsule SDFs for arches; one XY square root per active column; up to 2 ellipsoid pseudo-SDFs for domes; up to 3 quadratic pinch tests and one square root per active pinch. Floor bias adds a quadratic density offset without noise or SDF work. [arches](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:5001>) · [columns](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:5030>) · [domes](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:5063>) · [pinches](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:5128>) · [floor bias](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:5162>) | Finite if each placement and influence envelope is included in the bounds. These stamps can still change final walkability. |
| **Worm tunnels** | `N1=abs(Perlin(p)×1.25)`. If `N1` is below threshold, evaluate `N2=abs(Perlin(p+(137,259,431))×1.25)`; carve when `W=N1+N2<T` by `Density -= (1-W/T)·WormStrength·NetworkMask`. Thus the common cost is 1 Perlin, rising to 2 for eligible samples. [worm field](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelWormField.cpp:12>) · [worm mask and carve](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:5216>) | Carve amplitude is bounded by `WormStrength`. With `WormNetworkRange>0`, it is confined to a network-local fade, if the network distance bound is conservative. Range 0 gives global support and can create disconnected “confetti”; it is unsuitable for tight tile proofs or route guarantees. |
| **Boundary, passages, edge seal** | Structural operations run after worm carving. Their cost is parameter- and feature-dependent; they add no cave SDF or Perlin work, but are part of the final field and proof. [structural tail](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:5278>) | Their bands, passage mouths, and supports must be included in any native classification proof. |
The visual strengths are the contrast between chambers and corridors, tapered winding edges, soft room/tunnel joins, floor relief, and localized wall detail. The largest legacy costs are variable room/edge candidate walks, repeated square roots and capsule distances, per-sample noise, plus the two extra SDF probes for terraces. Cache construction also has nontrivial graph and player-fit work. I found no unseeded RNG in these cave paths: room and edge choices use deterministic hashes, and the cache key includes seed, parameter fingerprint, layout, and manager lifetime. However, LOD-dependent noise changes the field, and deterministic geometry is not automatically a safe route.
`bTunnelsFlowTowardOrigin` can create a tree toward the origin, but that origin is `(0,0)`—not the actual surface or inter-strate mouth. The code explicitly notes there is no radial road from those mouths. Length limits and origin connection caps can leave disconnected components; when flow is disabled, disconnected clusters are expected. Local player-fit-point selection is not a final capsule flood-fill from arrival to departure. Tunnel floors are wound for some critical steep edges and may receive broad ledges on eligible noncritical edges, but the default 44° “gentle” threshold exceeds the current 15° route gate. [origin and graph construction](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelCaveMorphology.cpp:7531>) · [local room fit](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelCaveMorphology.cpp:7833>) · [tunnel winding](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelCaveMorphology.cpp:8150>)
### `FStrateGenerationParams` fields
The relevant legacy defaults are: `BaseDensity=8`, `VerticalScale=1`; worm frequency `.015`, horizontal bias `3`, threshold `.06`, strength `10`, and network range `64`; room spacing `128`, density `.35`, radii `16–40`, height ratio `.85`, floor cut `.70–.90`, relief strength `4` at frequency `.015`, mouth rise `0` with blend `8`, origin-room radius `48`; tunnel radii `6–8`, density `.4`, max length `360`, warp strength `24`, horizontal bias `.5`, endpoint Z offset `.25`; SDF blend `4`, cave warp `16` at frequency `.015`, roughness `2` at frequency `.1` using FBM, domain warp `0` at `.03`, and floor bias `4`. Tunnel floor terrace step `1.71` is retained for compatibility but ignored by the active evaluator. See the fields in [FStrateGenerationParams](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelStrateTypes.h:372>).
## 2. Native Core field and route
Core already has resolved graph records, but not a native cave field contract or graph planner. `ResolveResolvedCavernGraphV1` validates and copies supplied records; it does not generate the spine. Current validation requires at least one room and edge and checks local identities, parameters, and bounds, but not global graph connectivity or an arrival-to-departure capsule route. [graph validation](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ResolvedLayoutInternal.h:1145>) · [graph resolver](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ResolvedLayoutInternal.h:1294>)
Use an immutable, versioned `FCaveFieldAdapter` bound once per resolved stratum. Evaluate in metres with Core’s sign convention: **negative solid, positive air**. Store feature coordinates and IDs in the resolved snapshot; key all randomness by world seed, strate ID, recipe version, and stable feature ID. Keep the field value identical at the same physical coordinate across LODs. R6’s bound-field contract also requires finite influence bounds and conservative `solid`, `air`, `mixed`, or `unknown` classification. [R6 contract](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Research6/REPORT.md:22>) · [current adapter kinds](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:136>)
Let `Dhost` be the native stratum field, with negative rock. Define each room or edge’s void field as negative inside its carved space:
```text
d_ellipsoid(p) = (sqrt(Σ((p_i - c_i)/r_i)^2) - 1) · mean(r)
d_floor(p) = F(x,y) - z
d_room_void = smax(d_ellipsoid, d_floor, w_floor)
d_tube(p) = min over baked segments j of (distance(p, segment_j) - r_j(t))
d_edge_void = smax(d_tube, d_floor, w_floor)
d_cave_void = smin over room and edge voids i of d_i, using w_union
D0 = max(Dhost, -d_cave_void)
```
For a sloped floor, use a grade-normalized half-space locally, `(F-z)/sqrt(1+|∇F|²)`, and keep the profile continuous through room/edge portals. Bake curves into deterministic physical-error-bounded polylines during resolve; the current Core demo searches a cubic Bezier with 17 XY samples and up to 5 Newton iterations per query, and repeats a similar search for the floor cap. [current graph evaluation](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:6189>)
Build the cave graph into the stratum field first. Then apply L42’s boundary bands, shared passage carving, and floor-aware stamps in that order. Give stamps and relief route keepouts, and include them in final route and interval checks. Remove the current trailing hard floor cap: it runs after boundary composition, passages, and stamps, reintroducing a hard intersection at the floor. [current composition order](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:1788>) · [L42 boundary rules](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux42/REPORT.md:1>)
### Bounds and feature queries
For every box, evaluate conservative intervals for the full composed field, outward-rounded:
- **Ellipsoid:** per axis, let `δmin` be distance from the box interval to the center and `δmax=max(|lo-c|,|hi-c|)`. Then `qmin/max=sqrt(Σ(δmin/max/r)²)` and `d` lies in `[(qmin-1)·mean(r), (qmax-1)·mean(r)]`.
- **Rounded room box:** apply interval arithmetic to the existing rounded-box formula, including round radius. A coarse result may be `mixed`; never claim more than the interval proves.
- **Swept edge:** bound each baked segment’s distance-to-box and its radius range. Its signed range is `[distance_min-r_max, distance_max-r_min]`; combine segment ranges with `min` for the tube. Subdivide long or highly curved edges at resolve time to tighten bounds.
- **Floor:** for `F∈[Fmin,Fmax]`, relief `δ∈[-A,A]`, and `z∈[zmin,zmax]`, the unnormalized numerator lies in `[Fmin-A-zmax, Fmax+A-zmin]`; multiply by an outward interval of the positive grade-normalization factor. Subdivide boxes at floor-profile spans.
- **Roughness/warp:** expand the SDF interval by proven displacement amplitude. For cave warp, expand the query box by `1.875·strength` on each axis at legacy scale, or use a separately bounded native warp.
- **Smooth CSG:** use the actual monotone smooth-min/max kernel at the interval endpoints (with outward rounding). The smooth correction is at most `width/6`; include all widths in bounds.
A BVH should be built once from the immutable resolved graph: a top-level tree for rooms, edges, shafts, columns, and bounded detail features, plus a segment tree for long edges. Inflate bounds for blend width, relief, warp, support, and the sample halo. Use deterministic median splits on the longest AABB axis, stable-ID tie breaks, and small leaves; sort candidates by stable ID before CSG folding. Reuse the same feature bounds for sample candidate lists, box intervals, and shape-free checks. Today `BuildCavernFeatureTileList` scans the whole graph per tile; the classifier returns mixed/unknown when graph bounds overlap rather than proving the cave field. [feature tile list](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:3740>) · [box classifier](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:4935>)
**`isTileShapeFree` and interval classification prove different things.** The shape-free gate decides whether a tile may use native-only evaluation at all; its conservative bounds must cover every shape dependency, including route, cave records, floor support, passage supports, stamps, and edits. The final-field interval then determines whether a padded tile is wholly air or solid. Any unsupported contributor or nonfinite bound must yield false/unknown and force evaluation. L44’s six LOD0 mismatches came from omitting support-column envelopes from `isTileShapeFree`; the fix bounded the anchor, route center, bore, wall, flare, and vertical span. [current shape-free check](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/VoxelForgeCore.cpp:1410>) · [L44 finding](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux44/REPORT.md:3>)
### Walkable backbone
Follow R12/R18: resolve actual arrival and departure mouths first, then plan a grade-limited spine between those mouths before optional room placement. Put at least one room on the spine, with matching edge portals and floor heights. Route through the usable content band; use broad switchbacks when direct grade is too high. Add Poisson rooms, connect accepted Delaunay neighbors with a deterministic spanning tree, then add only feasible loops and branches. Give each decision a stable feature-keyed seed.
Graph connectivity is only the planning constraint. After adding relief, stamps, passages, and boundary bands, run a capsule-swept reachability proof through the final field from arrival to departure, checking support, headroom, and local grade. Use the current gate as a minimum: 0.34 m radius, 1.76 m capsule height, at least 0.30 m overhead, and grade ≤15°. [R18 planner](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Research18/REPORT.md:1>) · [L46 reachability evidence](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux46/REPORT.md:1>)
Keep the legacy look selectively: varied ellipsoid/rounded-box rooms, tapered winding corridors, smooth junctions, low-amplitude floor relief, and bounded roughness, ribs, scallops, domes, and shafts. Replace the raw global worm field with bounded hash-seeded spline side branches attached to the spine. Keep noisy detail out of the route clearance band. Avoid global implicit noise with unbounded support.
## 3. Proof coverage and cost
For default sparse rooms—about 16 m spacing, 2–5 m room radii, and 0.75–1 m corridor radius after applying the R8 old-voxel conversion—most padded 8 m tiles in a typical underground view should be solid host rock. **Planning estimate, not measured:** about 75% `AllSolid`, 5% `AllAir`, and 20% mixed, with plausible ranges of 65–85%, 0–10%, and 15–30%. These are tile fractions, not volume fractions; the view direction, graph density, and tile halo can shift them. Target under 1% unknown, with zero false proofs.
The L51 comparison sets the scale: FloatingIslands whole-view time improved from 16.736 s to 7.355 s, while SurfaceWorld measured 1.770 s to 1.756 s. Before the fix, 1,075 of 2,370 nonempty FI tiles (45.36%) were all-air, yet loose bounds yielded no whole-tile skips. After interval changes **along with** X8 reuse and far-shell bounds, the run reported 1,959 air boxes, 18,857 mixed, 240 unknown, and 216 whole-tile skips. A separate audit checked 21,504 uniform blocks and 28.6 million samples with zero violations. The 7.36 s result is not an interval-only speedup. [L51 report](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux51/REPORT.md:1>)
A tight BVH and interval-aware field should make sparse caves a **medium-cost** generator: each mixed sample still evaluates local SDF features, but most distant host-rock boxes can skip cave work. A first implementation might land around **1.5–3 s** for the same whole-view scope; about 1 s is a reasonable optimization target, not a demonstrated estimate. The current Core graph demo is too expensive to serve as evidence: it performs repeated Bezier closest-point searches per edge per density sample, scans feature bounds linearly per tile, and does not yet interval-classify graph interiors. Measure whole-view time, first playable ring, graph-build time, candidate counts, feature evaluations, proof verdicts, and memory separately.
## 4. Floor/wall junction
R16’s construction is the right target: make the bore and floor **one void field**, apply its geometric fillet, carve once, then apply only floor-aware stamps. Do not intersect a bore and floor as separate hard fields and repair the seam afterward. Keep native rock beneath the walk plane; any fallback support should be narrow and included in bounds.
At 25 cm LOD0 spacing (`h`), R16 recommends geometric fillet radius `R≥2h=0.5 m`, preferably `R≈3h=0.75 m`. For this cubic smooth-max kernel, the local radius for two perpendicular unit half-spaces is approximately `R≈w/(2√2)`. That means `w≈1.41 m` for the minimum and `w≈2.12 m` for the preferred fillet. L46’s 0.30 m smooth width corresponds to only about 0.106 m, or 0.42 voxel, in that simplified cross-section. [R16 sizing and composition](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Research16/REPORT.md:1>) · [smooth-max kernel](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelCaveMorphology.h:177>) · [L46 demo dimensions](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux46/REPORT.md:1>)
This construction removes the hard, off-grid crease that produced the L47–L48 wall-foot teeth and gives Marching Cubes a smoother field across the junction. It does **not** guarantee alias-free output at every grid phase: R16 explicitly treats `2h–3h` as a practical sampling rule, not a proof. The field must stay LOD-invariant, so do not grow the fillet with LOD; use feature-aware sampling/filtering and audit phase shifts and transitions. L49’s one-void-before-stamps idea is a proposal; there is no validated L49 report in this checkout, and current Core code still runs a trailing floor cap. [L47 wall-foot defect](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux47/REPORT.md:1>) · [L48 whole-surface failure](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux48/REPORT.md:1>) · [current cap order](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:1788>)
## 5. Prior art
- **Minecraft cheese, spaghetti, noodle caves:** Mojang describes large cheese chambers, long winding spaghetti tunnels, and thinner, more claustrophobic noodles. The versioned data is a density expression, not a route graph. For example, cheese combines `4·L² + clamp(.27+C,-1,1) + clamp(1.5-.64·S,0,.5)` from cave-layer, cave-cheese, and sloped-cheese noise. The 1.20.3 spaghetti field uses rarity-scaled noise: `clamp(max(weirdScaled(R,N1), weirdScaled(R,N2))-.0765-.0115·T,-1,1)`. Noodles gate on a vertical range and combine a noise threshold with thickness and ridge terms. These formulas create strong scale families but provide no explicit arrival-to-exit walkability proof. [Mojang’s cave overview](https://www.minecraft.net/de-de/article/caves---cliffs--part-ii-out-today-java) · [1.21.1 overworld density](https://mcasset.cloud/1.21.1/data/minecraft/worldgen/noise_settings/overworld.json) · [1.20.3 cave density functions](https://mcasset.cloud/1.20.3-pre2/data/minecraft/worldgen/density_function/overworld/caves/_all.json)
- **Deep Rock Galactic:** 119 hand-built room templates and 10 biomes are assembled as rooms connected by narrow, winding tunnels; templates are warped, mirrored, or overlapped and receive biome-specific surface noise and debris. The cave seed is quick, but the developers say the full cave is assembled during the Drop Pod descent. Designers play through randomized rooms with different classes and reject layouts that prove unfun or unplayable. That is useful human traversal testing, not a formal capsule proof or a published full-build latency. [Ghost Ship Games, “Below Decks: Cave generation”](https://store.steampowered.com/news/posts/?appgroupname=Deep+Rock+Galactic&appids=548430&enddate=1730296516&feed=steam_community_announcements)
- **No Man’s Sky:** the Foundation update says caves are generated at lower terrain LODs to reduce visual differences at lower detail, alongside smaller features nearer the player and terrain cost/priority changes. This informs LOD consistency and streaming; the notes provide no route proof or directly comparable timing. [Foundation Update](https://www.nomanssky.com/foundation-update/)
- **Astroneer:** layered noise generates terrain and objects on the fly without needing neighboring planet parts or whole-planet load-time generation; cave layers are separate authoring layers. That supports local evaluation but provides no explicit walkability guarantee or comparable cave-generation time. [Unreal Engine interview](https://www.unrealengine.com/spotlights/how-system-era-softworks-leveraged-ue4-to-create-astroneer-s-wonderful-universe)
- **Graph and tunnel papers:** Santamaría-Ibirika et al. use POIs, Voronoi/Delaunay neighborhoods, relationship constraints, and path search; unreachable branches are discarded. Their 2014 evaluation on an Intel i7-950 reports roughly 10.7–11.6 s total, dominated by diagram construction, with the cave-generation phase itself at 52–877 ms. It is useful topology evidence, not a Core performance target. Mark et al. use an L-system room/tunnel skeleton, connect some ends with curl-noise paths, and carve noise-warped metaballs; point spacing no greater than the minimum metaball diameter ensures tunnel connection, but also prevents very tight cracks. Their paper claims a real-time GPU pipeline without a directly comparable latency figure. Paris et al. derive a graph-like karst skeleton from anisotropic shortest paths and geological fields, then build tunnel SDFs with blending and warping; shortest-path plus skeleton construction is reported under a second, nearest-neighbor synthesis up to 3 s, and construction-tree generation a few seconds in the worst case. None of these reported methods supplies the final VoxelForge capsule-clearance proof; that comparison is an inference from the described algorithms. [Santamaría-Ibirika et al.](https://santosgrueiro.com/papers/2014/2014-Santam-Cave.pdf) · [Mark et al.](https://lucris.lub.lu.se/ws/files/6067634/5464988.pdf) · [Paris et al.](https://diglib.cgv.tugraz.at/items/a4e7985c-af52-4b55-bd1a-eeeff6c47422)
## 6. Migration and legacy assets
R8 identifies the legacy owner voxel as 0.125 m; Core defaults to 0.25 m. Convert old spatial values with `metres=n×0.125`; convert frequencies with `cycles/m=oldFrequency/0.125`. Thus the old runtime defaults become: room spacing 16 m, room radii 2–5 m, origin radius 6 m, tunnel radius 0.75–1 m, max tunnel length 45 m, and SDF blend 0.5 m. Worm network range 64 becomes 8 m; roughness 2 becomes 0.25 m. Cave warp strength 16 is 2 m authored, but its proven displacement envelope is larger as described above. [R8 unit rules](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Research8/REPORT.md:1>)
Do not scale density amplitudes such as `BaseDensity`, `WormStrength`, layer depth, or floor bias as lengths. Split old mixed density and spatial parameters into explicit native fields; map only semantics that survive. Preserve `VerticalScale`, probabilities, angles, and noise thresholds as dimensionless settings. Some header comments conflict with the runtime units—for example, the 128-voxel spacing and 360-voxel max length are described there as 32 m and 90 m. Use each world’s captured legacy resolution and layout width, not those comments or current CDO defaults.
Keep old assets working through a versioned `LegacyCaveParamsV1` path with their old reflected values, defaults, evaluator, seed, and captured `CoreVoxelSizeCm`/layout width. Add custom asset-version conversion and redirects/deprecated holding properties; convert DataTable and external CSV/JSON sources too. Keep those assets on the legacy evaluator unless explicitly migrated to the new `caves` recipe. Store recipe/evaluator version in the resolved snapshot and version any new geometry identity. This preserves existing owner assets while making native caves an opt-in migration.
## 7. Verification slices
`verify.py` currently covers SurfaceWorld and FloatingIslands, not `caves`; its L48 whole-surface audit is not wired into the tiers and assumes exactly one room and one edge. The current reachability gate proves arrival-to-chamber only. Generalize the audit and route gate before promoting the graph. [verify.py tiers](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Tools/verify/verify.py:1035>) · [single-room/edge audit](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux48/AuditWholeSurfaceL48.py:143>) · [current reachability gate](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Tools/verify/verify.py:181>)
Estimates below are **post-build** planning estimates. Existing tier baselines are L51: fast 152 s, medium 471 s, full 1,062 s; the L48 whole-surface audit took 162 s. [L51 timings](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux51/REPORT.md:1>) · [L48 timings](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux48/REPORT.md:1>)
| Slice | Exact verification to add | Estimated pass time |
|---|---|---:|
| **1. One mandatory spine, one room, primitive fields and intervals** | Extend `verify.py fast`: retain Clang owner passages, reachability, regression/hash/ore controls, partial LOD0 ring, and random-camera sweep (seed `0x4C3434`, 3 cameras, W1/W8/W12, settings `(3,0,0)`); add the cave recipe, typed graph validation, interval-oracle containment and false-proof controls, and a deliberately broken-route expected failure. Run the generalized L48 whole-surface audit on the corridor, chamber, and full wall-foot at base alignment and ±h/2 grid phases. Capsule-flood-fill actual composed arrival-to-departure path, with buried/blocked negative control. | **7–10 min** |
| **2. Multiple rooms, attached branches, bounded wall detail** | Extend `verify.py medium`: all current Clang passages, reachability, regression and style matrices, transitions/invariants, LOD0–8 rings, capture/mesh audits, ore controls, and 5-camera random sweep with settings `(3,0,0)`, `(2,1,1)`, `(3,2,1)`, W1/W8/W12. Add at least 5 cave seeds, all routes, BVH-vs-brute-force candidate checks, interval negative controls, every room/edge wall-foot and floor phase in the whole-surface audit, and LOD transition samples. | **13–18 min** |
| **3. Loops, BVH tuning, legacy opt-in and promotion** | Extend `verify.py full`: passed medium, GCC supplement, 5-camera/3-setting sweep, 30-cell determinism, and five interleaved whole-view cost pairs. Add Clang/GCC W1/W8/W12 and reordered-input hash parity; route and interval audits across seed matrix; whole-surface and LOD-transition gates for every cave feature. Load/save old owner cave assets and compare non-opted-in output against legacy parity; benchmark the opted-in native recipe in five matched pairs against the previous build, with fixed tiles and seeds. | **25–40 min** |
Current `verify.py` random cameras use seed `0x4C3434`; fast runs 3 cameras at `(3,0,0)`, medium/full run 5 cameras at `(3,0,0)`, `(2,1,1)`, and `(3,2,1)` across W1/W8/W12. Whole-surface phase sweeps and departure reachability are new gates, not existing ones. No verification tier was run for this report.
**Owner question:** should existing `TunnelNetwork` assets remain on the legacy evaluator until explicitly opted into the versioned native `caves` recipe? My recommendation is yes.