feat(editor): walk a composed candidate in PIE + why rooms read angular
PART B -- the thing Jahni asked for: "any way to test those in game?" A candidate existed only as measurements and PNGs. Now he can stand in one. Select the VoxelWorld actor in PIE -> Live Edit|Composer -> ComposerSeed / ComposerCandidateIndex / ComposerTargetStrateIndex / bComposerRollStructure -> click Apply Composer Candidate. The button and the automation tests call the SAME roll wrapper, which was the load-bearing requirement: a second roll path could drift, and then he would be judging a different world than the contact sheet describes. A determinism sample is logged on apply (seed, index, recipe, archetype, metrics, epoch, eight-point density verdict) so drift is caught the day it happens rather than in a month. Hazards handled, since this is the first composer code to touch the live runtime path: preflight materialisation before any live mutation, generation and decoration tasks drained, PassagesVersion bumped to invalidate thread_local caches, reuse of the existing RegenerateAllChunks / Epoch invalidation rather than a new path, no Initialize() or GeneratePassages() during apply (the re-entrancy trap), DiffLayer locks untouched, and custom recipes conservatively force ClassifyTile to Mixed. Scope is deliberate: a DENSITY-ONLY overlay. Layout height, authored passages, content, water and biome metadata stay from the existing slot; RebuildStrates() clears it. A full composed layout replacement needs a safe rebuild path that does not exist yet. Editor-only, verified: a Shipping build succeeds with the bridge excluded (96/96 actions), so §3.1's "offline only, never on a player's machine" still holds. ⚠️ UNVERIFIED BY DESIGN: a button cannot be tested headlessly and Codex was told not to claim it works. Jahni presses it and confirms the visual plus the "determinism=PASS" log line. PART A -- why rooms read angular, measured not guessed. One of three room shapes is VoxelSDF::RoundedBox: ShapeA = (.8 Rxy, .8 Rxy, .8 Rz) ShapeR = .25 Rxy so rounding is 31% of the horizontal half-extent but 78% of the vertical. Corners are rounded; the broad planar FACES survive. SmoothMin (blend 4) softens room/tunnel junctions not isolated corners; the cave warp bends geometry but preserves flat regions; roughness is surface-scale only. The name is accurate -- "rounded box" is not "blob". NOT ACTED ON. Jahni corrected his own read: the angular archetype is Maze (lattice source, rectilinear BY DESIGN and correct), and TunnelNetwork is "alright-ish". Codex's recommendation is recorded for if he ever wants it: ~5-10% boxes, 10-20% capsules, rest ellipsoids, or a larger ShapeR. Also closed REVIEW_FINDINGS EVoxelPassageType/Style as WONTFIX, enacting a 2026-08-16 judgement that recommended closure and was left open. Build clean (Editor + Shipping), 25 succeeded / 0 failed, run by me. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU
This commit is contained in:
1 parent
90c40c8d5a
commit
d717bc74ff
13 files changed
+1182
-32
No files matched your search
+11
-2
@@ -413,13 +413,14 @@ Maps depth→strate at runtime; owns passages.
|
||||
| `AnyPassageNearBox` | — | Conservative sphere-vs-AABB test of every passage's bound against a voxel box (+carve blend pad). Per TILE (ClassifyTile guard), never per voxel. |
|
||||
| `FindSlotIndexForChunkZ` | 427 | Z → layout index. |
|
||||
| `GetStrateAt` / `GetStrateIndex` | 443 / 455 | World-Z queries. |
|
||||
| `GetLayoutVersion` | h:161 (inline) | Layout/passage generation counter (= `PassagesVersion`, bumped by every `Initialize`). Hot-path callers key `thread_local` memos on it (strate-index memo in `GetDensityWithParams`, passage shortlist) so editor rebuilds never serve stale data. |
|
||||
| `GetLayoutVersion` | h:161 (inline) | Layout/passage generation counter (= `PassagesVersion`, bumped by every `Initialize` and by the editor composer override). Hot-path callers key `thread_local` memos on it (strate-index memo in `GetDensityWithParams`, passage shortlist) so live changes never serve stale data. |
|
||||
| `GetStrateForChunk` | 466 | Chunk → definition. |
|
||||
| `GetGeneratorTypeForChunk` | 476 | Chunk → generator type. |
|
||||
| `UsesOperatorStackForChunk` | 559 | Chunk → should `GetDensityAt` take the operator stack? `bUseOperatorStack` on the definition **AND** archetype in the ported list — **now all 8 of 8** (Maze, FlatPlain, CrystalChamber, SurfaceWorld, VerticalShafts, FloatingIslands, TunnelNetwork, Underwater). **That list is written down here and nowhere else.** With every archetype ported the flag is now the *only* thing that decides the path, so ticking the box is no longer a no-op anywhere — it is a real switch onto the operator stack for that strate. |
|
||||
| `GetSlabParamsForChunk` | 490 | Slab params with runtime Z bounds (no blend — slabs use Hard). |
|
||||
| `GetBiomeContextForChunk` | — | Flatten the strate's `Biomes[]` + `BiomeMapParams` into a POD `FBiomeContext` for the biome field. Empty ⇒ biomes disabled. §8.14. |
|
||||
| `GetGenerationParams` | 515 | **Blended** TunnelNetwork params (handles Gradient/Hard/Interleaved transitions). |
|
||||
| `SetComposerOverrideForStrate` / `GetComposerOverrideForChunk` | editor-only | Temporary density-only candidate overlay for one existing slot. Copies immutable params/recipe into the worker refetch path, leaves layout/content/passages intact, and bumps `PassagesVersion` to invalidate generator memos. |
|
||||
| `BuildParamsFromDefinition` (static) | 1399 | Returns the definition's base `GenerationParams` only. Terrain-op assets are passed separately to `BuildChunkCache`, which applies one selected op per room and pre-bakes Column/Pit/Chimney features. |
|
||||
|
||||
**`Public/VoxelTerrainOpDefinition.h` + `.cpp`** — `UVoxelTerrainOpDefinition : UPrimaryDataAsset`
|
||||
@@ -462,7 +463,8 @@ selection → `FStrateGenerationParams::Lerp` or reflected native-family blend
|
||||
field range jitter (or the season-zero ±25% own-magnitude bootstrap for near-zero ranges) →
|
||||
editor-reflection clamps → ordered-pair repair. Bool
|
||||
`bTunnelsFlowTowardOrigin` inherits from the dominant parent; integer/enum SNAP fields are not
|
||||
jittered. This API is not called by runtime generation. The settings audit found **one unique path**,
|
||||
jittered. Normal runtime generation never calls this API; the editor-only AVoxelWorld bridge does so
|
||||
only from its PIE button. The settings audit found **one unique path**,
|
||||
`/Game/VoxelForge/DA_Strate3`, which explains the old one-vector corpus; the project assets were
|
||||
never in that pool.
|
||||
|
||||
@@ -475,6 +477,13 @@ it. `RequiredResources` / `ProvidedResources` close the room-state hole that cha
|
||||
could not express. `VoxelForgeComposerStructureRollTest` rolls 64 candidates, measures them through
|
||||
the offline sampler, and brute-forces every uniform box verdict from the novel stack itself.
|
||||
|
||||
Public/VoxelWorld.h + Private/VoxelWorld.cpp — ApplyComposerCandidate exposes the four
|
||||
Live Edit|Composer properties and the CallInEditor button. It preflights the candidate, pauses
|
||||
generation before installing the manager override, and calls the existing epoch-aware full reset.
|
||||
The post-apply check compares eight densities against the shared native/recipe stack where the live
|
||||
world has no extra diff, disturbance, or biome context. It reports SKIPPED rather than comparing
|
||||
unlike fields.
|
||||
|
||||
**`Public/VoxelStratePreview.h` + `Private/VoxelStratePreview.cpp`** — editor/automation-only PNG
|
||||
renderer and self-contained contact sheet. It consumes `FVoxelStrateSampleGrid` from the measurement
|
||||
pass, emits deterministic centre-Y XZ and data-selected XY slices via `IImageWrapper`, and shows filled-cell
|
||||
|
||||
Reference in new issue
Block a user