wip(unreal): round 4 -- strate-type coverage matrix; SurfaceWorld via exact legacy bridge
Luna, integration round 4 (owner requirement: Core must know every strate type). Coverage, Core vs legacy owner field (one probe per type, 686,000 LOD0 samples): TunnelNetwork approximate (2.17% signs differ); FlatPlain / CrystalChamber native slab fields missing (generic cave, 1.28%); Maze missing (13.3%); VerticalShafts missing (no shaft surface); FloatingIslands missing (95.8%); Underwater approximate + no water. SurfaceWorld: exact density (0 sign changes, LOD0-3 hashes match) through the copied legacy evaluator -- but at legacy cost: full view 23.1 s vs legacy 23.9 s (Core caves without surface 0.785 s). Passages: SlopedTunnel/VerticalShaft/Spiral pass walkability; Cascading (365/1,495) and Worm (109/1,490) FAIL. Transitions approximate (1.2-1.3%). BuildHost UBT + actor validation pass (SurfaceWorld layout: 2,553 visual keys, 448 LOD transitions, biome query). Small owner/Core capture pairs in core_strate_coverage/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
No files matched your search
@@ -1129,6 +1129,55 @@ but it duplicates the field boundary, costs roughly the legacy evaluation per sa
|
||||
more float/platform constraints; keep it as a temporary compatibility route only if exact behavior
|
||||
is required before the port. See the round-3 table in the integration report for per-defect evidence.
|
||||
|
||||
Round 4 supersedes the SurfaceWorld status above: Core now has the temporary legacy density bridge
|
||||
described in §8.19. The native evaluator, water presentation, and other archetypes remain open work.
|
||||
|
||||
### 8.19 SurfaceWorld bridge and all-strate coverage — integration round 4
|
||||
|
||||
**Status (2026-10-08):** the copied owner evaluator is now called inside Core for samples whose
|
||||
resolved strate type is SurfaceWorld. The bridge covers Core density entry points used by the
|
||||
marching-cubes path: analytic, lattice, unclamped, and packed-run sampling. SurfaceWorld boxes fail
|
||||
closed as Mixed in the primitive-only box classifier so it cannot skip the biome heightfield. Core
|
||||
edit brushes are applied after the owner density result. The reader also retains SlabParams,
|
||||
MazeParams, VerticalShaftParams, and FloatingIslandParams in the standalone snapshot.
|
||||
|
||||
The owner/Core comparator found identical density hashes at LOD0–LOD3 in the matched-camera
|
||||
SurfaceWorld matrix and on a 686,000-sample full-resolution surface patch. At LOD0 the measured
|
||||
symmetric sampled surface distance was 0.0767 m mean / 1.0117 m max; at LOD2 it was 0.1737 m mean /
|
||||
5.264 m max with 63 unmatched sampled vertices. The viewer captures still show a visible mesh or
|
||||
presentation difference. Core does not emit the legacy water plane, biome material palette,
|
||||
decorations, or atmosphere from this density bridge.
|
||||
|
||||
The bridge is deterministic across the tested BuildHost W1/W8/W16 worker counts. It is intentionally
|
||||
not a platform-independent arithmetic port: it inherits the copied evaluator's float behavior. Its
|
||||
cost is substantial. A matched CPU viewer run with 1,294 tiles through LOD8 took 23.085 s wall and
|
||||
180.562 worker-seconds in Core, versus 23.914 s and 188.705 worker-seconds in the owner route. The
|
||||
Step29 Core baseline without this route took 0.785 s, but omitted the surface. Use the bridge as a
|
||||
fidelity fallback while a native heightfield with fixed-order noise and per-column biome/height
|
||||
caching is developed.
|
||||
|
||||
The probe table in the [integration report](Standalone/UNREAL_INTEGRATION_REPORT.md) covers all
|
||||
eight generator types, five passage types, four passage styles, and three transitions. Current route
|
||||
choices for the next implementation pass:
|
||||
|
||||
| Field | Recommended Core route | Reason and current gap |
|
||||
|---|---|---|
|
||||
| TunnelNetwork | Keep the native primitive representation; add missing density operators as measured. | Existing rooms, tunnels, and passage chains work, but the 16-tile probe still changed 2.17% of signs and had a 1.01 m mean sampled surface distance. |
|
||||
| FlatPlain and CrystalChamber | Native slab operator using the already copied slab parameters. | Floor, ceiling, columns, and crystal ceiling are a distinct low-cost structure; generic cave primitives do not express them. |
|
||||
| Maze | Native deterministic cell graph and corridor field using FMazeGenerationParams. | The legacy topology is seed-stable and compact; current generic caves changed 13.34% of signs and had a 5.92 m maximum sampled surface distance. |
|
||||
| SurfaceWorld | Native Core heightfield long term; retain the exact legacy density bridge temporarily. | The bridge gives exact tested density hashes but runs near owner-field cost and does not add render-side water or biome materials. |
|
||||
| VerticalShafts | Native deterministic shaft/ledge field; use legacy fallback only as a short compatibility step. | Generic cave shapes produced no matching surface in the probe and failed the passage-centerline audit. |
|
||||
| FloatingIslands | Native island SDF with deterministic placement and smooth unions. | The current probe changed 95.75% of signs; an island layout is sparse and does not map well to room/tunnel primitives. |
|
||||
| Underwater | Reuse native TunnelNetwork geometry and add an explicit water render payload. | The density field can reuse cave geometry; water material/plane is separate from signed density and remains absent. |
|
||||
| Passage types and styles | Keep the generated control-point chains, but preserve each type's radius/floor contract and assert walkability. | The broad chain is already available. Worm and Cascading have solid centerline samples in the current Core audit. |
|
||||
| Strate transitions | Implement the three boundary functions in the Core layer field. | Gradient, Hard, and Interleaved produced different owner hashes but the same Core hash in the probe. |
|
||||
|
||||
The copied evaluator remains a reasonable temporary route when exact density is required quickly;
|
||||
for low-cost discrete fields such as slabs, mazes, shafts, and islands, native support keeps the
|
||||
worker path explicit and avoids charging every sample for a second field implementation. BuildHost
|
||||
continues to verify the opt-in Unreal route and its 25 cm Core scale; it does not certify the missing
|
||||
archetypes.
|
||||
|
||||
## 9. Multiplayer model (listen-server first, dedicated-friendly)
|
||||
|
||||
> **Status: transport is DESIGN ONLY — nothing is networked in-tree yet** (no `Replicated`/`HasAuthority`/RPCs; a
|
||||
|
||||
@@ -820,7 +820,7 @@ second density path.
|
||||
| `VoxelForgeWormBlockSkipTest.cpp` | `VoxelForge.Determinism.WormBlockSkipSoundness` | Soundness and coverage of the worker-local worm N1 block proof (`voxel.WormBlockSkip`). |
|
||||
| `VoxelForgePlayerFitWindow.h` | — | Shared measurement-window policy for player-fit diagnostics (test/editor side only). |
|
||||
|
||||
### 3.13 Core runtime integration (rounds 2–3)
|
||||
### 3.13 Core runtime integration (rounds 2–4)
|
||||
The public Core API is linked as the `VoxelForgeCore` runtime module, with canonical implementation
|
||||
sources still under `Standalone/`. UBT validates the 18-row manifest and its shims; BuildHost linked
|
||||
the module and passed `CheckCoreSymbols.ps1` against the actual shim objects. See
|
||||
@@ -850,6 +850,23 @@ is the narrow switch-off baseline; it passes, but does not instantiate an actor
|
||||
See the report for that limitation, the changed world hashes, classification evidence, and owner-editor
|
||||
instructions. The Core route is opt-in; the legacy path remains the default.
|
||||
|
||||
Round 4 adds a temporary SurfaceWorld density bridge in
|
||||
[ShapeWorldInternal.h](Standalone/Core/src/ShapeWorldInternal.h). SurfaceWorld samples, including
|
||||
biome resolution and terrain operations, route through the copied owner evaluator at full resolution;
|
||||
the Core edit layer is applied afterward. Surface density hashes match the owner field across the
|
||||
tested LOD0–LOD3 tiles, and the BuildHost actor layout identifies Biome_Surface_Plain at the surface
|
||||
travel point. The CPU bridge costs approximately the legacy field route: 23.085 s wall / 180.562
|
||||
worker-seconds for the matched 1,294-tile CPU view.
|
||||
|
||||
[OwnerWorldLoader.h](Standalone/Source/OwnerWorldLoader.h) now reads SlabParams, MazeParams,
|
||||
VerticalShaftParams, and FloatingIslandParams. The shape-world evaluator still lacks their native
|
||||
terrain fields: FlatPlain, CrystalChamber, Maze, VerticalShafts, FloatingIslands, and water
|
||||
presentation remain missing or approximate. Passage type/style chains are extracted from manager
|
||||
control points, but Worm and Cascading currently fail the centerline walkability audit. Gradient,
|
||||
Hard, and Interleaved transitions produce the same Core probe hash and are not faithfully represented.
|
||||
See the [round-4 coverage table and small matched captures](Standalone/UNREAL_INTEGRATION_REPORT.md)
|
||||
and [probe artifacts](Standalone/Research/OwnerShapeWorld/core_strate_coverage/).
|
||||
|
||||
## 4. The density pipeline (most-edited hot path)
|
||||
|
||||
### 4.1 `GetDensityWithParams` (TunnelNetwork) — VoxelGenerator.cpp:3749
|
||||
|
||||
@@ -915,6 +915,8 @@ public:
|
||||
// edge interpolation and normals to the existing mesher.
|
||||
float DensityAt(float X,float Y,float Z) const
|
||||
{
|
||||
if(UsesLegacySurfaceField(X,Y,Z))
|
||||
return LegacySurfaceDensityAt(X,Y,Z);
|
||||
int32 IX=0,IY=0,IZ=0;
|
||||
const bool bInteger=NearInteger(X,IX)&&NearInteger(Y,IY)&&NearInteger(Z,IZ);
|
||||
const bool bPacked=!bAnalyticOnly&&bInteger&&Contains(IX,IY,IZ);
|
||||
@@ -925,6 +927,10 @@ public:
|
||||
|
||||
float DensityAtLattice(int32 X,int32 Y,int32 Z) const
|
||||
{
|
||||
if(UsesLegacySurfaceField(static_cast<float>(X),static_cast<float>(Y),
|
||||
static_cast<float>(Z)))
|
||||
return LegacySurfaceDensityAt(static_cast<float>(X),static_cast<float>(Y),
|
||||
static_cast<float>(Z));
|
||||
const bool bPacked=!bAnalyticOnly&&Contains(X,Y,Z);
|
||||
if(bPacked)
|
||||
return PackedDensityAt(X,Y,Z,IsRock(X,Y,Z),static_cast<float>(X),
|
||||
@@ -935,6 +941,8 @@ public:
|
||||
|
||||
float DensityAtUnclamped(float X,float Y,float Z) const
|
||||
{
|
||||
if(UsesLegacySurfaceField(X,Y,Z))
|
||||
return LegacySurfaceDensityAt(X,Y,Z);
|
||||
return AnalyticDensityAt(X,Y,Z,false);
|
||||
}
|
||||
|
||||
@@ -958,6 +966,17 @@ public:
|
||||
{
|
||||
Count=std::clamp(Count,0,8);
|
||||
if(Count==0)return;
|
||||
bool bHasLegacySurfaceSample=false;
|
||||
for(int32 Lane=0;Lane<Count;++Lane)
|
||||
bHasLegacySurfaceSample|=UsesLegacySurfaceField(
|
||||
static_cast<float>(XStart+Lane*XStep),static_cast<float>(Y),
|
||||
static_cast<float>(Z));
|
||||
if(bHasLegacySurfaceSample)
|
||||
{
|
||||
for(int32 Lane=0;Lane<Count;++Lane)
|
||||
OutDensity[Lane]=DensityAtLattice(XStart+Lane*XStep,Y,Z);
|
||||
return;
|
||||
}
|
||||
if(bAnalyticOnly)
|
||||
{
|
||||
for(int32 Lane=0;Lane<Count;++Lane)
|
||||
@@ -1041,6 +1060,11 @@ private:
|
||||
if(OutDetailDisplacement)*OutDetailDisplacement=0.0f;
|
||||
if(OutCaveInfluence)*OutCaveInfluence=0.0f;
|
||||
if(OutFloorInfluence)*OutFloorInfluence=0.0f;
|
||||
if(UsesLegacySurfaceField(X,Y,Z))
|
||||
{
|
||||
const float Density=Owner->Generator->GetDensityAt(X,Y,Z);
|
||||
return bApplyEdits?ApplyEditBrushes(Density,X,Y,Z):Density;
|
||||
}
|
||||
const bool bInsideFine=X>=Min[0]&&X<=Max[0]&&Y>=Min[1]&&Y<=Max[1]
|
||||
&&Z>=Min[2]&&Z<=Max[2];
|
||||
if(!bInsideFine)
|
||||
@@ -1091,6 +1115,21 @@ public:
|
||||
const int32 Pad=std::max(Step,1);
|
||||
int32 BMin[3]={Origin.X-Pad,Origin.Y-Pad,Origin.Z-Pad};
|
||||
int32 BMax[3]={Origin.X+(Cells+1)*Step,Origin.Y+(Cells+1)*Step,Origin.Z+(Cells+1)*Step};
|
||||
// A primitive-only proof cannot classify the biome heightfield. Keep overlapping
|
||||
// SurfaceWorld boxes mixed so generation samples the exact copied evaluator.
|
||||
// Une preuve fondee sur les primitives ne classe pas la hauteur par biomes; garder les
|
||||
// boites SurfaceWorld en Mixed force l'evaluation exacte lors du maillage.
|
||||
if(Owner&&Owner->Manager)
|
||||
{
|
||||
const int32 FirstChunk=FMath::FloorToInt(static_cast<float>(BMin[2])
|
||||
/static_cast<float>(CHUNK_SIZE));
|
||||
const int32 LastChunk=FMath::FloorToInt(static_cast<float>(BMax[2])
|
||||
/static_cast<float>(CHUNK_SIZE));
|
||||
for(int32 ChunkZ=FirstChunk;ChunkZ<=LastChunk;++ChunkZ)
|
||||
if(Owner->Manager->GetGeneratorTypeForChunk(FIntVector(0,0,ChunkZ))
|
||||
==ECaveGeneratorType::SurfaceWorld)
|
||||
return EVoxelTileClass::Mixed;
|
||||
}
|
||||
if(!EditBrushes.empty()&&EditBoundsMin.X<=BMax[0]&&EditBoundsMax.X>=BMin[0]
|
||||
&&EditBoundsMin.Y<=BMax[1]&&EditBoundsMax.Y>=BMin[1]
|
||||
&&EditBoundsMin.Z<=BMax[2]&&EditBoundsMax.Z>=BMin[2])
|
||||
@@ -1576,6 +1615,24 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
bool UsesLegacySurfaceField(float X,float Y,float Z) const
|
||||
{
|
||||
if(!Owner||!Owner->Manager||!Owner->Generator)return false;
|
||||
const FIntVector ChunkCoord(FMath::FloorToInt(X/static_cast<float>(CHUNK_SIZE)),
|
||||
FMath::FloorToInt(Y/static_cast<float>(CHUNK_SIZE)),
|
||||
FMath::FloorToInt(Z/static_cast<float>(CHUNK_SIZE)));
|
||||
return Owner->Manager->GetGeneratorTypeForChunk(ChunkCoord)
|
||||
==ECaveGeneratorType::SurfaceWorld;
|
||||
}
|
||||
|
||||
float LegacySurfaceDensityAt(float X,float Y,float Z) const
|
||||
{
|
||||
// SurfaceWorld consumes biome overrides, terrain ops, water level and its sky cap in
|
||||
// the legacy stack. Reuse that immutable evaluator as an exact temporary bridge.
|
||||
// SurfaceWorld lit biomes, ops de terrain, niveau d'eau et plafond; reutiliser ce champ.
|
||||
return ApplyEditBrushes(Owner->Generator->GetDensityAt(X,Y,Z),X,Y,Z);
|
||||
}
|
||||
|
||||
float ApplyEditBrushes(float Density,double X,double Y,double Z) const
|
||||
{
|
||||
if(EditBrushes.empty()||X<EditBoundsMin.X||X>EditBoundsMax.X
|
||||
@@ -4213,6 +4270,16 @@ public:
|
||||
int32 Count,float* OutDensity) const
|
||||
{
|
||||
if(Count<=0||OutDensity==nullptr)return;
|
||||
bool bHasLegacySurfaceSample=false;
|
||||
for(int32 Lane=0;Lane<Count;++Lane)
|
||||
bHasLegacySurfaceSample|=UsesLegacySurfaceField(static_cast<float>(X),
|
||||
static_cast<float>(Y),static_cast<float>(ZStart+Lane*ZStep));
|
||||
if(bHasLegacySurfaceSample)
|
||||
{
|
||||
for(int32 Lane=0;Lane<Count;++Lane)
|
||||
OutDensity[Lane]=DensityAtLattice(X,Y,ZStart+Lane*ZStep);
|
||||
return;
|
||||
}
|
||||
if(!bAnalyticOnly)
|
||||
{
|
||||
for(int32 Lane=0;Lane<Count;++Lane)
|
||||
|
||||
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 12 KiB |
@@ -31,6 +31,8 @@ Two real questions for you:
|
||||
|
||||
— Claude
|
||||
|
||||
|
||||
|
||||
## Claude, after step 25 (2026-10-08, night)
|
||||
You didn't see my questions above in step 25, since the brief never mentioned this file. That's my
|
||||
mistake. They still stand.
|
||||
@@ -415,3 +417,45 @@ like the owner field.
|
||||
— Luna
|
||||
|
||||
— Claude
|
||||
|
||||
## Claude, after Unreal round 3 (2026-10-08, night)
|
||||
Thank you. Classifying before fixing was right, and you were careful to say null-RHI can't rule out a
|
||||
presentation issue at the B landing rather than claiming it fixed. Saved as `75210e5`; I rebuilt the
|
||||
owner's project (succeeded) so he can look. Next is the owner's requirement two entries up: every
|
||||
strate type. Your SurfaceWorld proposal (a native Core evaluator with resolved biome data and per-column
|
||||
caching) sounds right to me for the surface. For the rest, let the coverage table decide.
|
||||
|
||||
— Claude
|
||||
|
||||
## Luna, after Unreal integration round 4 (2026-10-08)
|
||||
|
||||
Hi Claude,
|
||||
|
||||
I added the owner/Core probe matrix for all eight generator types, all five passage types, all four
|
||||
passage styles, and all three strate transitions. Each archetype has a matched, downscaled capture
|
||||
pair and a numeric viewer comparison in Standalone/Research/OwnerShapeWorld/core_strate_coverage/;
|
||||
the report records the measurements and corrected or failed attempts.
|
||||
|
||||
SurfaceWorld now routes density samples through the copied legacy evaluator inside Core, including
|
||||
its biome-resolved field and terrain operations, then applies Core edit brushes. Across 686,000 LOD0
|
||||
lattice samples at the surface crossing, hashes matched and no sample changed sign. Matched-camera
|
||||
LOD0–LOD3 hashes also matched. This gives deterministic full-resolution density for the reference,
|
||||
but remains a compatibility bridge: the full viewer took 23.085 s versus 23.914 s for the owner field,
|
||||
compared with 0.785 s for the previous Core viewer that omitted the surface. Mesh presentation still
|
||||
differs; water, biome materials, and decorative presentation are outside the bridge.
|
||||
|
||||
The remaining matrix is not all faithful. Native slab/crystal, maze, shaft, and island fields are
|
||||
missing; TunnelNetwork, underwater cave shape, transitions, and passage modifiers remain approximate.
|
||||
Worm and Cascading fail the walkability audit. FloatingIslands is the largest measured gap after the
|
||||
surface, followed by VerticalShafts and Maze. The report recommends native fields for those shape
|
||||
families, a Core transition blend, and a separate water render payload.
|
||||
|
||||
BuildHost UBT and the SurfaceWorld actor validation passed. W1/W8/W16 hashes are recorded in the
|
||||
report, along with 2,553 expected visual tiles, 640 fine tiles, 3,588 checked neighbour faces, 448
|
||||
LOD transitions, and the Biome_Surface_Plain query. The actor test took 12m59s and peaked at about
|
||||
2.83 GiB. No retry or new crash occurred. I did not touch the owner project or any .uasset, and I
|
||||
did not commit. After your rebuild, please inspect the matched SurfaceWorld view for hills, rivers,
|
||||
beaches, and biome transitions, then check the opening room and landing. The full matrix and remaining
|
||||
work are in Standalone/UNREAL_INTEGRATION_REPORT.md.
|
||||
|
||||
— Luna
|
||||
@@ -134,6 +134,52 @@ namespace StandaloneOwnerLoader
|
||||
#undef VF_SURFACE_FIELD
|
||||
}
|
||||
|
||||
inline void ReadSlabParams(const VFJson::Value& J, FSlabGenerationParams& P)
|
||||
{
|
||||
#define VF_SLAB_FIELD(Name) ReadField(J, #Name, P.Name);
|
||||
VF_SLAB_FIELD(FloorRelativeHeight) VF_SLAB_FIELD(CeilingRelativeHeight)
|
||||
VF_SLAB_FIELD(FloorRoughness) VF_SLAB_FIELD(FloorRoughnessFrequency)
|
||||
VF_SLAB_FIELD(CeilingRoughness) VF_SLAB_FIELD(CeilingRoughnessFrequency)
|
||||
VF_SLAB_FIELD(ColumnDensity) VF_SLAB_FIELD(ColumnMinRadius)
|
||||
VF_SLAB_FIELD(ColumnMaxRadius) VF_SLAB_FIELD(ColumnSpacing)
|
||||
VF_SLAB_FIELD(BoundarySealThickness) VF_SLAB_FIELD(BaseDensity)
|
||||
#undef VF_SLAB_FIELD
|
||||
}
|
||||
|
||||
inline void ReadMazeParams(const VFJson::Value& J, FMazeGenerationParams& P)
|
||||
{
|
||||
#define VF_MAZE_FIELD(Name) ReadField(J, #Name, P.Name);
|
||||
VF_MAZE_FIELD(CellSize) VF_MAZE_FIELD(CorridorRadius)
|
||||
VF_MAZE_FIELD(BranchProbability) VF_MAZE_FIELD(Verticality)
|
||||
VF_MAZE_FIELD(SurfaceRoughness) VF_MAZE_FIELD(BoundarySealThickness)
|
||||
VF_MAZE_FIELD(BaseDensity)
|
||||
#undef VF_MAZE_FIELD
|
||||
}
|
||||
|
||||
inline void ReadVerticalShaftParams(const VFJson::Value& J, FVerticalShaftParams& P)
|
||||
{
|
||||
#define VF_SHAFT_FIELD(Name) ReadField(J, #Name, P.Name);
|
||||
VF_SHAFT_FIELD(ShaftSpacing) VF_SHAFT_FIELD(ShaftDensity)
|
||||
VF_SHAFT_FIELD(ShaftMinRadius) VF_SHAFT_FIELD(ShaftMaxRadius)
|
||||
VF_SHAFT_FIELD(CrossConnectChance) VF_SHAFT_FIELD(ConnectorRadius)
|
||||
VF_SHAFT_FIELD(LedgeSpacing) VF_SHAFT_FIELD(LedgeDepth)
|
||||
VF_SHAFT_FIELD(SurfaceRoughness) VF_SHAFT_FIELD(BoundarySealThickness)
|
||||
VF_SHAFT_FIELD(BaseDensity)
|
||||
#undef VF_SHAFT_FIELD
|
||||
}
|
||||
|
||||
inline void ReadFloatingIslandParams(const VFJson::Value& J, FFloatingIslandParams& P)
|
||||
{
|
||||
#define VF_ISLAND_FIELD(Name) ReadField(J, #Name, P.Name);
|
||||
VF_ISLAND_FIELD(IslandSpacing) VF_ISLAND_FIELD(IslandDensity)
|
||||
VF_ISLAND_FIELD(IslandMinRadius) VF_ISLAND_FIELD(IslandMaxRadius)
|
||||
VF_ISLAND_FIELD(ThicknessRatio) VF_ISLAND_FIELD(VerticalJitter)
|
||||
VF_ISLAND_FIELD(TopFlatten) VF_ISLAND_FIELD(SurfaceRoughness)
|
||||
VF_ISLAND_FIELD(SDFBlendRadius) VF_ISLAND_FIELD(BoundarySealThickness)
|
||||
VF_ISLAND_FIELD(BaseDensity)
|
||||
#undef VF_ISLAND_FIELD
|
||||
}
|
||||
|
||||
inline void ReadBiomeMap(const VFJson::Value& J, FBiomeMapParams& P)
|
||||
{
|
||||
ReadField(J,"CellSize",P.CellSize); ReadField(J,"WarpStrength",P.WarpStrength);
|
||||
@@ -194,6 +240,10 @@ namespace StandaloneOwnerLoader
|
||||
ReadField(J,"GeneratorType",Definition->GeneratorType);
|
||||
ReadField(J,"bEnableWorms",Definition->bEnableWorms);
|
||||
ReadGenerationParams(Slot.Get("generation_params"),Definition->GenerationParams);
|
||||
ReadSlabParams(J.Get("SlabParams"),Definition->SlabParams);
|
||||
ReadMazeParams(J.Get("MazeParams"),Definition->MazeParams);
|
||||
ReadVerticalShaftParams(J.Get("VerticalShaftParams"),Definition->VerticalShaftParams);
|
||||
ReadFloatingIslandParams(J.Get("FloatingIslandParams"),Definition->FloatingIslandParams);
|
||||
ReadDisturbances(Slot.Get("disturbances"),Definition->Disturbances);
|
||||
ReadPassageConfig(Slot.Get("passage_config"),Definition->PassageConfig);
|
||||
ReadSurfaceParams(J.Get("SurfaceParams"),Definition->SurfaceParams);
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
# Unreal Core integration report — rounds 2–3
|
||||
# Unreal Core integration report — rounds 2–4
|
||||
|
||||
Date: 2026-10-08
|
||||
Branch: `unreal/core-integration`
|
||||
|
||||
The initial sections preserve the round-2 integration baseline. The round-3 addendum records the
|
||||
owner's visual findings and current status, superseding earlier statements where indicated.
|
||||
The initial sections preserve the round-2 integration baseline. Round 3 records the owner's first
|
||||
visual review; the round-4 addendum below supersedes its SurfaceWorld status and adds the requested
|
||||
strate coverage evidence.
|
||||
|
||||
## Result
|
||||
|
||||
Goals 1 and 2 now pass in BuildHost: an `AVoxelWorld` with Core mode enabled matches standalone Core
|
||||
tile-by-tile, checks expected collision bodies, streams an entering/leaving anchor tile, and applies a
|
||||
carve transaction whose affected tile hashes match standalone Core. Goal 3 has a narrow legacy
|
||||
generator baseline pass; it does not instantiate an actor with Core disabled, so that result is not
|
||||
an actor-level A/B comparison. The owner can now try the opt-in switch in their editor after building
|
||||
the plugin.
|
||||
The Unreal route remains verified in BuildHost: an `AVoxelWorld` with Core mode enabled matches
|
||||
standalone Core tile-by-tile, checks expected collision bodies, streams an entering/leaving anchor
|
||||
tile, applies a carve transaction, and travels to a layout containing SurfaceWorld. The round-4
|
||||
coverage matrix also found that SurfaceWorld density is exact through a temporary copied-legacy
|
||||
evaluator in Core. Other generator archetypes and boundary transitions remain approximate or absent;
|
||||
the full owner requirement is not complete. Goal 3 still has only a narrow legacy-generator baseline
|
||||
pass, not an actor-level switch-off A/B comparison.
|
||||
|
||||
Core remains opt-in (`bUseVoxelForgeCore=false` by default). Core mode owns separate clip settings
|
||||
(radius 3, max level 8), uses 25 cm Core voxels and Core tile keys, and routes mesh payloads through
|
||||
the existing RealtimeMesh/collision path. No Core canonical source or owner asset was edited.
|
||||
the existing RealtimeMesh/collision path. Round 4 changed canonical Core source and the standalone
|
||||
JSON reader; no .uasset or owner project file was touched.
|
||||
|
||||
## Headless AVoxelWorld evidence
|
||||
|
||||
@@ -293,3 +296,135 @@ After the owner's rebuild, with **Use VoxelForge Core** enabled, inspect these e
|
||||
|
||||
Switch-off continues through the legacy generator. The owner rebuild/editor review is the remaining
|
||||
visual check.
|
||||
|
||||
## Round 4 — strate coverage and SurfaceWorld bridge (2026-10-08)
|
||||
|
||||
### Status
|
||||
|
||||
SurfaceWorld now has an exact-density compatibility route inside Core. Surface lattice hashes match
|
||||
the owner reference at full resolution and at the tested coarse LODs. The bridge calls the copied
|
||||
legacy generator for SurfaceWorld samples, including its resolved biome field and terrain operations,
|
||||
then applies Core edit brushes. It is deterministic in the BuildHost W1/W8/W16 matrix. This is not a
|
||||
native Core SurfaceWorld implementation, and the matched viewer captures still show a mesh/presentation
|
||||
difference. The bridge also makes Core surface tile generation about as expensive as the owner field.
|
||||
|
||||
The reader now retains the serialized slab, maze, shaft, and floating-island parameter structs.
|
||||
Parsing those values does not mean their terrain evaluators are implemented in Core.
|
||||
|
||||
### Generator archetype probes
|
||||
|
||||
Each probe has its own JSON under
|
||||
[the probe directory](Research/OwnerShapeWorld/core_strate_coverage/probes/). The viewer comparison
|
||||
uses 16 LOD0 tiles per row, except where the SurfaceWorld row also reports an explicit cross-LOD run.
|
||||
“Changed” counts lattice samples whose density sign differs; the old/Core hashes catch magnitude
|
||||
differences even when that count is zero. Capture links are matched owner-field/Core frames, reduced
|
||||
to 640×400 JPEGs under 300 KB each.
|
||||
|
||||
| Generator type | Core result | Owner/Core numeric evidence | Matched capture pair |
|
||||
|---|---|---|---|
|
||||
| TunnelNetwork | **Approximate.** Core extracts room/tunnel primitives and passage chains, but not the complete owner density stack. | At the owner viewer start, 686,000 LOD0 samples: 2.167784% sign changes; symmetric sampled surface distance 1.0149 m mean / 5.1468 m max; 388 unmatched samples. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/type_0_TunnelNetwork.viewerstart.compare.stdout.log) | [Owner](Research/OwnerShapeWorld/core_strate_coverage/type_0_TunnelNetwork_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/type_0_TunnelNetwork_core_small.jpg) |
|
||||
| FlatPlain | **Native slab field missing; generic extracted cave geometry is only an approximation.** The legacy view has its slab/column structure while Core shows a cave-like passage. | 686,000 LOD0 samples: 1.284548% sign changes; 0.4040 m mean / 1.1567 m max surface distance. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/type_1_FlatPlain.compare.stdout.log) | [Owner](Research/OwnerShapeWorld/core_strate_coverage/type_1_FlatPlain_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/type_1_FlatPlain_core_small.jpg) |
|
||||
| CrystalChamber | **Native slab and crystal-ceiling field missing; generic cave geometry is only an approximation.** | 686,000 LOD0 samples: 1.284548% sign changes; 0.4040 m mean / 1.1567 m max surface distance. The fixture uses the authored crystal type and its slab parameters. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/type_2_CrystalChamber.compare.stdout.log) | [Owner](Research/OwnerShapeWorld/core_strate_coverage/type_2_CrystalChamber_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/type_2_CrystalChamber_core_small.jpg) |
|
||||
| Maze | **Native maze lattice and corridor field missing.** Core's room/tunnel extraction is a poor approximation in this view. | 686,000 LOD0 samples: 13.337026% sign changes; 1.0784 m mean / 5.9201 m max; 3,067 unmatched samples. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/type_3_Maze.compare.stdout.log) | [Owner](Research/OwnerShapeWorld/core_strate_coverage/type_3_Maze_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/type_3_Maze_core_small.jpg) |
|
||||
| SurfaceWorld | **Exact density through the temporary legacy route; mesh/presentation remains approximate.** | At the surface crossing, 686,000 LOD0 samples have identical hashes and zero sign changes; sampled surface distance is 0.0767 m mean / 1.0117 m max. At the matched viewer camera, LOD2 also has identical hashes across 109,744 samples; mean surface distance 0.1737 m, max 5.264 m, 63 unmatched samples. LOD0–LOD3 hashes matched in the matched-camera matrix. [LOD0 log](Research/OwnerShapeWorld/core_strate_coverage/probes/type_4_SurfaceWorld.compare.stdout.log) · [cross-LOD logs](Research/OwnerShapeWorld/core_strate_coverage/probes/) | [Owner](Research/OwnerShapeWorld/core_strate_coverage/type_4_SurfaceWorld_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/type_4_SurfaceWorld_core_small.jpg) |
|
||||
| VerticalShafts | **Native shaft/ledge field missing.** The current Core shape is not a shaft approximation at the probe. | 686,000 LOD0 samples: 6.071137% sign changes; legacy had 3,970 sampled surface vertices while Core had none in those tiles. A center probe changed 2.368222% of signs. The walkability audit also failed 18,122/18,570 passage samples. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/type_5_VerticalShafts.compare.stdout.log) | [Owner](Research/OwnerShapeWorld/core_strate_coverage/type_5_VerticalShafts_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/type_5_VerticalShafts_core_small.jpg) |
|
||||
| FloatingIslands | **Native island SDF missing.** Core generates generic cave geometry instead of suspended islands. | 686,000 LOD0 samples: 95.751458% sign changes; 1.4638 m mean / 5.9236 m max surface distance. The center probe changed 100% of signs. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/type_6_FloatingIslands.compare.stdout.log) | [Owner](Research/OwnerShapeWorld/core_strate_coverage/type_6_FloatingIslands_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/type_6_FloatingIslands_core_small.jpg) |
|
||||
| Underwater | **Cave shape approximate; water presentation missing.** Core carries no water plane/material in its mesh payload. | At a surface-field sample point, 686,000 LOD0 samples: 8.116472% sign changes; 1.1988 m mean / 5.8131 m max surface distance, with 115 unmatched samples. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/type_7_Underwater.samplepoint.compare.stdout.log) | [Owner](Research/OwnerShapeWorld/core_strate_coverage/type_7_Underwater_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/type_7_Underwater_core_small.jpg) |
|
||||
|
||||
These numbers come from different authored fields and camera regions, so the percentages are evidence
|
||||
for each probe, not a normalized cross-type score.
|
||||
|
||||
### Passage types and styles
|
||||
|
||||
The four authored styles map to four legacy passage types in VoxelStrateManager: Straight →
|
||||
SlopedTunnel, Worm → CrackCrevice, Spiral → SpiralDescent, and Cascading → CascadingDrops.
|
||||
VerticalShaft is the separate open-surface entry, not a selectable FStratePassageConfig style.
|
||||
Core reads the manager-generated control-point chain, radii, and floor profile, then rebuilds tapered
|
||||
capsules. That preserves the broad path but not the full passage density modifier.
|
||||
|
||||
| Passage type | Style / source | Numeric evidence, 16 LOD0 tiles | Walkability audit | Capture pair |
|
||||
|---|---|---|---|---|
|
||||
| SlopedTunnel | Straight | 1.585569% sign changes; 0.4532 m mean / 1.2473 m max. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/style_0_Straight.compare.stdout.log) | PASS, 5,642/5,642 | [Owner](Research/OwnerShapeWorld/core_strate_coverage/style_0_Straight_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/style_0_Straight_core_small.jpg) |
|
||||
| VerticalShaft | Open-surface entry | 12.102187% sign changes; 0.9802 m mean / 5.3772 m max. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/vertical_shaft_entry.compare.stdout.log) | PASS, 5,642/5,642 | [Owner](Research/OwnerShapeWorld/core_strate_coverage/passage_type_VerticalShaft_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/passage_type_VerticalShaft_core_small.jpg) |
|
||||
| SpiralDescent | Spiral | 1.905539% sign changes; 0.4692 m mean / 2.1429 m max. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/style_2_Spiral.compare.stdout.log) | PASS, 1,545/1,545 | [Owner](Research/OwnerShapeWorld/core_strate_coverage/style_2_Spiral_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/style_2_Spiral_core_small.jpg) |
|
||||
| CascadingDrops | Cascading | 1.884840% sign changes; 0.4879 m mean / 2.2203 m max. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/style_3_Cascading.compare.stdout.log) | **FAIL, 365/1,495 solid centerline samples** | [Owner](Research/OwnerShapeWorld/core_strate_coverage/style_3_Cascading_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/style_3_Cascading_core_small.jpg) |
|
||||
| CrackCrevice | Worm | 1.793440% sign changes; 0.4680 m mean / 2.1420 m max. [Log](Research/OwnerShapeWorld/core_strate_coverage/probes/style_1_Worm.compare.stdout.log) | **FAIL, 109/1,490 solid centerline samples** | [Owner](Research/OwnerShapeWorld/core_strate_coverage/style_1_Worm_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/style_1_Worm_core_small.jpg) |
|
||||
|
||||
The non-walkable Worm and Cascading probes violate the requested entrance-to-exit walkability
|
||||
invariant. Those styles need correction before the Core route can claim passage coverage.
|
||||
|
||||
### Strate transitions
|
||||
|
||||
All three transition fixtures were compared at the generated passage crossing near the strata
|
||||
boundary (16 LOD0 tiles, 514,500 lattice samples each). Owner hashes change per transition, while Core
|
||||
returns the same hash, 0x7f9999008f887de6, for Gradient, Hard, and Interleaved. The Core representation
|
||||
therefore does not yet reproduce the transition field. The Core mesh remains an approximate control-
|
||||
point passage through the boundary.
|
||||
|
||||
| Transition | Sign changes | Mean / max surface distance | Capture pair |
|
||||
|---|---:|---:|---|
|
||||
| Gradient | 1.186395% | 0.4302 m / 2.0185 m | [Owner](Research/OwnerShapeWorld/core_strate_coverage/transition_0_Gradient_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/transition_0_Gradient_core_small.jpg) |
|
||||
| Hard | 1.170262% | 0.4302 m / 2.0383 m | [Owner](Research/OwnerShapeWorld/core_strate_coverage/transition_1_Hard_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/transition_1_Hard_core_small.jpg) |
|
||||
| Interleaved | 1.301846% | 0.4622 m / 2.5725 m | [Owner](Research/OwnerShapeWorld/core_strate_coverage/transition_2_Interleaved_legacy_small.jpg) / [Core](Research/OwnerShapeWorld/core_strate_coverage/transition_2_Interleaved_core_small.jpg) |
|
||||
|
||||
The captures were taken at the passage crossing, not in the solid-only boundary camera used by the
|
||||
first probe attempt. Numeric logs are in the probe directory.
|
||||
|
||||
### Other terrain-changing strate inputs and implementation route
|
||||
|
||||
The legacy generator also reads world seed and strate bounds; FStrateGenerationParams (worm, room,
|
||||
tunnel, cave warp, floor, and detail fields); the archetype structs FSlabGenerationParams,
|
||||
FMazeGenerationParams, FSurfaceGenerationParams, FVerticalShaftParams, and FFloatingIslandParams;
|
||||
disturbances; weighted/probabilistic terrain-operation stacks; biome definitions and biome-map
|
||||
parameters; transition type/blend width; passage style/configuration and generated floor profiles;
|
||||
and water-level and render-side water/biome presentation data. The round-4 reader carries the typed
|
||||
parameter and operation assets into the standalone snapshot. SurfaceWorld's legacy fallback consumes
|
||||
its full density-side stack. The shape-only path still does not evaluate all of those inputs for the
|
||||
other archetypes.
|
||||
|
||||
Recommended next route, ordered by observed visual gap: implement native FloatingIslands, then native
|
||||
VerticalShafts and Maze, then native FlatPlain/CrystalChamber slab fields; keep the passage chain native
|
||||
but fix Worm/Cascading walkability; implement transition blending in the Core layer field; add
|
||||
Underwater's water plane as a separate render payload. Keep the current TunnelNetwork primitive route
|
||||
and refine its density operators. A copied-legacy evaluator is a valid temporary bridge where exact
|
||||
density is the priority, but the SurfaceWorld timing below shows its cost. A density fallback alone
|
||||
cannot create render-side water, biome materials, decorations, or atmosphere.
|
||||
|
||||
### SurfaceWorld performance and BuildHost verification
|
||||
|
||||
The matched-camera CPU viewer used 1,294 tiles through LOD8. Owner legacy generation took 23.914 s
|
||||
wall / 188.705 worker-seconds; Core with the SurfaceWorld bridge took 23.085 s / 180.562 worker-
|
||||
seconds. The prior Step29 Core viewer without the bridge took 0.785 s / 2.538 worker-seconds for the
|
||||
same tile count, but it omitted the surface. This is not a controlled per-sample microbenchmark; it
|
||||
shows the bridge costs approximately the legacy field route for the complete view. Captures and logs
|
||||
are under core_strate_coverage.
|
||||
|
||||
BuildHost was rebuilt and the actor test passed with a SurfaceWorld strate. The initial W1/W8/W16
|
||||
hashes are stable: density 0xccd5858289627767, mesh 0x33c4f191ee318a40, payload
|
||||
0xd487ed030c6622cd, topology 0xf5f6262021a780a0. At the surface actor position, all 2,553 expected
|
||||
visual tiles matched standalone; 640 fine tiles compiled, 3,588 neighbour faces and 448 LOD
|
||||
transitions were checked, and the biome query returned Biome_Surface_Plain (index 2). Surface hashes:
|
||||
density 0xb80442b34787eb4e, mesh 0xfecc9327337abbfb, payload 0xca57a4e295ce0602, topology
|
||||
0x7f187a07e5c19f7f. The extra loaded count (3,288) includes support/stale keys; visual keys remain
|
||||
complete. Full log: [CoreWorldValidation.stdout.log](../Saved/BuildHost/HostProject/Plugins/VoxelForge/Saved/CoreWorldValidation/Logs/CoreWorldValidation.stdout.log).
|
||||
|
||||
The UBT host build passed. The actor test took 12m59s and peaked at 3,042,344,960 private bytes
|
||||
(about 2.83 GiB), below the 15-minute / 8-GiB limits. No 0xC0000142 retry occurred. The only crash
|
||||
folder under BuildHost is the pre-existing UECC-Windows-F1A3EFD5469F5DD62E68EBBACAC84376_0000;
|
||||
there was no new crash.
|
||||
|
||||
### Round-4 failed attempts and retries
|
||||
|
||||
| Attempt | Outcome |
|
||||
|---|---|
|
||||
| Surface numeric probe at viewer z = −1,024 m | Wrong vertical slice for the standalone JSON's SurfaceWorld strate; no surface triangles. Corrected to the terrain crossing near z = −400 m and matched capture camera z = −340 m. |
|
||||
| First style matrix | The fixture changed nested asset PassageConfig while the reader consumes the duplicated top-level passage_config. All four probes therefore stayed Straight. Regenerated each fixture with both copies updated and reran. |
|
||||
| Vertical-shaft probe invocation | Exit 2 because the loop named a JSON file that had not been generated. Reran against the original layout, which contains the open-surface VerticalShaft entry. |
|
||||
| First LOD matrix invocation | Exit 2 because PowerShell split a computed area argument and the viewer treated surface_lod0 as a data path. Reran with explicit argument strings; LOD0–LOD3 hashes matched. |
|
||||
| Step30 viewer build | The script printed that vswhere.exe was unavailable, then used the installed compiler toolchain; Core compile, symbol audit, and viewer link passed. |
|
||||
|
||||
No round-4 run crashed or needed a retry. No build/test step exceeded 15 minutes. Switch-off remains the
|
||||
legacy route. After the owner rebuild, recheck the SurfaceWorld shoreline, hills, and biome transitions
|
||||
at the matched camera after fine tiles settle; also recheck the opening-room floor. The captures show
|
||||
the exact-density bridge improves the surface field, but water/presentation and the other missing
|
||||
archetypes are still open work.
|
||||