docs: CODEMAP rows + progress entry for the Phase 1 Maze port
CODEMAP gains 3.2c (VoxelDensityPrimitives), 3.2d (the operator stack and its factories), FVoxelOpSample under 3.2b, and the two new tests under 3.12. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+25
@@ -106,8 +106,31 @@ Paths relative to `Source/VoxelForge/`. `Public/` = headers, `Private/` = impl.
|
|||||||
| `FVoxelOpContext` | Chunk-constant inputs. **Carries `LayoutVersion` by construction** so a new op cannot forget it (AUDIT C2). |
|
| `FVoxelOpContext` | Chunk-constant inputs. **Carries `LayoutVersion` by construction** so a new op cannot forget it (AUDIT C2). |
|
||||||
| `IVoxelDensityOp` | `PrepareChunk` / `Eval` / `EffectOverBox` / `ClassifyBox` / `IsXYPure`. |
|
| `IVoxelDensityOp` | `PrepareChunk` / `Eval` / `EffectOverBox` / `ClassifyBox` / `IsXYPure`. |
|
||||||
| `IVoxelDensityOp::ClassifyBox` | ⚠️ **not source-only.** Forcing ops (the boundary seal inside its band) overwrite the input entirely, which pure direction cannot express. |
|
| `IVoxelDensityOp::ClassifyBox` | ⚠️ **not source-only.** Forcing ops (the boundary seal inside its band) overwrite the input entirely, which pure direction cannot express. |
|
||||||
|
| `FVoxelOpSample` | The state threaded through the stack: **two** channels, `Density` (INTERNAL convention, **positive = SOLID**, negated to MC once by the caller) and `Sdf` (standard SDF, negative = inside). ⚠️ `min()` therefore means opposite things on the two channels. |
|
||||||
| `FVoxelBoxHypotheses` + `VF_ForceHypotheses` / `VF_FoldEffect` / `VF_FoldOp` | The fold that turns a stack into an `EVoxelTileClass`. Reproduces today's hand-written `ClassifyTile` line for line — the mapping is written out in the header. |
|
| `FVoxelBoxHypotheses` + `VF_ForceHypotheses` / `VF_FoldEffect` / `VF_FoldOp` | The fold that turns a stack into an `EVoxelTileClass`. Reproduces today's hand-written `ClassifyTile` line for line — the mapping is written out in the header. |
|
||||||
|
|
||||||
|
### 3.2c Structural primitives — `Public/VoxelDensityPrimitives.h`
|
||||||
|
`VF_ApplyOriginSpine` · `VF_ApplyBoundarySeal` · `VF_ApplyPassageCarving` — the three world
|
||||||
|
invariants every archetype appends, **moved here 2026-07-27** so the generator and the operator
|
||||||
|
stack share ONE copy. `VoxelGenerator.cpp` keeps same-named `static FORCEINLINE` forwarders so its
|
||||||
|
~20 call sites are unchanged; bodies are byte-identical. Also `VoxelDensityReach::SpineBlend` /
|
||||||
|
`PassageBlend`, the blend radii `ClassifyTile` currently hand-duplicates.
|
||||||
|
**Convention: INTERNAL (positive = solid).**
|
||||||
|
|
||||||
|
### 3.2d Operator stack — `Public/VoxelDensityOpStack.h` + `Private/VoxelDensityOpStack.cpp`
|
||||||
|
⚠️ **Feeds nothing yet.** `GetDensityAt`/`ClassifyTile` are untouched; the archetype `switch` is
|
||||||
|
still the only production path. Exercised solely by `VoxelForge.OpStack.MazeEquivalence`.
|
||||||
|
|
||||||
|
| Symbol | Role | Notes |
|
||||||
|
|--------|------|-------|
|
||||||
|
| `FVoxelOpStack` | — | Ordered `TUniquePtr` list. `PrepareChunk` / `EvalInternal` / `EvalMC` / `ClassifyBox` (the fold, with an early-out when both hypotheses die). |
|
||||||
|
| `FVoxelOpStack::AppendStructuralPost` | 4 | Appends spine → seal → passage **in that fixed order**. An author cannot omit or reorder them. The diff layer is NOT here yet — it still lives in `GetDensityAt` after the MC negate, with disturbances. |
|
||||||
|
| `VoxelDensityOps::MakeConstantRockSource` | 1 | `Density = BaseDensity`. `ClassifyBox` → **AllSolid**, exact and free. Shared by TunnelNetwork, Maze, VerticalShafts and bedrock gaps. |
|
||||||
|
| `VoxelDensityOps::MakeLatticeCorridorSource` | 1 | Maze corridors, SDF channel. Edge identity = `hash(lower node, axis)` ⇒ adjacent chunks cannot disagree (AUDIT §6.4's preferred pattern). Its `EffectOverBox` answers for the source+carve **pair** (Phase 1 simplification) so it must be told the downstream `ExtraReach`. |
|
||||||
|
| `VoxelDensityOps::MakeSdfRoughnessMod` | 3 | Wall roughness in **SDF** space (Maze/Shafts/Islands variant). TunnelNetwork's density-space roughness is a **different op** — see OPSTACK-DECOMPOSITION §1. |
|
||||||
|
| `VoxelDensityOps::MakeSdfCarve` | 2 | SDF → density carve. The same six lines currently copied in three archetypes. |
|
||||||
|
| `VoxelDensityOps::BuildMazeStack` | — | The 7-op Maze stack. If this ever becomes one op, the refactor failed its own test (§2.5). |
|
||||||
|
|
||||||
### 3.3 Chunk identity
|
### 3.3 Chunk identity
|
||||||
`VoxelChunk.h` (the old `FVoxelChunk` coord wrapper) was DELETED — dead since the tile
|
`VoxelChunk.h` (the old `FVoxelChunk` coord wrapper) was DELETED — dead since the tile
|
||||||
redesign; tile identity lives in `FVoxelTileKey` (VoxelWorld.h).
|
redesign; tile identity lives in `FVoxelTileKey` (VoxelWorld.h).
|
||||||
@@ -344,6 +367,8 @@ The plugin's first tests (`OPSTACK-PLAN.md` Phase 0.5). Run them from the editor
|
|||||||
| ″ | `VoxelForge.Determinism.LiveEditInvalidation` | AUDIT C2 regression: triple the heightfield params, `Initialize` again, require the density to MOVE. The edit does not move the strate, so only `LayoutVersion` changes. |
|
| ″ | `VoxelForge.Determinism.LiveEditInvalidation` | AUDIT C2 regression: triple the heightfield params, `Initialize` again, require the density to MOVE. The edit does not move the strate, so only `LayoutVersion` changes. |
|
||||||
| `VoxelForgeClassifyTileTest.cpp` | `VoxelForge.Determinism.ClassifyTileSoundness` | Scans for a non-`Mixed` verdict, then brute-forces the exact mesher lattice (`g ∈ [-1, Cells+1]`). **A false verdict is an invisible, collisionless hole** — T1.d v1 was reverted for exactly this. Errors out rather than passing if it found nothing to check. |
|
| `VoxelForgeClassifyTileTest.cpp` | `VoxelForge.Determinism.ClassifyTileSoundness` | Scans for a non-`Mixed` verdict, then brute-forces the exact mesher lattice (`g ∈ [-1, Cells+1]`). **A false verdict is an invisible, collisionless hole** — T1.d v1 was reverted for exactly this. Errors out rather than passing if it found nothing to check. |
|
||||||
| `VoxelForgeDiffLayerTest.cpp` | `VoxelForge.Determinism.DiffLayerContention` | N readers running the worker call mix while the game thread writes and `Clear()`s. Survival + monotonic `ModsVersion`. |
|
| `VoxelForgeDiffLayerTest.cpp` | `VoxelForge.Determinism.DiffLayerContention` | N readers running the worker call mix while the game thread writes and `Clear()`s. Survival + monotonic `ModsVersion`. |
|
||||||
|
| `VoxelForgeClassifyTileTest.cpp` | `VoxelForge.OpStack.BoxVerdictFold` | Pure-logic walk of the fold in `VoxelDensityOp.h`, case by case — including the seal-forces-AllSolid case that justifies `ClassifyBox` existing. Also the only `.cpp` that includes the op header, so the build actually sees it. |
|
||||||
|
| `VoxelForgeOpStackMazeTest.cpp` | `VoxelForge.OpStack.MazeEquivalence` | **Phase 1's load-bearing test.** The 7-op Maze stack vs `GetMazeDensity` over 20k points (aiming for bit-identity; a side-of-iso disagreement is the hard fail), plus purity across workers and brute force on every box verdict the stack emits. Reports how many tiles the stack can prove uniform — today's `ClassifyTile` proves **zero** for any cave archetype. |
|
||||||
|
|
||||||
## 4. The density pipeline (most-edited hot path)
|
## 4. The density pipeline (most-edited hot path)
|
||||||
|
|
||||||
|
|||||||
@@ -211,3 +211,48 @@ edits to `VoxelDensityOp.h` and `VoxelGenerator.cpp` (include the primitives, de
|
|||||||
**Next single action:** write those files, then STOP.
|
**Next single action:** write those files, then STOP.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-07-27 — Phase 1 done (written, not built). Maze DOES decompose.
|
||||||
|
|
||||||
|
**The Phase 1 question is answered.** `OPSTACK-PLAN §4`'s stop-trigger asked whether the
|
||||||
|
source/modifier split falls out naturally from the existing code. It does — Maze becomes seven ops
|
||||||
|
with no contortion, and three of them are already shared with other archetypes:
|
||||||
|
|
||||||
|
```
|
||||||
|
FConstantRockSource ← also TunnelNetwork's and VerticalShafts' first line
|
||||||
|
FLatticeCorridorSource ← Maze only (role 1: what makes a maze a maze)
|
||||||
|
FSdfRoughnessMod ← also VerticalShafts, FloatingIslands
|
||||||
|
FSdfCarveOp ← the same six lines currently copied in three archetypes
|
||||||
|
FOriginSpineOp ─┐
|
||||||
|
FBoundarySealOp ├─ identical in all six density functions
|
||||||
|
FPassageCarveOp ┘
|
||||||
|
```
|
||||||
|
|
||||||
|
No revert, no stop-trigger. Commit `4c53d3b`.
|
||||||
|
|
||||||
|
**What is deliberately NOT wired:** `GetDensityAt` and `ClassifyTile` are untouched, so nothing in a
|
||||||
|
running world can change. `OPSTACK-PLAN §4` Phase 1 step 3 ("GetDensityAt gains one branch") is
|
||||||
|
**held back until the build is green** — wiring an uncompiled stack into the hot path would be
|
||||||
|
exactly the stacked-unverified-work pattern `AUDIT §P3` documents. The port is validated instead by
|
||||||
|
`VoxelForge.OpStack.MazeEquivalence`.
|
||||||
|
|
||||||
|
**Two contract decisions taken (Jahni delegated them):** two-channel `Eval`, and INTERNAL sign
|
||||||
|
convention inside the stack. Both are argued in the previous entry and in the commit message. The
|
||||||
|
second **reverses** what `VoxelDensityOp.h` said on 2026-07-26 — if a later context finds MC-in-stack
|
||||||
|
written anywhere, that text is stale.
|
||||||
|
|
||||||
|
**One pre-existing hairline bug found and NOT silently patched:** at the inner edge of a seal band,
|
||||||
|
`1 - Dist/Thickness` can round to exactly `0.0f`, so `SealFactor·BaseDensity` is 0, internal density
|
||||||
|
lands on 0, and the mesher's `D >= IsoLevel` counts that point as AIR. Today's `ClassifyTile`
|
||||||
|
excludes those z from column testing and can therefore emit `AllSolid` over them. It needs the
|
||||||
|
archetype to produce air at exactly that z, so the window is hairline — but a false `AllSolid` is a
|
||||||
|
hole. The **new** seal op keeps a 1-voxel safety margin before it forces. The old path is untouched;
|
||||||
|
`VoxelForge.Determinism.ClassifyTileSoundness` would catch it if it ever fires.
|
||||||
|
|
||||||
|
**UNVERIFIED:** everything, still. Nothing has been compiled.
|
||||||
|
|
||||||
|
**Next single action: BUILD.** Then, in order: fix what the tests report → read
|
||||||
|
`MazeEquivalence`'s two numbers (how many samples differ, and how many tiles the stack can prove
|
||||||
|
uniform) → only then wire the stack into `GetDensityAt` behind a per-strate opt-in.
|
||||||
|
|
||||||
|
---
|
||||||
|
|||||||
Reference in New Issue
Block a user