# Research R6 — director, generators, and mesher in metres Read-only review of the current checkout and L20/L21/L22/L29, R2, and R5 notes. No builds or tests were run. **R2’s layout-chunk split is already resolved in the checked source.** `AttachValidatedWorldAssembly` computes one physical `LayoutChunkWidthSubvoxels` from `StrateLayoutChunkSizeMeters`, passes it to both `BuildSurfaceStratumPlan` and `BuildFloatingIslandStratumPlan`, and writes the same manager/dispatch width into the resolved snapshot (L22). Do not apply the FI owner/Core ratio to layout bounds again. FI still uses that ratio to convert its *generator parameters* and passage dimensions from owner voxels; that separate authoring-unit leak remains. ## 1. Current leaks The closest current match to the three layers is: director work in `VoxelStrateManager.cpp::Initialize` and `VoxelForgeCoreAdapter.cpp::AttachValidatedWorldAssembly`; field evaluators in `Heightfield2D::point`, `FloatingIslandFieldV1::densitySubvoxels`, and legacy `UVoxelGenerator::GetDensityAt`; shared composition in `FStandaloneShapeWorld::ApplyResolvedStrateComposition`; extraction in `World::generateTile` and `UVoxelMarchingCubesMesher::GenerateMesh`. `VoxelWorld::BuildDesiredTiles` is the scheduling side of the director. The table lists where these boundaries still cross. | Leak | Current location and consequence | |---|---| | Director lookup inside field evaluation | `Standalone/Core/src/ShapeWorldInternal.h::FStandaloneShapeWorld::DensityAt`, `NativeSurfaceDensityAt`, `NativeFloatingIslandDensityAt`, and `ClassifyBoxDetailed` query `UVoxelStrateManager` and select native SurfaceWorld, native FloatingIslands, or legacy evaluation while workers sample. `Source/VoxelForge/Private/VoxelGenerator.cpp::UVoxelGenerator::GetDensityAt` also routes each sample through manager type/params. The resolved layout exists, but is not yet the sole dispatch input. | | No common generator API/format | `Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h::Heightfield2D` and `FloatingIslandFieldV1` have distinct recipe/evaluator APIs; the legacy path in `VoxelGenerator.cpp`, operator stacks, and morphology is a third. `FStandaloneShapeWorld` is their adapter and shared composition path at once. A new generator cannot currently implement one common contract. | | Units cross boundaries repeatedly | `VoxelStrateDefinition.h::StrateHeightInChunks`, `VoxelSettings.h::InterStrateGapChunks`, and many `VoxelStrateTypes.h` shape/passage values are authored in chunks or voxels. `VoxelStrateManager.cpp::Initialize` converts metre chunk width to owner voxels; `VoxelForgeCoreAdapter.cpp::WorldAssemblyFixed` packs values as 1/256 Core voxel; `BuildFloatingIslandStratumPlan` and `AttachValidatedWorldAssembly` use owner/Core ratios for FI dimensions and passages. Snapshot bounds are micrometres, but recipe anchors are still labelled 1/256 Core voxel, and `voxelSizeMicrometres` is currently filled with the same Core size for every strate. `VoxelStrateDefinition.h` still documents 16 chunks as 64 m at 4 m/chunk although the current 8 m setting makes that 128 m. | | Generator policy remains in shared composition | `ShapeWorldInternal.h::ApplyResolvedStrateBoundaryBand` branches on generator-kind strings for FI air-gap and surface/landing behavior; the density/classification functions above branch on generator types. These exceptions should become explicit resolved interface or generator capabilities, not string tests in the common evaluator. | | Route and passage logic is only partly shared | `VoxelForgeCoreAdapter.cpp::BuildFiniteSurfaceRoute` plans the SurfaceWorld route. `BuildFloatingIslandStratumPlan` embeds passage/spiral dimensions into the FI anchor root. `ResolvedLayoutInternal.h::PlanResolvedLayoutPassagesV1` still tests SurfaceWorld and FloatingIslands to place mouths and handle the FI root; `ShapeWorldInternal.h::ApplyResolvedStratePassageCarves` applies the shared carve but also contains route/support policy. Legacy passage behavior remains in `UVoxelGenerator::GetDensityAt`. A new generator should not need a route implementation. | | Tile builder knows generator recipes | `Standalone/Core/src/VoxelForgeCore.cpp::World::generateTile` scans SurfaceWorld feature IDs 2/4, refines their resolution, limits a native SurfaceWorld density band, and selects/skips far-horizon repair based on SurfaceWorld/FloatingIslands plan presence. The generic mesher should receive bounds, surface hints, and a sampling request, not recipe IDs. | The shared ceiling/content/bedrock records and Hard/Gradient/Interleaved evaluation are real foundations (`ResolvedLayoutSnapshotV3`, `ApplyResolvedStrateBoundaryBand`, L29). Remaining work is to make their resolved physical records authoritative and remove generator-name exceptions. The mesh-side boundary floor/ceiling patches in `VoxelForgeCore.cpp`/`FarShellsInternal.h` still duplicate part of that surface policy. ## 2. Generator contract The director resolves an immutable world snapshot before jobs are queued. A generator is constructed once for a resolved strate and receives: - Stable world seed, strate ID, generator/recipe/schema/evaluator versions, and that strate’s immutable parameters. - Physical half-open bounds `[bottom, top)` and lattice origin in integer micrometres; the resolved ceiling/content/bedrock and adjacent-interface records that touch the strate. - Its own `voxelSizeMicrometres` (25 cm by default), independent of the 8 m layout chunk and of the tile key. The request gives the physical query bounds plus the mesher’s exact halo. LOD may guide work, but the same physical coordinate and recipe must return the same field value at every LOD. - The shared deterministic library: versioned noise, fixed-point conversion, common distance/shape helpers, and conservative bounds utilities. Resolved passage descriptors and style are consumed by shared composition; the generator need not plan or carve the inter-strate route. Concrete evaluator shape: `densityAt(xUm, yUm, zUm) -> signed field value`, with one documented convention (recommended: negative is solid, zero is the surface, positive is air). Keep magnitude units stable and documented; metre-scaled signed distance is the target for shared band composition. Provide a conservative support/influence AABB or “unbounded/unknown”; an interval/classification for a requested AABB (`solid`, `air`, `mixed`, or `unknown`); and an optional detail envelope (smallest safe sample spacing). A SurfaceWorld-like generator may also return semantic ground/cap surfaces in metres. Caches and feature tile lists may accelerate these queries, but are not part of output identity. **A generator must never** query the manager, UObject state, chunk index, season, or a neighbour while evaluating; choose strate bounds, gaps, transitions, bedrock/ceiling ownership, or route geometry; mutate input state; generate triangles; or vary a field by tile order, worker, or LOD. Unknown proof means evaluate, never skip. The director selects the evaluator once; shared composition applies the interface bands, passages and edits; the mesher consumes the composed field and generic hints. This is enough for TunnelNetwork or a cavern generator to be added without edits to the director’s sampling loop or mesher. ## 3. Ordered migration “No” means existing-world density/mesh/output hashes stay identical. A new schema may change manifest identity only when deliberately versioned; do not hide such a change behind a claimed pure refactor. Size estimates are one engineer’s rough implementation effort: S 1–2 days, M 3–5 days, L 1–2 weeks. | Step | Change and verification tier | Changes output? | Main risk | Size | |---:|---|---|---|---| | 1 | Freeze the current source stamp, canonical owner FI Style 2/SW Style 1 resolved snapshots, and existing hashes as the comparison set. Use R5 **fast** to establish the baseline; medium/full remain promotion gates. | No | Incorrect/stale binaries or mislabeled style invalidate all comparisons. | XS | | 2 | Add a common immutable field interface and wrap the current SurfaceWorld, FloatingIslands, and legacy evaluators without changing their arithmetic. Bind the evaluator once per resolved strate/tile, not via a manager lookup per density sample. Run **fast** hash parity; **medium** before merge. | No; hashes must match. | Virtual/function dispatch cost; accidentally changing float/fixed-point call order. | M | | 3 | Make the resolved metre layout the sole runtime authority: resolve height, gap, transition width, band bounds, seed, and passage settings before scheduling. Keep chunk indices only as a compatibility projection. Convert the existing 8 m chunk and L29 bands exactly. R2’s FI/SW split is handled here by the already-present common layout width; retain owner/Core ratios only in the legacy FI parameter adapter. Run **fast + medium** (layout, transition, passage checks). | No for equivalent existing layouts; hashes must match. | Negative-Z floor/rounding, old season snapshots, adapter and manager disagreeing about interval edges. | M | | 4 | Introduce metre-valued authored height/gap/transition/passage dimensions and a per-strate `voxelSizeMeters` default of 0.25. Add a versioned conversion from old chunk/voxel assets based on each legacy route’s established unit; do not assume the source unit is recorded on the asset or reinterpret old numeric values as metres. Keep 8 m layout chunk independent. **Fast + medium** for old assets; full when enabling non-default resolutions. | No for converted old assets. Yes for changed metre values or voxel size; bump layout/recipe/evaluator identity. | Asset migration and resolution-dependent detail; changing 25 cm to 12.5 cm can mean about 8× samples per physical volume. | L | | 5 | Route all new and existing passage requests through resolved per-strate configs and a shared route plan. First copy existing SW/FI route anchors exactly; replace FI-root and SurfaceWorld placement branches with explicit resolved anchor/surface capabilities in follow-up slices. Run **fast + medium** passage matrix and route parity. | No for exact route replay; hashes must match. New geometry/style semantics are Yes and need a generator/layout version bump. | Walkability/support, deterministic placement, route planning cost. | M | | 6 | Move remaining boundary exceptions into explicit interface records/capabilities. Keep ceiling → content → breakable bedrock per strate and the upper strate’s Hard/Gradient/Interleaved rule. Preserve L29 samples and passage-mouth fade exactly. Run **fast + medium** transition, hole, and passage gates. | No; hashes must match. | Interface edge ownership and a false solid/air shortcut can open a hole. | M | | 7 | Standardize culling outputs: conservative support bounds, interval certificates, unknown fallback, and detail envelope. Adapt existing field proofs first; replace type switches only when the new proof matches brute-force/classification controls. Run **fast**, then **medium** proof negatives and cost pairs. | No; hashes must match. | Unsound certificates skip density work; per-voxel bounds calls hurt performance. | M/L | | 8 | Make `World::generateTile` and the mesher consume generic feature boxes, semantic surfaces, field bounds, and sample-spacing hints. Move current SurfaceWorld refinements behind capabilities while keeping their algorithms byte-for-byte. Run **fast + medium** ring/shape checks. | No for dispatch-only refactor; hashes must match. | Cross-LOD seams, tile halos, mixed-resolution tile boundaries, Unreal mesher assumptions. | L | | 9 | Add an opt-in metre-native TunnelNetwork/cavern recipe through the contract and generic mesher interface. Run **medium** on the new recipe and R5 **full** before enabling it in owner layouts. | Yes for worlds selecting it; bump that generator’s recipe/evaluator version. | New density cost and output identity. | M/L | | 10 | Implement the L20 shared, LOD-stable surface/transition representation to remove measured ring ledges. Run **medium** ring/shape checks and R5 **full** on the final tree. | Yes; bump the mesher/layout version and establish new golden hashes. | Surface topology and cross-LOD transitions change; coarse sampling may erase thin bands. | L | R5’s draft timings are about **3–4 min fast**, **8–10 min additional medium**, and **32–34 min full**, excluding builds. Run fast for every step: output-neutral slices must match existing hashes; output-changing slices must match their new versioned golden hashes. Medium is required before promoting layout, route, culling, or mesher changes. Full is final-source evidence after output-changing versions and golden hashes are reviewed. Include the actual owner configs and assert their resolved styles, as R5 requires; do not treat style-override fixtures as owner evidence. ### Cross-cutting risks - **Determinism:** convert metres to integer micrometres once; use a specified tie rule and mathematical floor for negative coordinates; hash resolved parameters, voxel size, generator versions, and interface records in stable order. Keep floating-point contraction/platform checks for the compatibility evaluator. - **Per-voxel cost:** eliminate manager/recipe selection from the hot call, pre-resolve field objects and tile candidates, and keep unknown proofs conservative. Benchmark actual FI2 and SW1 with R5 cost pairs at medium/full. A finer voxel size is cubic work growth, not a cheap resolution toggle. - **Unreal adapter:** `VoxelForgeCoreAdapter.cpp` currently serializes UObject parameters into Core fixed units; new reflected metre fields need versioned asset migration and UHT/UBT validation. R2 also recorded that recent adapter changes had no Unreal build evidence. Static research cannot establish that compile boundary. ## Open question for the owner Should existing voxel-authored assets retain their current physical dimensions through a per-generator compatibility conversion? Recommended: yes, then author new recipes in metres. Reinterpreting old values at 25 cm would rescale worlds and require broad output-version bumps.