From 34ae1d71877554b5a812a7c45270d27f464caa6c Mon Sep 17 00:00:00 2001 From: Fr0zka Date: Tue, 20 Oct 2026 05:52:59 +0200 Subject: [PATCH] wip(L17, side branch): FloatingIslands seal-cap fix + owner/Core chunk-scale change (breaks SurfaceWorld) Not for assembler/world: the 8 m -> 4 m strate chunk change moves every stratum, so the SurfaceWorld spawn camera floats in a void and the L1 mesh export shrank 58.7 -> 31.7 MB. Kept for its diagnostics, the boundarySeal finding and the readable capture shading. See Linux17/REPORT.md. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX --- ARCHITECTURE.md | 22 ++ CODEMAP.md | 10 +- .../include/VoxelForgeCore/VoxelForgeCore.h | 4 +- Standalone/Core/src/ShapeWorldInternal.h | 195 +++++++++++++----- Standalone/Core/src/VoxelForgeCore.cpp | 12 +- .../WorldAssemblerM3/Linux17/BoundaryProbe.py | 89 ++++++++ .../Linux17/FloatingIslandDensityProbe.cpp | 143 +++++++++++++ .../WorldAssemblerM3/Linux17/MeasureBuild.py | 67 ++++++ .../WorldAssemblerM3/Linux17/MeshProbe.py | 100 +++++++++ .../WorldAssemblerM3/Linux17/OWNER_NOTE.md | 26 +++ .../WorldAssemblerM3/Linux17/REPORT.md | 182 ++++++++++++++++ .../WorldAssemblerM3/Linux17/RingProbe.py | 151 ++++++++++++++ .../WorldAssemblerM3/Linux17/RunMatrix.py | 120 +++++++++++ .../Linux17/boundary-after.txt | 27 +++ .../Linux17/boundary-before.txt | 35 ++++ .../floating-islands-flat-square-after.jpg | Bin 0 -> 47612 bytes .../floating-islands-flat-square-before.jpg | Bin 0 -> 70166 bytes .../floating-islands-island-view-after.jpg | Bin 0 -> 51429 bytes .../floating-islands-island-view-before.jpg | Bin 0 -> 70813 bytes .../surface-world-l1-readable-tiles.jpg | Bin 0 -> 53351 bytes .../Linux17/mesh-after-boundary-summary.txt | 13 ++ .../Linux17/mesh-after-summary.txt | 13 ++ .../Linux17/mesh-before-matched-summary.txt | 19 ++ .../Linux17/mesh-before-summary.txt | 19 ++ .../Linux17/mesh-sw-after-summary.txt | 12 ++ .../Linux17/mesh-sw-l1-after-summary.txt | 5 + .../Linux17/mesh-sw-l1-cap-after-summary.txt | 5 + .../mesh-sw-l1-ground-after-summary.txt | 5 + Standalone/Source/LinuxOffscreenCapture.cpp | 124 ++++++++++- Standalone/Source/StreamBenchmarkHeadless.cpp | 25 +++ 30 files changed, 1353 insertions(+), 70 deletions(-) create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/BoundaryProbe.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/FloatingIslandDensityProbe.cpp create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/MeasureBuild.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/MeshProbe.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/OWNER_NOTE.md create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/REPORT.md create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/RingProbe.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/RunMatrix.py create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/boundary-after.txt create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/boundary-before.txt create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/captures/floating-islands-flat-square-after.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/captures/floating-islands-flat-square-before.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/captures/floating-islands-island-view-after.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/captures/floating-islands-island-view-before.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/captures/surface-world-l1-readable-tiles.jpg create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/mesh-after-boundary-summary.txt create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/mesh-after-summary.txt create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/mesh-before-matched-summary.txt create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/mesh-before-summary.txt create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-after-summary.txt create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-after-summary.txt create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-cap-after-summary.txt create mode 100644 Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-ground-after-summary.txt diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 9a4bcbd..6afa382 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1840,6 +1840,28 @@ fill and check page tiles against the evaluator they actually sample. This is th the Unreal adapter and its asynchronous MPSC/Epoch flow are unchanged. See [`Standalone/Research/WorldAssemblerM3/Linux13/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux13/REPORT.md). +### 8.37 Owner/Core stratum coordinates and FloatingIslands boundaries — World Assembler M3 L17 + +Manager chunk coordinates are in owner chunks, while Core density positions are Core voxels. Convert +between them with `32 * OwnerVoxelSizeMicrons / CoreVoxelSizeMicrons`; do not divide Core positions +by `CHUNK_SIZE` directly. The L17 owner snapshot uses 0.125 m owner voxels and 0.25 m Core voxels, +so one owner chunk is 16 Core voxels (4 m), not 32 (8 m). The old hard-coded divisor doubled the +manifest's vertical stratum bounds and misplaced native-only readiness queries. + +FloatingIslands is the sparse `FloatingIslandFieldV1` manifest route. Its 0.5 m `boundarySeal` +limits feature influence; it is not a signed solid cap across the whole XY plane. Applying it as a +solid cap produced a false top at +3.5 m, while the doubled legacy layer bound also produced a cap at ++8 m. SurfaceWorld remains the planar `Heightfield2D` field with its independent ground and cap +surfaces. Adjacent native FI/SW strata now clip their signed distances to the same physical owner +boundary, preserving exact surface signs and height through the mesh sample lattice. + +The output change increments `WorldAssemblyEvaluatorVersion` from 6 to 7; the plan schema and +recipe geometry version stay unchanged because their inputs did not change. The L17 probes found +zero cave/floor influence at the false square and at the sampled island ground. The shared Core +coordinate conversion also changes SurfaceWorld native readiness and hashes where the previous +mapping selected the wrong route. See +[`Standalone/Research/WorldAssemblerM3/Linux17/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux17/REPORT.md). + ## 9. Multiplayer model (listen-server first, dedicated-friendly) > **Status: transport is DESIGN ONLY — nothing is networked in-tree yet** (no `Replicated`/`HasAuthority`/RPCs; a diff --git a/CODEMAP.md b/CODEMAP.md index 2d0f7e7..d01af0d 100644 --- a/CODEMAP.md +++ b/CODEMAP.md @@ -1132,11 +1132,19 @@ Implementation and evidence: [`Standalone/Research/WorldAssemblerM3/Linux9/REPOR | Symbol | Canonical file | Role | |---|---|---| -| `FStandaloneShapeWorld::SetSharedDensitySource`, `SharedDensitySource` | `Standalone/Core/src/ShapeWorldInternal.h`, bound before publication in `Standalone/Core/src/VoxelForgeCore.cpp` | Makes compiled analytic pages delegate field, lattice, detail, classification, and solid queries to the Core world's base shape; `WorldAssemblyEvaluatorVersion` is 6. | +| `FStandaloneShapeWorld::SetSharedDensitySource`, `SharedDensitySource` | `Standalone/Core/src/ShapeWorldInternal.h`, bound before publication in `Standalone/Core/src/VoxelForgeCore.cpp` | Makes compiled analytic pages delegate field, lattice, detail, classification, and solid queries to the Core world's base shape; `WorldAssemblyEvaluatorVersion` is 7. | The base manifest field is authoritative for tile generation and exact queries. See ARCHITECTURE §8.36 and [`Standalone/Research/WorldAssemblerM3/Linux13/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux13/REPORT.md). +### 3.23 Owner/Core stratum coordinates — World Assembler M3 L17 + +`FStandaloneShapeWorld::GetCoreVoxelsPerOwnerChunk` is the shared conversion for manager chunk +lookups, manifest layer bounds, readiness proofs, and adjacent native strata. FloatingIslands uses +`FloatingIslandFieldV1`; its boundary seal bounds feature influence and does not fill an XY-wide +solid cap. SurfaceWorld remains the `Heightfield2D` path. See ARCHITECTURE §8.37 and +[`Standalone/Research/WorldAssemblerM3/Linux17/REPORT.md`](Standalone/Research/WorldAssemblerM3/Linux17/REPORT.md). + ## 4. The density pipeline (most-edited hot path) ### 4.1 `GetDensityWithParams` (TunnelNetwork) — VoxelGenerator.cpp:3749 diff --git a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h index d46e08d..7b5d663 100644 --- a/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h +++ b/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h @@ -249,8 +249,8 @@ namespace VoxelForgeCore // L'assembleur v1 encode coordonnees et scalaires en 1/256 de voxel, independamment des tuiles. inline constexpr std::int64_t WorldAssemblySubvoxelsPerVoxel = 256; inline constexpr std::uint32_t WorldAssemblySchemaVersion = 1; - // Version 6 binds every compiled tile page to the world's base density evaluator. - inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 6; + // Version 7 fixes owner/Core chunk mapping and native adjacent-stratum boundaries. + inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 7; enum class FieldChannel : std::uint32_t { diff --git a/Standalone/Core/src/ShapeWorldInternal.h b/Standalone/Core/src/ShapeWorldInternal.h index f05f7ee..74d1aa5 100644 --- a/Standalone/Core/src/ShapeWorldInternal.h +++ b/Standalone/Core/src/ShapeWorldInternal.h @@ -47,6 +47,18 @@ public: return static_cast(CHUNK_SIZE) * OwnerVoxelSizeCm / GetCoreVoxelSizeCm(); } + int32 OwnerChunkLowerBoundaryCoreVoxel(int32 ChunkZ) const + { + return static_cast(std::floor( + static_cast(ChunkZ) * GetCoreVoxelsPerOwnerChunk())); + } + + int32 OwnerChunkUpperBoundaryCoreVoxel(int32 ChunkZ) const + { + return static_cast(std::ceil( + static_cast(ChunkZ) * GetCoreVoxelsPerOwnerChunk())); + } + enum class EDetailVariant : uint8 { Coherent, Smooth, PerVoxel }; struct FBoxClassification { @@ -712,14 +724,21 @@ public: if(Owner&&Owner->Manager) { const double TileZ0=Origin.Z,TileZ1=Origin.Z+static_cast(Cells)*Step; + const double CoreVoxelsPerOwnerChunk=GetCoreVoxelsPerOwnerChunk(); for(const FStrateSlot& Slot:Owner->Manager->GetLayout()) { + const int32 MidChunkZ=(Slot.TopChunkZ+Slot.BottomChunkZ)/2; + if(bUseNativeManifestFields + &&Owner->Manager->GetGeneratorTypeForChunk(FIntVector(0,0,MidChunkZ)) + ==ECaveGeneratorType::FloatingIslands) + continue; const FStrateGenerationParams Params=Owner->Manager->GetGenerationParams( - FIntVector(0,0,(Slot.TopChunkZ+Slot.BottomChunkZ)/2)); + FIntVector(0,0,MidChunkZ)); const float HalfWidth=static_cast(std::max(8.0, static_cast(Params.BoundarySealThickness)+8.0)); - const float Boundaries[2]={static_cast(Slot.BottomChunkZ)*CHUNK_SIZE, - static_cast(Slot.TopChunkZ+1)*CHUNK_SIZE}; + const float Boundaries[2]={ + static_cast(static_cast(Slot.BottomChunkZ)*CoreVoxelsPerOwnerChunk), + static_cast(static_cast(Slot.TopChunkZ+1)*CoreVoxelsPerOwnerChunk)}; for(const float Z:Boundaries) if(Z+HalfWidth>=TileZ0&&Z-HalfWidth<=TileZ1) Out.stratumBoundaries.push_back({Z,HalfWidth}); @@ -1028,19 +1047,21 @@ public: float NativeDensity=0.0f; if(!NativeSurfaceDensityAt(X,Y,Z,NativeDensity)) {RecordNativeOnlyViolation();return 0.0f;} - return NativeDensity; + return ApplyAdjacentStratumBoundary(X,Y,Z,NativeDensity,false); } float IslandDensity=0.0f; if(NativeFloatingIslandDensityAt(X,Y,Z,IslandDensity)) { ++ThreadClassificationStats().NativeFloatFieldCalls; - return ApplyEditBrushes(IslandDensity,X,Y,Z); + return ApplyEditBrushes(ApplyAdjacentStratumBoundary( + X,Y,Z,IslandDensity,true),X,Y,Z); } float NativeDensity=0.0f; if(NativeSurfaceDensityAt(X,Y,Z,NativeDensity)) { ++ThreadClassificationStats().NativeFloatFieldCalls; - return ApplyEditBrushes(NativeDensity,X,Y,Z); + return ApplyEditBrushes(ApplyAdjacentStratumBoundary( + X,Y,Z,NativeDensity,false),X,Y,Z); } if(UsesLegacySurfaceField(X,Y,Z)) return LegacySurfaceDensityAt(X,Y,Z); @@ -1064,21 +1085,27 @@ public: if(!NativeSurfaceDensityAt(static_cast(X),static_cast(Y), static_cast(Z),NativeDensity)) {RecordNativeOnlyViolation();return 0.0f;} - return NativeDensity; + return ApplyAdjacentStratumBoundary( + static_cast(X),static_cast(Y),static_cast(Z), + NativeDensity,false); } float IslandDensity=0.0f; if(NativeFloatingIslandDensityAt(static_cast(X),static_cast(Y), static_cast(Z),IslandDensity)) { ++ThreadClassificationStats().NativeLatticeFieldCalls; - return ApplyEditBrushes(IslandDensity,X,Y,Z); + return ApplyEditBrushes(ApplyAdjacentStratumBoundary( + static_cast(X),static_cast(Y),static_cast(Z), + IslandDensity,true),X,Y,Z); } float NativeDensity=0.0f; if(NativeSurfaceDensityAt(static_cast(X),static_cast(Y), static_cast(Z),NativeDensity)) { ++ThreadClassificationStats().NativeLatticeFieldCalls; - return ApplyEditBrushes(NativeDensity,X,Y,Z); + return ApplyEditBrushes(ApplyAdjacentStratumBoundary( + static_cast(X),static_cast(Y),static_cast(Z), + NativeDensity,false),X,Y,Z); } if(UsesLegacySurfaceField(static_cast(X),static_cast(Y), static_cast(Z))) @@ -1102,19 +1129,21 @@ public: float NativeDensity=0.0f; if(!NativeSurfaceDensityAt(X,Y,Z,NativeDensity)) {RecordNativeOnlyViolation();return 0.0f;} - return NativeDensity; + return ApplyAdjacentStratumBoundary(X,Y,Z,NativeDensity,false); } float IslandDensity=0.0f; if(NativeFloatingIslandDensityAt(X,Y,Z,IslandDensity)) { ++ThreadClassificationStats().NativeUnclampedFieldCalls; - return ApplyEditBrushes(IslandDensity,X,Y,Z); + return ApplyEditBrushes(ApplyAdjacentStratumBoundary( + X,Y,Z,IslandDensity,true),X,Y,Z); } float NativeDensity=0.0f; if(NativeSurfaceDensityAt(X,Y,Z,NativeDensity)) { ++ThreadClassificationStats().NativeUnclampedFieldCalls; - return ApplyEditBrushes(NativeDensity,X,Y,Z); + return ApplyEditBrushes(ApplyAdjacentStratumBoundary( + X,Y,Z,NativeDensity,false),X,Y,Z); } if(UsesLegacySurfaceField(X,Y,Z)) return LegacySurfaceDensityAt(X,Y,Z); @@ -1260,12 +1289,18 @@ private: if(OutFloorInfluence)*OutFloorInfluence=0.0f; float IslandDensity=0.0f; if(NativeFloatingIslandDensityAt(X,Y,Z,IslandDensity)) + { + IslandDensity=ApplyAdjacentStratumBoundary(X,Y,Z,IslandDensity,true); return bApplyEdits?ApplyEditBrushes(IslandDensity,X,Y,Z):IslandDensity; + } if(UsesLegacySurfaceField(X,Y,Z)) { float NativeDensity=0.0f; if(NativeSurfaceDensityAt(X,Y,Z,NativeDensity)) + { + NativeDensity=ApplyAdjacentStratumBoundary(X,Y,Z,NativeDensity,false); return bApplyEdits?ApplyEditBrushes(NativeDensity,X,Y,Z):NativeDensity; + } const float Density=Owner->Generator->GetDensityAt(X,Y,Z); return bApplyEdits?ApplyEditBrushes(Density,X,Y,Z):Density; } @@ -1321,8 +1356,11 @@ public: return SharedDensitySource->GetNativeSurfaceHeightsAt(X,Y,ChunkZ,OutGroundZ,OutCeilingZ); if(!WorldAssembly||!Owner||!Owner->Manager||!Owner->Generator ||!std::isfinite(X)||!std::isfinite(Y))return false; - const std::int64_t chunkMinimum=static_cast(ChunkZ)*CHUNK_SIZE; - const std::int64_t chunkMaximum=chunkMinimum+CHUNK_SIZE; + const double CoreVoxelsPerOwnerChunk=GetCoreVoxelsPerOwnerChunk(); + const std::int64_t chunkMinimum=static_cast(std::floor( + static_cast(ChunkZ)*CoreVoxelsPerOwnerChunk)); + const std::int64_t chunkMaximum=static_cast(std::ceil( + static_cast(ChunkZ+1)*CoreVoxelsPerOwnerChunk)); if(bNativeOnly&&(!NativeOnlyContainsColumn(X,Y) ||chunkMaximumNativeOnlyMaximum.Z ||Owner->Manager->GetGeneratorTypeForChunk(FIntVector(0,0,ChunkZ)) @@ -1344,7 +1382,8 @@ public: const VoxelForgeCore::Heightfield2D Block(WorldAssembly->recipe,*Plan); if(!Block.isValid())return false; const auto Column=Block.point(ToFixed(X),ToFixed(Y), - static_cast(ChunkZ)*CHUNK_SIZE*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel); + static_cast(std::llround(static_cast(ChunkZ) + *CoreVoxelsPerOwnerChunk*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel))); OutGroundZ=static_cast(Column.groundHeightSubvoxels/Scale); OutCeilingZ=static_cast(Column.capHeightSubvoxels/Scale); return std::isfinite(OutGroundZ)&&std::isfinite(OutCeilingZ); @@ -1360,10 +1399,11 @@ public: const int32 Pad=std::max(Step,1); const int32 BMin=Origin.Z-Pad; const int32 BMax=Origin.Z+(Cells+1)*Step; + const double CoreVoxelsPerOwnerChunk=GetCoreVoxelsPerOwnerChunk(); const int32 FirstChunk=FMath::FloorToInt(static_cast(BMin) - /static_cast(CHUNK_SIZE)); + /static_cast(CoreVoxelsPerOwnerChunk)); const int32 LastChunk=FMath::FloorToInt(static_cast(BMax) - /static_cast(CHUNK_SIZE)); + /static_cast(CoreVoxelsPerOwnerChunk)); const VoxelForgeCore::WorldAssemblyStratumPlanV1* Plan=nullptr; for(int32 ChunkZ=FirstChunk;ChunkZ<=LastChunk;++ChunkZ) { @@ -1407,12 +1447,13 @@ public: bool bIslandOtherStrateOverlap=false,bBadPlan=false; if(Owner&&Owner->Manager) { - // Keep the delivered SurfaceWorld chunk mapping unchanged. - // Conserver le mapping de chunks SurfaceWorld deja livre. + // All manifest strata use the same resolved owner-chunk to Core-voxel scale. + // Toutes les strates du manifeste partagent l'echelle owner/Core resolue. + const double CoreVoxelsPerOwnerChunk=GetCoreVoxelsPerOwnerChunk(); const int32 FirstChunk=FMath::FloorToInt(static_cast(BMin[2]) - /static_cast(CHUNK_SIZE)); + /static_cast(CoreVoxelsPerOwnerChunk)); const int32 LastChunk=FMath::FloorToInt(static_cast(BMax[2]) - /static_cast(CHUNK_SIZE)); + /static_cast(CoreVoxelsPerOwnerChunk)); for(int32 ChunkZ=FirstChunk;ChunkZ<=LastChunk;++ChunkZ) { const ECaveGeneratorType Type=Owner->Manager->GetGeneratorTypeForChunk( @@ -1544,19 +1585,6 @@ public: { if(!IslandPlan)return Finish(EVoxelTileClass::Mixed,true); constexpr std::int64_t Scale=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel; - const std::int64_t Bottom=IslandPlan->manifest.recipe.layoutMinimumZSubvoxels; - const std::int64_t Top=IslandPlan->manifest.recipe.layoutMaximumZSubvoxels; - const std::int64_t Seal=IslandPlan->manifest.recipe.boundarySealSubvoxels; - const std::int64_t BoxBottom=static_cast(BMin[2])*Scale; - const std::int64_t BoxTop=static_cast(BMax[2])*Scale; - const bool bBottomSealOverlap=BoxBottom=Bottom; - const bool bTopSealOverlap=BoxBottom<=Top&&BoxTop>Top-Seal; - if(bBottomSealOverlap) - return Finish(BoxBottom>=Bottom&&BoxTop<=Bottom+Seal - ?EVoxelTileClass::AllSolid:EVoxelTileClass::Mixed); - if(bTopSealOverlap) - return Finish(BoxBottom>=Top-Seal&&BoxTop<=Top - ?EVoxelTileClass::AllSolid:EVoxelTileClass::Mixed); const VoxelForgeCore::FloatingIslandFieldV1 Block( IslandPlan->manifest.recipe,IslandPlan->manifest.plan); if(!Block.isValid())return Finish(EVoxelTileClass::Mixed,true); @@ -2079,7 +2107,8 @@ private: { if(!bUseNativeManifestFields||!WorldAssembly||!Owner||!Owner->Manager||!Owner->Generator ||!std::isfinite(X)||!std::isfinite(Y)||!std::isfinite(Z))return false; - const int32 ChunkZ=FMath::FloorToInt(Z/static_cast(CHUNK_SIZE)); + const int32 ChunkZ=FMath::FloorToInt(Z + /static_cast(GetCoreVoxelsPerOwnerChunk())); if(Owner->Manager->GetGeneratorTypeForChunk(FIntVector(0,0,ChunkZ)) !=ECaveGeneratorType::SurfaceWorld)return false; const int32 StrateIndex=Owner->Manager->GetStrateIndex( @@ -2125,23 +2154,79 @@ private: const VoxelForgeCore::FloatingIslandFieldV1 Field( Plan->manifest.recipe,Plan->manifest.plan); if(!Field.isValid())return false; - std::int64_t Density=Field.densitySubvoxels(ToFixed(X),ToFixed(Y),ToFixed(Z)); - const std::int64_t Bottom=Plan->manifest.recipe.layoutMinimumZSubvoxels; - const std::int64_t Top=Plan->manifest.recipe.layoutMaximumZSubvoxels; - const std::int64_t Seal=Plan->manifest.recipe.boundarySealSubvoxels; - const std::int64_t Zq=ToFixed(Z); - if(Zq>=Bottom&&Zq(1,Zq-Bottom)); - if(Zq<=Top&&Zq>Top-Seal)Density=std::min(Density,-std::max(1,Top-Zq)); + // The recipe's boundary seal is a feature margin, not a horizontal solid cap. + // La marge de scellement du plan borne ses formes, sans remplir tout le plan XY. + const std::int64_t Density=Field.densitySubvoxels(ToFixed(X),ToFixed(Y),ToFixed(Z)); OutDensity=static_cast(static_cast(Density)/Scale); return std::isfinite(OutDensity); } + float ApplyAdjacentStratumBoundary(float X,float Y,float Z,float Density, + bool bFloatingIsland) const + { + if(!bUseNativeManifestFields||!WorldAssembly||!Owner||!Owner->Manager + ||!std::isfinite(X)||!std::isfinite(Y)||!std::isfinite(Z))return Density; + const double CoreVoxelsPerOwnerChunk=GetCoreVoxelsPerOwnerChunk(); + const int32 ChunkZ=FMath::FloorToInt(Z/static_cast(CoreVoxelsPerOwnerChunk)); + const ECaveGeneratorType CurrentType=Owner->Manager->GetGeneratorTypeForChunk( + FIntVector(0,0,ChunkZ)); + if(bFloatingIsland&&CurrentType==ECaveGeneratorType::FloatingIslands) + { + const int32 StrateIndex=Owner->Manager->GetStrateIndex( + static_cast((static_cast(ChunkZ)*CHUNK_SIZE+CHUNK_SIZE/2)*VOXEL_SIZE)); + const auto* Plan=FindWorldAssemblyFloatingIslandStratum(StrateIndex,ChunkZ); + if(!Plan)return Density; + const int32 LowerChunk=Plan->bottomChunkZ-1; + if(Owner->Manager->GetGeneratorTypeForChunk(FIntVector(0,0,LowerChunk)) + !=ECaveGeneratorType::SurfaceWorld)return Density; + const double Boundary=static_cast(Plan->bottomChunkZ) + *CoreVoxelsPerOwnerChunk; + float LowerDensity=0.0f,UpperDensity=0.0f; + if(!NativeSurfaceDensityAt(X,Y,static_cast(Boundary-0.5),LowerDensity) + ||!NativeFloatingIslandDensityAt(X,Y,static_cast(Boundary+0.5),UpperDensity) + ||(LowerDensity<0.0f)==(UpperDensity<0.0f))return Density; + + // Clip the two signed-distance fields to their shared owner-stratum plane. + // This keeps a solid-below/air-above seam continuous at every mesh sample step. + // Les deux champs sont limites au plan commun, quel que soit le pas de maillage. + const float Plane=static_cast(static_cast(Z)-Boundary); + return LowerDensity<0.0f?std::min(Density,Plane) + :std::max(Density,-Plane); + } + if(!bFloatingIsland&&CurrentType==ECaveGeneratorType::SurfaceWorld) + { + const int32 StrateIndex=Owner->Manager->GetStrateIndex( + static_cast((static_cast(ChunkZ)*CHUNK_SIZE+CHUNK_SIZE/2)*VOXEL_SIZE)); + const auto* Plan=FindWorldAssemblyStratum(StrateIndex,ChunkZ); + if(!Plan)return Density; + const int32 UpperChunk=Plan->topChunkZ+1; + if(Owner->Manager->GetGeneratorTypeForChunk(FIntVector(0,0,UpperChunk)) + !=ECaveGeneratorType::FloatingIslands)return Density; + const auto* UpperPlan=FindWorldAssemblyFloatingIslandStratum( + Owner->Manager->GetStrateIndex(static_cast(( + static_cast(UpperChunk)*CHUNK_SIZE+CHUNK_SIZE/2)*VOXEL_SIZE)),UpperChunk); + if(!UpperPlan)return Density; + const double Boundary=static_cast(UpperPlan->bottomChunkZ) + *CoreVoxelsPerOwnerChunk; + float LowerDensity=0.0f,UpperDensity=0.0f; + if(!NativeSurfaceDensityAt(X,Y,static_cast(Boundary-0.5),LowerDensity) + ||!NativeFloatingIslandDensityAt(X,Y,static_cast(Boundary+0.5),UpperDensity) + ||(LowerDensity<0.0f)==(UpperDensity<0.0f))return Density; + + const float Plane=static_cast(static_cast(Z)-Boundary); + return LowerDensity<0.0f?std::max(Density,Plane) + :std::min(Density,-Plane); + } + return Density; + } + 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(CHUNK_SIZE)), - FMath::FloorToInt(Y/static_cast(CHUNK_SIZE)), - FMath::FloorToInt(Z/static_cast(CHUNK_SIZE))); + const float CoreVoxelsPerOwnerChunk=static_cast(GetCoreVoxelsPerOwnerChunk()); + const FIntVector ChunkCoord(FMath::FloorToInt(X/CoreVoxelsPerOwnerChunk), + FMath::FloorToInt(Y/CoreVoxelsPerOwnerChunk), + FMath::FloorToInt(Z/CoreVoxelsPerOwnerChunk)); return Owner->Manager->GetGeneratorTypeForChunk(ChunkCoord) ==ECaveGeneratorType::SurfaceWorld; } @@ -2351,19 +2436,26 @@ private: int32 Top=MIN_int32,Bottom=MAX_int32; for(const FStrateSlot& Slot:Layout) { + const int32 MidChunkZ=(Slot.TopChunkZ+Slot.BottomChunkZ)/2; + // A manifest-backed FloatingIslands stratum supplies its own sparse island + // field; it must not extend the legacy solid envelope across the open sky. + if(bUseNativeManifestFields + &&Owner->Manager->GetGeneratorTypeForChunk(FIntVector(0,0,MidChunkZ)) + ==ECaveGeneratorType::FloatingIslands) + continue; Top=std::max(Top,Slot.TopChunkZ);Bottom=std::min(Bottom,Slot.BottomChunkZ); if(!Slot.Definition)continue; - const int32 MidChunkZ=(Slot.TopChunkZ+Slot.BottomChunkZ)/2; FLayerField Field; - Field.Lo=Slot.BottomChunkZ*CHUNK_SIZE; - Field.Hi=(Slot.TopChunkZ+1)*CHUNK_SIZE; + Field.Lo=OwnerChunkLowerBoundaryCoreVoxel(Slot.BottomChunkZ); + Field.Hi=OwnerChunkUpperBoundaryCoreVoxel(Slot.TopChunkZ+1); Field.StrateIndex=Slot.StrateIndex; Field.Params=Owner->Manager->GetGenerationParams(FIntVector(0,0,MidChunkZ)); LayerFields.push_back(std::move(Field)); } if(Top>=Bottom) { - LayerRanges.push_back({Bottom*CHUNK_SIZE,(Top+1)*CHUNK_SIZE}); + LayerRanges.push_back({OwnerChunkLowerBoundaryCoreVoxel(Bottom), + OwnerChunkUpperBoundaryCoreVoxel(Top+1)}); } } @@ -3474,8 +3566,9 @@ private: auto Unit=[&](uint32 H){return static_cast(Hash(H)>>8)*(1.0/16777216.0);}; for(const FStrateSlot& Slot:Layout) { - const double ZBottom=static_cast(Slot.BottomChunkZ)*CHUNK_SIZE; - const double ZTop=static_cast(Slot.TopChunkZ+1)*CHUNK_SIZE; + const double CoreVoxelsPerOwnerChunk=GetCoreVoxelsPerOwnerChunk(); + const double ZBottom=static_cast(Slot.BottomChunkZ)*CoreVoxelsPerOwnerChunk; + const double ZTop=static_cast(Slot.TopChunkZ+1)*CoreVoxelsPerOwnerChunk; for(int32 GY=GY0;GY<=GY1;++GY)for(int32 GX=GX0;GX<=GX1;++GX) { uint32 H=Hash(Seed^static_cast(GX)*0x9E3779B9u diff --git a/Standalone/Core/src/VoxelForgeCore.cpp b/Standalone/Core/src/VoxelForgeCore.cpp index 1952e96..7feed8d 100644 --- a/Standalone/Core/src/VoxelForgeCore.cpp +++ b/Standalone/Core/src/VoxelForgeCore.cpp @@ -1162,8 +1162,13 @@ namespace VoxelForgeCore const std::int64_t tileMinimum[3]={boundsMin.X,boundsMin.Y,boundsMin.Z}; const std::int64_t tileMaximum[3]={boundsMax.X,boundsMax.Y,boundsMax.Z}; - const int32 firstSurfaceChunk=FloorDiv(boundsMin.Z,CHUNK_SIZE); - const int32 lastSurfaceChunk=FloorDiv(boundsMax.Z,CHUNK_SIZE); + const double coreVoxelsPerOwnerChunk=static_cast(CHUNK_SIZE) + *static_cast(impl_->owner->OwnerVoxelSizeMicrons) + /static_cast(std::max(1u,impl_->owner->CoreVoxelSizeMicrons)); + const int32 firstSurfaceChunk=FMath::FloorToInt( + static_cast(boundsMin.Z)/coreVoxelsPerOwnerChunk); + const int32 lastSurfaceChunk=FMath::FloorToInt( + static_cast(boundsMax.Z)/coreVoxelsPerOwnerChunk); const WorldAssemblyStratumPlanV1* selectedPlan=nullptr; for(int32 chunkZ=firstSurfaceChunk;chunkZ<=lastSurfaceChunk;++chunkZ) { @@ -1183,9 +1188,6 @@ namespace VoxelForgeCore if(!selectedPlan||!Heightfield2D(impl_->worldAssembly->recipe,*selectedPlan).isValid()) return false; - const double coreVoxelsPerOwnerChunk=static_cast(CHUNK_SIZE) - *static_cast(impl_->owner->OwnerVoxelSizeMicrons) - /static_cast(std::max(1u,impl_->owner->CoreVoxelSizeMicrons)); const int32 firstIslandChunk=FMath::FloorToInt( static_cast(boundsMin.Z)/coreVoxelsPerOwnerChunk); const int32 lastIslandChunk=FMath::FloorToInt( diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/BoundaryProbe.py b/Standalone/Research/WorldAssemblerM3/Linux17/BoundaryProbe.py new file mode 100644 index 0000000..054c1a8 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/BoundaryProbe.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +"""Measure upward mesh faces around the FI/SW stratum interface.""" +import array +import collections +import math +import struct +import sys + + +def read_exact(stream, size): + data = stream.read(size) + if len(data) != size: + raise EOFError(f"wanted {size} bytes, got {len(data)}") + return data + + +path = sys.argv[1] +low_z = float(sys.argv[2]) if len(sys.argv) > 2 else -80.0 +high_z = float(sys.argv[3]) if len(sys.argv) > 3 else -45.0 +with open(path, "rb") as stream: + if read_exact(stream, 8) != b"VFMSH001": + raise SystemExit("bad VFMSH001 header") + version, voxel_um, tile_count = struct.unpack("<3I", read_exact(stream, 12)) + camera = struct.unpack("<3d", read_exact(stream, 24)) + yaw, pitch = struct.unpack("<2d", read_exact(stream, 16)) + per_lod = collections.defaultdict(lambda: {"tiles": 0, "faces": [], "spans": []}) + near_tiles = collections.defaultdict(list) + for _ in range(tile_count): + key = struct.unpack("<4i", read_exact(stream, 16)) + surf_vertices, skirt_count, vertex_count, index_count, mask_count = struct.unpack( + "<5I", read_exact(stream, 20)) + p = array.array("f") + p.frombytes(read_exact(stream, vertex_count * 12)) + n = array.array("f") + n.frombytes(read_exact(stream, vertex_count * 12)) + if sys.byteorder != "little": + p.byteswap(); n.byteswap() + indices = array.array("I") + indices.frombytes(read_exact(stream, index_count * 4)) + masks = read_exact(stream, mask_count) + if sys.byteorder != "little": + indices.byteswap() + lod = key[3] + z_values = [] + for tri in range(index_count // 3): + if masks and masks[tri] != 0: + continue + a, b, c = indices[tri * 3:tri * 3 + 3] + if max(a, b, c) >= surf_vertices: + continue + normal_z = (n[a * 3 + 2] + n[b * 3 + 2] + n[c * 3 + 2]) / 3.0 + if normal_z < 0.65: + continue + z = (p[a * 3 + 2] + p[b * 3 + 2] + p[c * 3 + 2]) / 3.0 + if low_z <= z <= high_z: + z_values.append(z) + if not z_values: + continue + z_values.sort() + row = per_lod[lod] + row["tiles"] += 1 + row["faces"].extend(z_values) + span = z_values[math.floor(.95 * (len(z_values) - 1))] - z_values[math.floor(.05 * (len(z_values) - 1))] + row["spans"].append(span) + extent = 32 * (1 << lod) * voxel_um / 1_000_000.0 + cx = (key[0] + 0.5) * extent + cy = (key[1] + 0.5) * extent + near_tiles[lod].append((math.hypot(cx - camera[0], cy - camera[1]), key, + z_values[len(z_values) // 2], span, len(z_values))) + + +def q(values, fraction): + return values[math.floor(fraction * (len(values) - 1))] if values else math.nan + + +print(f"camera_m={camera} yaw={yaw} pitch={pitch} boundary_band_m={low_z}..{high_z}") +print("lod tiles_with_boundary_faces faces z_m_p05/median/p95 tile_span_m_p50/p95/max") +for lod in sorted(per_lod): + row = per_lod[lod] + spans = sorted(row["spans"]) + print(f"{lod} {row['tiles']} {len(row['faces'])} " + f"{q(sorted(row['faces']), .05):.4f}/{q(sorted(row['faces']), .5):.4f}/" + f"{q(sorted(row['faces']), .95):.4f} " + f"{q(spans, .5):.4f}/{q(spans, .95):.4f}/{max(spans):.4f}") +print("nearest_xy_boundary_tiles_by_lod:") +for lod in sorted(near_tiles): + for distance, key, median, span, faces in sorted(near_tiles[lod])[:3]: + print(f"lod={lod} key={key} xy_distance_m={distance:.2f} " + f"boundary_median_z={median:.4f} within_tile_p05_p95_m={span:.4f} faces={faces}") diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/FloatingIslandDensityProbe.cpp b/Standalone/Research/WorldAssemblerM3/Linux17/FloatingIslandDensityProbe.cpp new file mode 100644 index 0000000..11dbf89 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/FloatingIslandDensityProbe.cpp @@ -0,0 +1,143 @@ +#include "Json.h" +#include "StandaloneCoreScheduler.h" +#include "StandaloneSnapshotAdapter.h" +#include "VoxelForgeCore/VoxelForgeCore.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + constexpr double CoreVoxelsPerMeter = 4.0; + constexpr std::int64_t QPerCoreVoxel = VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel; + + std::int64_t ToQ(double Meters) + { + return static_cast(std::llround(Meters*CoreVoxelsPerMeter*QPerCoreVoxel)); + } + + void PrintLegacyBoundarySealTerms(const VoxelForgeCore::FloatingIslandManifestV1& Manifest, + double X, double Y, double Z) + { + using namespace VoxelForgeCore; + const auto Xq=ToQ(X),Yq=ToQ(Y),Zq=ToQ(Z); + const FloatingIslandFieldV1 field(Manifest.recipe,Manifest.plan); + const std::int64_t fieldQ=field.densitySubvoxels(Xq,Yq,Zq); + const std::int64_t bottom=Manifest.recipe.layoutMinimumZSubvoxels; + const std::int64_t top=Manifest.recipe.layoutMaximumZSubvoxels; + const std::int64_t seal=Manifest.recipe.boundarySealSubvoxels; + std::int64_t bridged=fieldQ; + bool applied=false; + if(Zq>=bottom&&Zq(1,Zq-bottom));applied=true;} + if(Zq<=top&&Zq>top-seal) + {bridged=std::min(bridged,-std::max(1,top-Zq));applied=true;} + std::printf("[PreFixIslandTerms] xyz_m=%.3f,%.3f,%.3f native_field_q=%lld " + "legacy_solid_seal_delta_q=%lld legacy_seal_active=%d pre_fix_wrapper_q=%lld\n", + X,Y,Z,static_cast(fieldQ), + static_cast(bridged-fieldQ),applied?1:0,static_cast(bridged)); + for(const auto& island:Manifest.plan.islands) + { + const bool inBounds=Xq>=island.influenceMinimumSubvoxels[0] + &&Xq<=island.influenceMaximumSubvoxels[0] + &&Yq>=island.influenceMinimumSubvoxels[1] + &&Yq<=island.influenceMaximumSubvoxels[1] + &&Zq>=island.influenceMinimumSubvoxels[2] + &&Zq<=island.influenceMaximumSubvoxels[2]; + std::printf("[IslandGroup] ordinal=%u center_m=%.3f,%.3f,%.3f " + "bounds_contains_sample=%d\n", + island.ordinal,island.centerSubvoxels[0]/1024.0,island.centerSubvoxels[1]/1024.0, + island.centerSubvoxels[2]/1024.0,inBounds?1:0); + } + for(const auto& edge:Manifest.plan.clusterEdges) + { + bool inBounds=true; + const std::int64_t q[3]={Xq,Yq,Zq}; + for(std::size_t axis=0;axis<3;++axis) + inBounds=inBounds&&q[axis]>=edge.influenceMinimumSubvoxels[axis] + &&q[axis]<=edge.influenceMaximumSubvoxels[axis]; + std::printf("[IslandConnector] id=%016llx bounds_contains_sample=%d\n", + static_cast(edge.stableId),inBounds?1:0); + } + } +} + +void PrintDensityLine(VoxelForgeCore::World& World,const char* Label, + double X,double Y,double ZMinimum,double ZMaximum,double Step) +{ + using namespace VoxelForgeCore; + std::printf("[DensityLine] label=%s xy_m=(%.6f,%.6f) z_m=%.2f..%.2f step_m=%.2f\n", + Label,X,Y,ZMinimum,ZMaximum,Step); + for(double Z=ZMinimum;Z<=ZMaximum+1.0e-9;Z+=Step) + { + const Vec3d Point{X*CoreVoxelsPerMeter,Y*CoreVoxelsPerMeter, + Z*CoreVoxelsPerMeter}; + const double Density=World.densityAt(Point); + const double Unclamped=World.unclampedDensityAt(Point); + const DetailFieldSample Detail=World.detailSampleAt(Point); + std::printf("[DensitySample] label=%s xyz_m=%.3f,%.3f,%.3f density_core_vox=%.9f " + "density_cm=%.3f unclamped_core_vox=%.9f cave_influence=%.6f " + "floor_influence=%.6f detail_displacement=%.6f sign=%s\n",Label,X,Y,Z, + Density,Density*25.0,Unclamped,Detail.caveInfluence,Detail.floorInfluence, + Detail.displacement,Density<0.0?"solid":"air"); + } +} + +int main(int argc,char** argv) +{ + if(argc!=2) + { + std::fprintf(stderr,"usage: %s owner-world-with-world-assembly.json\n",argv[0]); + return 2; + } + VFJson::Value root; + std::string error; + if(!VFJson::Load(argv[1],root,error)) + {std::fprintf(stderr,"owner JSON parse failed: %s\n",error.c_str());return 2;} + auto snapshot=VoxelForgeCore::MakeStandaloneSnapshotFromParsedJson(root,0,3,8,false,false,error); + if(!snapshot) + {std::fprintf(stderr,"snapshot resolve failed: %s\n",error.c_str());return 2;} + const auto* assembly=snapshot.worldAssembly(); + if(!assembly||assembly->floatingIslands.empty()) + {std::fprintf(stderr,"FloatingIslands manifest missing\n");return 2;} + + VoxelForgeCore::World world(std::move(snapshot)); + VoxelForgeCore::ShapeBuildRequest request; + request.minVoxel={-96,-512,-288}; + request.maxVoxel={96,96,64}; + request.clipMinVoxel=request.minVoxel; + request.clipMaxVoxel=request.maxVoxel; + request.workerLimit=12; + request.includeFarWorld=false; + FStandaloneCoreScheduler scheduler; + if(!world.compile(request,scheduler,error)) + {std::fprintf(stderr,"shape compile failed: %s\n",error.c_str());return 2;} + + constexpr double FlatX=-11.612443923950195; + constexpr double FlatY=-118.22123718261719; + constexpr double IslandX=-6.3; + constexpr double IslandY=-19.057; + constexpr double RingX=-4.889; + constexpr double RingY=-16.008; + std::printf("[DensityRoute] flat_square_xy_m=(%.6f,%.6f) island_ground_xy_m=(%.6f,%.6f) " + "compiled=%d core_voxel_size_m=0.25 owner_to_core_chunk_voxels=16\n", + FlatX,FlatY,IslandX,IslandY,world.isCompiled()?1:0); + PrintDensityLine(world,"flat-square",FlatX,FlatY,2.5,9.0,0.25); + PrintDensityLine(world,"fi-sw-boundary",FlatX,FlatY,-62.0,-58.0,0.25); + PrintDensityLine(world,"island-center",IslandX,IslandY,-39.0,-20.0,0.5); + PrintDensityLine(world,"lod0-lod1-ring-edge",RingX,RingY,-62.0,-20.0,1.0); + + const auto& island=assembly->floatingIslands.front().manifest; + for(double z:{2.75,2.99,3.00,3.01,3.25,3.49,3.50,3.51,3.75,3.99,4.00,4.01,7.75,8.00,8.25}) + PrintLegacyBoundarySealTerms(island,FlatX,FlatY,z); + for(double z:{-35.0,-30.0,-25.0}) + PrintLegacyBoundarySealTerms(island,IslandX,IslandY,z); + for(double z:{-60.0,-35.0,-28.0,-25.0}) + PrintLegacyBoundarySealTerms(island,RingX,RingY,z); + return 0; +} diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/MeasureBuild.py b/Standalone/Research/WorldAssemblerM3/Linux17/MeasureBuild.py new file mode 100644 index 0000000..a1b28e3 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/MeasureBuild.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +"""Measure peak per-process RSS for a build process tree under the L17 limits.""" +import os +import subprocess +import sys +import time +from pathlib import Path + + +def descendants(root): + pending = [root] + seen = set() + while pending: + pid = pending.pop() + if pid in seen: + continue + seen.add(pid) + try: + children = Path(f"/proc/{pid}/task/{pid}/children").read_text().split() + pending.extend(int(child) for child in children) + except (FileNotFoundError, PermissionError, ProcessLookupError): + pass + return seen + + +def status(pid): + try: + fields = {} + for line in Path(f"/proc/{pid}/status").read_text().splitlines(): + if line.startswith(("Name:", "VmRSS:", "VmSize:")): + key, *value = line.split() + fields[key[:-1]] = value[0] if value else "" + return (int(fields.get("VmRSS", "0")), int(fields.get("VmSize", "0")), + fields.get("Name", "")) + except (FileNotFoundError, PermissionError, ProcessLookupError, ValueError): + return None + + +if len(sys.argv) < 2: + raise SystemExit("usage: MeasureBuild.py command [arguments ...]") +if not os.sched_getaffinity(0).issubset(set(range(12))): + raise SystemExit("run under taskset -c 0-11") + +started = time.monotonic() +process = subprocess.Popen(sys.argv[1:], start_new_session=True) +peak_rss = (0, 0, "") +peak_vms = (0, 0, "") +while process.poll() is None: + for pid in descendants(process.pid): + measured = status(pid) + if measured is None: + continue + rss, vms, name = measured + if rss > peak_rss[0]: + peak_rss = (rss, pid, name) + if vms > peak_vms[0]: + peak_vms = (vms, pid, name) + time.sleep(0.1) + +exit_code = process.wait() +elapsed = time.monotonic() - started +print(f"[BuildTreeResources] exit_code={exit_code} wall_s={elapsed:.3f} " + f"peak_process_rss_kib={peak_rss[0]} peak_rss_pid={peak_rss[1]} " + f"peak_rss_name={peak_rss[2]} peak_process_vms_kib={peak_vms[0]} " + f"peak_vms_pid={peak_vms[1]} peak_vms_name={peak_vms[2]} " + "monitor_interval_s=0.1", flush=True) +raise SystemExit(exit_code) diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/MeshProbe.py b/Standalone/Research/WorldAssemblerM3/Linux17/MeshProbe.py new file mode 100644 index 0000000..414062b --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/MeshProbe.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +"""Summarize exported tile geometry and upward-facing ground for L17.""" +import array +import collections +import math +import struct +import sys + + +def read_exact(stream, size): + data = stream.read(size) + if len(data) != size: + raise EOFError(f"wanted {size} bytes, got {len(data)}") + return data + + +path = sys.argv[1] +with open(path, "rb") as stream: + if read_exact(stream, 8) != b"VFMSH001": + raise SystemExit("bad VFMSH001 header") + version, voxel_um, tile_count = struct.unpack("<3I", read_exact(stream, 12)) + camera = struct.unpack("<3d", read_exact(stream, 24)) + yaw, pitch = struct.unpack("<2d", read_exact(stream, 16)) + per_lod = collections.defaultdict(lambda: {"tiles": 0, "vertices": 0, + "triangles": 0, "surface_triangles": 0, "up_triangles": 0, + "up_centroids": [], "tile_spans": [], "empty": 0}) + tile_rows = [] + for _ in range(tile_count): + key = struct.unpack("<4i", read_exact(stream, 16)) + surf_vertices, skirt_count, vertex_count, index_count, mask_count = struct.unpack( + "<5I", read_exact(stream, 20)) + p = array.array("f") + p.frombytes(read_exact(stream, vertex_count * 12)) + n = array.array("f") + n.frombytes(read_exact(stream, vertex_count * 12)) + if sys.byteorder != "little": + p.byteswap(); n.byteswap() + indices = array.array("I") + indices.frombytes(read_exact(stream, index_count * 4)) + masks = read_exact(stream, mask_count) + if sys.byteorder != "little": + indices.byteswap() + lod = key[3] + row = per_lod[lod] + row["tiles"] += 1 + row["vertices"] += vertex_count + row["triangles"] += index_count // 3 + row["surface_triangles"] += index_count // 3 - skirt_count + up = [] + for tri in range(index_count // 3): + if masks and masks[tri] != 0: + continue + a, b, c = indices[tri * 3:tri * 3 + 3] + if max(a, b, c) >= surf_vertices: + continue + if (n[a * 3 + 2] + n[b * 3 + 2] + n[c * 3 + 2]) / 3.0 < 0.65: + continue + up.append((p[a * 3 + 2] + p[b * 3 + 2] + p[c * 3 + 2]) / 3.0) + row["up_triangles"] += len(up) + row["up_centroids"].extend(up) + if up: + up.sort() + span = up[math.floor(0.95 * (len(up) - 1))] - up[math.floor(0.05 * (len(up) - 1))] + row["tile_spans"].append(span) + tile_rows.append((key, vertex_count, index_count // 3, skirt_count, + len(up), up[0], up[len(up) // 2], up[-1], span)) + else: + row["empty"] += 1 + tile_rows.append((key, vertex_count, index_count // 3, skirt_count, + 0, math.nan, math.nan, math.nan, math.nan)) + +print(f"version={version} voxel_um={voxel_um} tiles={tile_count} camera_m={camera} yaw={yaw} pitch={pitch}") +print("lod tiles mesh_tiles vertices triangles skirt_triangles upward_surface_triangles " + "upward_centroid_z_m_p05/median/p95 tile_up_z_span_m_p50/p95/max") +for lod in sorted(per_lod): + r = per_lod[lod] + z = sorted(r["up_centroids"]) + s = sorted(r["tile_spans"]) + def q(values, fraction): + return values[math.floor(fraction * (len(values) - 1))] if values else math.nan + print(f"{lod} {r['tiles']} {r['tiles']-r['empty']} {r['vertices']} {r['triangles']} " + f"{sum(row[3] for row in tile_rows if row[0][3] == lod)} {r['up_triangles']} " + f"{q(z,.05):.4f}/{q(z,.5):.4f}/{q(z,.95):.4f} " + f"{q(s,.5):.4f}/{q(s,.95):.4f}/{max(s) if s else math.nan:.4f}") + +print("near_camera_up_tiles (sorted by XY tile-centre distance):") +near = [] +for row in tile_rows: + key = row[0] + lod = key[3] + extent = 32 * (1 << lod) * voxel_um / 1_000_000.0 + cx = (key[0] + 0.5) * extent + cy = (key[1] + 0.5) * extent + near.append((math.hypot(cx-camera[0], cy-camera[1]), row)) +for distance, row in sorted(near)[:30]: + key, verts, tris, skirts, ups, lo, med, hi, span = row + if ups: + print(f"key={key} xy_distance_m={distance:.2f} vertices={verts} triangles={tris} " + f"skirt_triangles={skirts} upward_triangles={ups} z_m={lo:.3f}/{med:.3f}/{hi:.3f} " + f"tile_span_p05_p95_m={span:.3f}") diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/OWNER_NOTE.md b/Standalone/Research/WorldAssemblerM3/Linux17/OWNER_NOTE.md new file mode 100644 index 0000000..2a4ebf0 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/OWNER_NOTE.md @@ -0,0 +1,26 @@ +# Owner note — L17 FloatingIslands steps + +The ledges were real generated mesh geometry caused by two boundary mistakes that made empty space +look like flat ground: the FloatingIslands seal was applied as a solid cap across XY, and owner +chunks were treated as 8 m of Core voxels instead of their actual 4 m. At the measured flat square, +the native island field is air and cave/floor influence is zero. The point is about 100 m from the +four islands. + +I removed the false cap and corrected the shared owner/Core coordinate conversion. Evaluator version +is 7. The before/after captures show the false sheet disappear and the actual island shape remain. +SurfaceWorld’s L1 hash changes because it now selects its intended `Heightfield2D` route; its route, +readiness and proof audits pass. + +The export has nonempty meshes at LOD0–8, and the standalone viewer enables and draws all levels by +default. I cannot identify the screenshot’s dark square as a whole missing LOD from the Linux data; +it may be a specific tile or viewer draw/upload issue. I did not change the Windows viewer. Please +capture the view below and, if the square remains, repeat with `--capture-only-lod=0` through `8`. + +The low-view camera is `(-22,-19,-22.8) m`, yaw 0°, pitch −4°, matching the Linux island pair. + +```bat +VoxelForgeCoreStandalone.exe --world-assembler-prototype --recipe=floating-islands --clip-radius=3 --max-clip-level=8 --workers=12 --camera=-22,-19,-22.8,0,-4 --capture=Standalone\Research\WorldAssemblerM3\Linux17\captures\floating-islands-windows.png --frame-limit=60 +``` + +Use a different `--capture=` filename for each isolated LOD. Send the all-level image plus the +isolated image that corresponds to the square. diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/REPORT.md b/Standalone/Research/WorldAssemblerM3/Linux17/REPORT.md new file mode 100644 index 0000000..6b278bc --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/REPORT.md @@ -0,0 +1,182 @@ +# VoxelForge L17 — FloatingIslands boundary report + +Branch `assembler/world`, starting HEAD `9a7c87e`. No cache code was changed. The shared evaluator +version is now 7; the recipe schema stays at 1. + +## Cause and fix + +FloatingIslands uses the sparse `FloatingIslandFieldV1` manifest field. SurfaceWorld uses the +separate planar `Heightfield2D` field. The owner voxel is 12.5 cm and the Core voxel is 25 cm, so +one 32-voxel owner chunk is **16 Core voxels / 4 m**. Several shared paths divided Core positions +by 32 directly, treating that chunk as 8 m. That doubled stratum bounds, selected the wrong +generator route near the SurfaceWorld boundary, and made the legacy layer envelope extend over +empty FloatingIslands space. + +The FloatingIslands `boundarySeal` also had been applied as a solid cap over all XY. At the owner’s +flat-square probe `(-11.612444,-118.221237) m`, the raw island field is air: at Z=3.25 m it was +`+81,809` subvoxels. The old seal added `−82,065`, yielding `−256` (`−1` Core voxel, or −25 cm); +at Z=3.50 m it yielded `−1` subvoxel (−0.098 cm), then air again at Z=3.75 m. The wrong 8 m +legacy layer bound produced a second false top near Z=8 m (old world density at 7.75 m was +−0.743 Core voxels; at 8 m it was +0.073). The owner’s 4.5 m LOD0 jump is real mesh geometry +created by those bad boundaries, often inside a tile; it is not a renderer artifact or island relief. +Nested clipmap rectangles made its placement look like a tile-boundary-only issue. + +The fix uses the resolved owner/Core scale for manager lookups, layer bounds, readiness, and +adjacent native strata; removes the XY-wide FloatingIslands seal cap and its all-solid proof; and +clips adjacent native FI/SW signed-distance fields at their shared physical boundary. This is in +Core and applies to every generator route. SurfaceWorld still uses `Heightfield2D`. + +The cave-floor lead does not match the samples. Cave and floor influence were exactly zero at the +flat square, the island center, and the sampled ledge/ring point. The native FI field and its island +or connector bounds account for the surface. The owner world compiled 70 rooms, 69 tunnels and 2 +passages in this run; those legacy primitives do not contribute to the measured FI ledge. + +## Before/after measurements + +`RingProbe.py` samples upward-facing mesh surfaces on adjacent XY tile edges only when the tiles’ +vertical bands overlap. Values are median / p95 / maximum absolute height difference, in cm. `n/a` +means this sparse-island export had no same-band LOD0↔1 surface pair after removing the false cap; +it is not a zero-error result. Higher rings include the deep SurfaceWorld boundary and other deep +surfaces, so those rows are not all FloatingIslands ground. + +| LOD edge | Before (cm) | After (cm) | +|---|---:|---:| +| 0→1 | 3.451 / 8.920 / 449.158 (266 samples) | n/a (no same-band pair) | +| 1→2 | 26.642 / 148.262 / 149.862 (514) | 0 / 0 / 0 (234) | +| 2→3 | 0.134 / 198.730 / 773.318 (596) | 0 / 0 / 0 (207) | +| 3→4 | 3.269 / 47.875 / 188.531 (277) | 0 / 0 / 0 (288) | +| 4→5 | 29.975 / 130.496 / 445.444 (544) | 0 / 0 / 30.957 (258) | +| 5→6 | 12.234 / 127.224 / 536.573 (266) | 12.234 / 127.224 / 536.573 (266) | +| 6→7 | 29.013 / 301.752 / 42,624.479 (264) | 28.892 / 291.861 / 945.477 (264) | +| 7→8 | 83.843 / 1,225.416 / 3,755.407 (275) | 83.843 / 1,225.416 / 3,755.407 (275) | + +The valid worst pre-fix LOD0↔1 sample is the false cap: 3.500 m vs 7.992 m, a 449.158 cm +difference. Upward-face within-tile span p95 / maximum changed from 4.490 / 4.491 m to 1.186 / +1.927 m on LOD0. The remaining LOD0 span is the actual island shape. LOD1–3 after-fix upward +faces at the measured lower boundary are exactly at −60 m. The island tops around the matched +camera are roughly −30 to −25 m. + +A separate exploratory column comparison initially reported a 34.7 m difference by pairing an +island top near −25 m with a −60 m SurfaceWorld surface from a vertically disjoint tile. That +comparison was rejected: it is not a same-band ring seam. The saved `RingProbe.py` output is the +cross-LOD evidence used above. + +## History, viewer and SurfaceWorld + +Prebuilt L7, L9, L12, L13 and L14 binaries/logs all have the same legacy hashes: whole-view D/M/P/T +`92ba6a57a8690c00 / 9c6b56dfab6241c9 / 82394dd7c368a061 / 445e40bdb69b0bdb`; full-detail +`93ee3b6fb6b446f3 / 3ebc72d2027ab80b / cd5f55a96de12458 / 2f61c29af247b547`. The pattern +predates L7; these measurements show no output change at L9 or L13. S9 `e7586a1`, S12 `212814a` +and S14 `ec2afe9` do not contain the headless pipeline source, so they cannot be measured this way. +No old commit was rebuilt: `git worktree add` failed because `.git/worktrees` is read-only, and the +available old binaries were used as-is. + +The headless mesh export has nonempty tiles at **all** LODs 0–8 (matched view counts: +15, 64, 40, 48, 48, 96, 48, 48, 153). The standalone viewer initializes all nine `bShowLevel` +flags to true and its draw loop visits all streaming batches. There is no evidence that a whole LOD +is absent from generated data or globally filtered by the viewer. The screenshot’s dark square +cannot be mapped to a particular tile/LOD from this Linux export; a localized viewer draw/upload +or camera issue remains unconfirmed. No viewer change was made because the Windows D3D11 build and +capture are unavailable here. The Unreal comparison does not identify the cause of that square. + +SurfaceWorld L1 hashes changed for the shared coordinate fix. Old L14 LOD1 D/M/P/T was +`5043975b1e5b5a3d / 1c2a5658f10fdeaa / 23b6779ef35c3a0a / 1a6d2e2d152b4f84`; L17 is +`393ad79fd8c07132 / 47c9ba17e9f5ceaa / d5d6a948ac880e17 / 8b85ea08b2c440c4`. Before, readiness +was 0/27; now it is 27/27 on the near ring. The old mapping selected the wrong route at the +SurfaceWorld stratum; the corrected mapping selects its manifest `Heightfield2D` plan. Page/native +route parity and exact queries pass, so this is the intended shared-route output change. + +## Gates, captures and limits + +All 28 determinism rows passed: FI and SW, Clang 19 `-ffp-contract=off` and GCC 14 default, +W1/W8/W12 with five W12 repeats. Each recipe had one unique full, whole, nine-LOD and exact-query +hash tuple across all configurations. FI whole-view D/M/P/T is +`8339509b4d5ec231 / 70e5b2b9085b517c / 4e72e53745f20ed0 / 1a2643e5138e0407`; SW whole-view is +`b286ee4f4c38b7fc / 6862deb8ab9c2af9 / f23480a4953457f9 / 62977edfd04b3afe`. + +FI route parity: 8 page pairs, 14 higher-LOD exact pairs, 782,026 exact samples, zero mismatches; +uniform proof: 19,288 blocks / 25,672,328 samples / zero violations. SW: 5 page and 9 native-only +pairs, 814,625 exact samples, zero mismatches; uniform proof: 13,297 blocks / 17,698,307 samples / +zero violations. Readiness negative controls were caught. The Clang FP-contraction-off and GCC +default builds passed; the Core startup FP self-test did not reject either. No async/MPSC/Epoch +code changed; `FLazy`, shared column caches, L9/L12 proof paths and L13 route binding remain in the +tested build. + +Readable Linux capture mode adds directional light with soft ambient, gentle height tint, and an +optional faint tile-edge overlay. Five 1600×900 JPEGs, all below 300 KB, are in `captures/`: + +- `floating-islands-flat-square-before.jpg` / `floating-islands-flat-square-after.jpg`: same owner + probe camera `(-11.6124,-118.2212,-19.8452) m`, yaw 0, pitch 0, before/after. +- `floating-islands-island-view-before.jpg` / `floating-islands-island-view-after.jpg`: same low + island camera `(-22,-19,-22.8) m`, yaw 0, pitch −4°, before/after. +- `surface-world-l1-readable-tiles.jpg`: SurfaceWorld L1 sanity view, camera `(0,-35,30) m`, yaw 0, + pitch −60°. + +All are 1600×900 JPEGs; SHA256 is included for byte-level review. + +| Capture | Bytes | SHA256 | +|---|---:|---| +| `floating-islands-flat-square-before.jpg` | 70,166 | `c41ed7645735ebefea97fbc1aed167b66a3e06c019c25b1c7d8cae9449713999` | +| `floating-islands-flat-square-after.jpg` | 47,612 | `f8fb5f937ac65be9db70a41473c7a10d7f35943ba6ef5c94ab03fde9ded5c544` | +| `floating-islands-island-view-before.jpg` | 70,813 | `5c7a8eda446f51a51ab22e45ed7286bf4180e69d8e3b2180780349facadacd32` | +| `floating-islands-island-view-after.jpg` | 51,429 | `3aeedef903fce62e81ea1f07bb460dd2beb42b893bbd9bf29220973951295b4c` | +| `surface-world-l1-readable-tiles.jpg` | 53,351 | `23f1753ed100c87607e22d2adc4f8e8a2856b8af3f1d37aa4f4cec9420a92b93` | + +Clang/GCC compile peak RSS was 435,588 / 902,000 KiB. Determinism peak was 538,140 KiB; FI/SW +route-audit peaks were 621,404 / 763,112 KiB. The governor remained `powersave`; runs were limited +to CPUs 0–11, at most 12 workers, 6 GiB address space; llvmpipe used 12 threads. + +## Failed or retried attempts + +- The first headless invocation omitted the explicit owner-world input; it was rerun with + `Standalone/data/owner_world.json`. +- An initial SurfaceWorld export failed the native-only readiness guard; corrected owner/Core + mapping and rerun passed. +- A SurfaceWorld `--max-clip-level=1` attempt expanded to 35,435,983 tiles and failed the bounded + compiler (20.985 s, 3,988,160 KiB peak RSS). Retried with `--max-level=1` (960 tiles), which + passed. +- `BoundaryProbe.py` was first called with unsupported named Z arguments; rerun with positional + bounds passed. +- The first XY-only ring comparison mixed vertically disjoint surfaces; replaced by the + overlapping-band `RingProbe.py` used above. The exploratory column probe was also rejected for + pairing different vertical bands. +- The first offscreen SurfaceWorld command reversed scene/output arguments and failed to open the + mesh; rerun with the documented order passed. +- The first density-probe invocation used `Standalone/data/owner_world.json` without a resolved FI + manifest and failed. It was rerun with `Saved/Linux/l17-fi-owner-snapshot.json` and passed. +- `/usr/bin/time` was unavailable and an early process monitor mishandled a zombie child; the + process-tree monitor in `MeasureBuild.py` replaced both attempts. +- `git worktree add` could not write `.git/worktrees`; no worktree was created and no old commit was + built outside the repository. +- Mesa could not create `/home/jahni/.cache` in the read-only environment, disabled shader caching, + and completed all captures. No file was written outside the repository. + +## Windows confirmation + +Run from the repository root on Windows to capture the low island view: + +```bat +VoxelForgeCoreStandalone.exe --world-assembler-prototype --recipe=floating-islands --clip-radius=3 --max-clip-level=8 --workers=12 --camera=-22,-19,-22.8,0,-4 --capture=Standalone\Research\WorldAssemblerM3\Linux17\captures\floating-islands-windows.png --frame-limit=60 +``` + +For isolation, repeat with `--capture-only-lod=0` through `--capture-only-lod=8`, changing the +capture filename each time. Please send the all-level image and the isolated image matching the +dark square; those will identify whether it is a per-tile draw gap or a particular LOD payload. + +## Orchestrator review (Claude) — NOT MERGED + +- **The fix breaks SurfaceWorld.** I exported the L1 view (camera `0,-35,-487.94`) from L14 and from + L17 and rendered both in the new readable mode (`Saved/Linux/claude/sw/{before,after}-{l1,hz}.jpg`). + After L17, the ground under the spawn camera is gone (black void below), the terrain sits far + away, and the mesh export shrank from 58.7 MB to 31.7 MB. Halving the strate chunk size (8 m → 4 m) + moves and squashes every stratum: a world change, not a fix. +- **What the approved world uses:** the Core world the owner played and approved places strata + with 8 m chunks (32 Core voxels of 25 cm). The "owner chunk = 4 m" claim must be checked against + what the Unreal Core route actually does (`AVoxelWorld::CoreVoxelSizeCm`, the Core bridge, + `ResolvedWorldSnapshot`), not assumed. +- **Probably real and separable:** the FloatingIslands `boundarySeal` applied as a solid cap over all + XY (the false floors at 3.5/8 m). That needs its own minimal fix with SurfaceWorld unchanged. +- **Still open in FloatingIslands after the fix:** dark tile-aligned rectangles on the ground (the L17 + "after" captures, lower left). +- Kept on side branch `wip/l17-fi-scale`. Only the capture tool's readable shading + (`LinuxOffscreenCapture.cpp`) is taken into `assembler/world`. diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/RingProbe.py b/Standalone/Research/WorldAssemblerM3/Linux17/RingProbe.py new file mode 100644 index 0000000..b722a3a --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/RingProbe.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +"""Compare upward mesh heights on shared XY edges between adjacent LOD rings.""" +import array +import collections +import math +import struct +import sys + + +def read_scene(path): + tiles = [] + with open(path, "rb") as f: + if f.read(8) != b"VFMSH001": + raise SystemExit(f"{path}: invalid mesh header") + version, voxel_um, count = struct.unpack("<3I", f.read(12)) + camera = struct.unpack("<3d", f.read(24)) + yaw, pitch = struct.unpack("<2d", f.read(16)) + voxel_m = voxel_um / 1_000_000.0 + for _ in range(count): + key = struct.unpack("<4i", f.read(16)) + surface_vertices, skirt_count, vertex_count, index_count, mask_count = struct.unpack( + "<5I", f.read(20)) + positions = array.array("f") + positions.frombytes(f.read(vertex_count * 12)) + normals = array.array("f") + normals.frombytes(f.read(vertex_count * 12)) + indices = array.array("I") + indices.frombytes(f.read(index_count * 4)) + masks = f.read(mask_count) + if sys.byteorder != "little": + positions.byteswap(); normals.byteswap(); indices.byteswap() + triangles = [] + for i in range(0, index_count, 3): + if masks and masks[i // 3] != 0: + continue + a, b, c = indices[i:i + 3] + if max(a, b, c) >= surface_vertices: + continue + nz = (normals[a * 3 + 2] + normals[b * 3 + 2] + normals[c * 3 + 2]) / 3.0 + if nz < 0.65: + continue + tri = tuple((positions[j * 3], positions[j * 3 + 1], positions[j * 3 + 2]) + for j in (a, b, c)) + triangles.append(tri) + if triangles: + lod = key[3] + extent = 32 * (1 << lod) * voxel_m + tiles.append({"key": key, "lod": lod, "extent": extent, + "x0": key[0] * extent, "y0": key[1] * extent, + "x1": (key[0] + 1) * extent, "y1": (key[1] + 1) * extent, + "z0": key[2] * extent, "z1": (key[2] + 1) * extent, + "triangles": triangles}) + return camera, yaw, pitch, tiles + + +def height_at(tile, x, y): + best = None + for tri in tile["triangles"]: + (x0, y0, z0), (x1, y1, z1), (x2, y2, z2) = tri + den = (y1 - y2) * (x0 - x2) + (x2 - x1) * (y0 - y2) + if abs(den) < 1.0e-10: + continue + a = ((y1 - y2) * (x - x2) + (x2 - x1) * (y - y2)) / den + b = ((y2 - y0) * (x - x2) + (x0 - x2) * (y - y2)) / den + c = 1.0 - a - b + if min(a, b, c) >= -1.0e-5: + z = a * z0 + b * z1 + c * z2 + if best is None or z > best: + best = z + return best + + +path = sys.argv[1] +camera, yaw, pitch, tiles = read_scene(path) +by_lod = collections.defaultdict(list) +for tile in tiles: + by_lod[tile["lod"]].append(tile) +print(f"scene={path} camera_m={camera} yaw={yaw} pitch={pitch} nonempty_mesh_tiles={len(tiles)}") +print("lod_pair shared_edges samples_both median_abs_cm p95_abs_cm max_abs_cm median_delta_cm gaps") +for lod in range(8): + fine = by_lod[lod] + coarse = by_lod[lod + 1] + deltas = [] + edge_rows = [] + edge_count = 0 + gap_count = 0 + # Shared XY edges occur only where tile extents touch and overlap on the other axis. + for a in fine: + for b in coarse: + zlo, zhi = max(a["z0"], b["z0"]), min(a["z1"], b["z1"]) + if zhi - zlo <= 1.0e-4: + continue + edge = None + if abs(a["x1"] - b["x0"]) < 1.0e-4 or abs(b["x1"] - a["x0"]) < 1.0e-4: + lo, hi = max(a["y0"], b["y0"]), min(a["y1"], b["y1"]) + if hi - lo > 1.0e-4: + edge = ("x", a["x1"] if abs(a["x1"] - b["x0"]) < 1.0e-4 else a["x0"], lo, hi) + if edge is None and (abs(a["y1"] - b["y0"]) < 1.0e-4 or abs(b["y1"] - a["y0"]) < 1.0e-4): + lo, hi = max(a["x0"], b["x0"]), min(a["x1"], b["x1"]) + if hi - lo > 1.0e-4: + edge = ("y", a["y1"] if abs(a["y1"] - b["y0"]) < 1.0e-4 else a["y0"], lo, hi) + if edge is None: + continue + edge_count += 1 + axis, fixed, lo, hi = edge + epsilon = min(0.02, a["extent"] * 0.001, b["extent"] * 0.001) + samples = 9 + matched = 0 + edge_deltas = [] + for i in range(samples): + t = (i + 0.5) / samples + varying = lo + (hi - lo) * t + if axis == "x": + side_a = 1.0 if abs(a["x1"] - fixed) < 1.0e-4 else -1.0 + side_b = 1.0 if abs(b["x1"] - fixed) < 1.0e-4 else -1.0 + za = height_at(a, fixed - side_a * epsilon, varying) + zb = height_at(b, fixed - side_b * epsilon, varying) + else: + side_a = 1.0 if abs(a["y1"] - fixed) < 1.0e-4 else -1.0 + side_b = 1.0 if abs(b["y1"] - fixed) < 1.0e-4 else -1.0 + za = height_at(a, varying, fixed - side_a * epsilon) + zb = height_at(b, varying, fixed - side_b * epsilon) + if za is not None and not zlo - 1.0e-3 <= za <= zhi + 1.0e-3: + za = None + if zb is not None and not zlo - 1.0e-3 <= zb <= zhi + 1.0e-3: + zb = None + if za is not None and zb is not None: + delta = (za - zb) * 100.0 + deltas.append(delta) + edge_deltas.append((delta, za, zb, varying)) + matched += 1 + if matched == 0: + gap_count += 1 + elif edge_deltas: + edge_rows.append((max(abs(row[0]) for row in edge_deltas), + a["key"], b["key"], edge, edge_deltas)) + if deltas: + absolute = sorted(abs(x) for x in deltas) + signed = sorted(deltas) + p95 = absolute[math.floor(0.95 * (len(absolute) - 1))] + median_abs = absolute[len(absolute) // 2] + median_delta = signed[len(signed) // 2] + print(f"{lod}->{lod+1} {edge_count} {len(deltas)} {median_abs:.3f} {p95:.3f} {max(absolute):.3f} {median_delta:.3f} {gap_count}") + for worst, fine_key, coarse_key, edge, rows in sorted(edge_rows, reverse=True)[:2]: + row = max(rows, key=lambda item: abs(item[0])) + print(f" worst_edge max_abs_cm={worst:.3f} fine={fine_key} coarse={coarse_key} " + f"axis={edge[0]} fixed_m={edge[1]:.3f} span_m={edge[2]:.3f}..{edge[3]:.3f} " + f"sample_v_m={row[3]:.3f} fine_z_m={row[1]:.3f} " + f"coarse_z_m={row[2]:.3f} delta_cm={row[0]:.3f}") + else: + print(f"{lod}->{lod+1} {edge_count} 0 n/a n/a n/a n/a {gap_count}") diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/RunMatrix.py b/Standalone/Research/WorldAssemblerM3/Linux17/RunMatrix.py new file mode 100644 index 0000000..798d145 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/RunMatrix.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +"""Run the L17 deterministic W1/W8/W12 x5 matrix on both supported Linux builds.""" +import os +import re +import signal +import subprocess +import sys +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[4] +OUT = ROOT / "Saved/Linux/l17-matrix" +OUT.mkdir(parents=True, exist_ok=True) +if not os.sched_getaffinity(0).issubset(set(range(12))): + raise SystemExit("run under taskset -c 0-11") + +BINARIES = { + "clang-off": ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-linux17-final-clang", + "gcc-default": ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-linux17-final-gcc", +} +RECIPES = { + "floating-islands": "-10,-31,-22,0,-8", + "surface-world": "0,-35,-75,0,0", +} +HASH_PATTERNS = { + "full": re.compile(r"^\[PipelineFullDetailHash\].*$", re.M), + "whole": re.compile(r"^\[PipelineWholeViewHash\].*$", re.M), + "lod": re.compile(r"^\[PipelineLODHash\].*$", re.M), + "exact": re.compile(r"^\[PipelineExactQueryHash\].*$", re.M), +} +rows = [] +all_pass = True + +for recipe, camera in RECIPES.items(): + for compiler, binary in BINARIES.items(): + if not binary.exists(): + raise SystemExit(f"missing binary: {binary}") + for workers, repeat in [(1, 1), (8, 1), (12, 1), (12, 2), (12, 3), (12, 4), (12, 5)]: + name = f"{recipe}-{compiler}-w{workers}-r{repeat}" + logfile = OUT / f"{name}.log" + command = ["prlimit", "--as=6442450944", "--", str(binary), + str(ROOT / "Standalone/data/owner_world.json"), + "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", + "--stream-hash", "--force-generate", "--clip-radius=3", + "--max-clip-level=8", f"--workers={workers}", f"--camera={camera}", + f"--recipe={recipe}"] + started = time.monotonic() + peak_rss_kib = 0 + with logfile.open("w", encoding="utf-8") as stream: + process = subprocess.Popen(command, stdout=stream, stderr=subprocess.STDOUT, + start_new_session=True) + while process.poll() is None: + pending = [process.pid] + seen = set() + while pending: + pid = pending.pop() + if pid in seen: + continue + seen.add(pid) + try: + children = Path(f"/proc/{pid}/task/{pid}/children").read_text().split() + pending.extend(int(value) for value in children) + for line in Path(f"/proc/{pid}/status").read_text().splitlines(): + if line.startswith("VmRSS:"): + peak_rss_kib = max(peak_rss_kib, int(line.split()[1])) + break + except (FileNotFoundError, PermissionError, ProcessLookupError, ValueError): + pass + if time.monotonic() - started > 900: + os.killpg(process.pid, signal.SIGTERM) + try: + process.wait(timeout=5) + except subprocess.TimeoutExpired: + os.killpg(process.pid, signal.SIGKILL) + process.wait() + all_pass = False + break + time.sleep(0.1) + code = process.wait() + elapsed = time.monotonic() - started + output = logfile.read_text(encoding="utf-8", errors="replace") + matched = {key: pattern.findall(output) for key, pattern in HASH_PATTERNS.items()} + ok = code == 0 and all(matched.values()) and len(matched["lod"]) == 9 + if not ok: + all_pass = False + row = {"recipe": recipe, "compiler": compiler, "workers": workers, + "repeat": repeat, "exit": code, "seconds": elapsed, + "peak_rss_kib": peak_rss_kib, "ok": ok, + "full": matched["full"][-1] if matched["full"] else "", + "whole": matched["whole"][-1] if matched["whole"] else "", + "lod": " || ".join(matched["lod"]), + "exact": matched["exact"][-1] if matched["exact"] else ""} + rows.append(row) + print(f"[MatrixRun] {name} exit={code} seconds={elapsed:.3f} " + f"peak_rss_kib={peak_rss_kib} hash_rows={sum(map(len,matched.values()))} " + f"status={'PASS' if ok else 'FAIL'}", flush=True) + +summary = OUT / "summary.tsv" +columns = ["recipe", "compiler", "workers", "repeat", "exit", "seconds", "peak_rss_kib", + "ok", "full", "whole", "lod", "exact"] +with summary.open("w", encoding="utf-8") as f: + f.write("\t".join(columns) + "\n") + for row in rows: + f.write("\t".join(str(row[key]) for key in columns) + "\n") + +for recipe in RECIPES: + reference = None + for row in rows: + if row["recipe"] != recipe: + continue + signature = (row["full"], row["whole"], row["lod"], row["exact"]) + if reference is None: + reference = signature + elif signature != reference: + print(f"[MatrixMismatch] recipe={recipe} workers={row['workers']} " + f"compiler={row['compiler']} repeat={row['repeat']}", flush=True) + all_pass = False +print(f"[MatrixSummary] rows={len(rows)} expected=28 result={'PASS' if all_pass else 'FAIL'} " + f"path={summary}", flush=True) +raise SystemExit(0 if all_pass and len(rows) == 28 else 1) diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/boundary-after.txt b/Standalone/Research/WorldAssemblerM3/Linux17/boundary-after.txt new file mode 100644 index 0000000..b712dc0 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/boundary-after.txt @@ -0,0 +1,27 @@ +camera_m=(-22.0, -19.0, -22.799999237060547) yaw=0.0 pitch=-4.0 boundary_band_m=-80.0..-45.0 +lod tiles_with_boundary_faces faces z_m_p05/median/p95 tile_span_m_p50/p95/max +1 64 131072 -60.0000/-60.0000/-60.0000 0.0000/0.0000/0.0000 +2 40 20480 -60.0000/-60.0000/-60.0000 0.0000/0.0000/0.0000 +3 48 24576 -60.0000/-60.0000/-60.0000 0.0000/0.0000/0.0000 +4 48 22945 -60.0000/-60.0000/-60.0000 0.0000/0.9167/1.8008 +5 48 19554 -60.0000/-60.0000/-60.0000 0.0000/1.0819/1.7900 +6 9 134 -60.0000/-60.0000/-60.0000 0.0000/0.0000/0.0000 +nearest_xy_boundary_tiles_by_lod: +lod=1 key=(-2, -2, -4, 1) xy_distance_m=5.39 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=2048 +lod=1 key=(-2, -1, -4, 1) xy_distance_m=11.18 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=2048 +lod=1 key=(-1, -2, -4, 1) xy_distance_m=14.87 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=2048 +lod=2 key=(-1, 1, -2, 2) xy_distance_m=67.27 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=512 +lod=2 key=(1, -1, -2, 2) xy_distance_m=70.06 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=512 +lod=2 key=(-2, 1, -2, 2) xy_distance_m=71.87 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=512 +lod=3 key=(-3, -1, -1, 3) xy_distance_m=138.61 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=512 +lod=3 key=(-1, -3, -1, 3) xy_distance_m=141.35 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=512 +lod=3 key=(-3, 0, -1, 3) xy_distance_m=147.12 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=512 +lod=4 key=(-3, -1, -1, 4) xy_distance_m=301.38 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=512 +lod=4 key=(-1, -3, -1, 4) xy_distance_m=303.92 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=512 +lod=4 key=(-3, 0, -1, 4) xy_distance_m=309.34 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=512 +lod=5 key=(-3, -1, -1, 5) xy_distance_m=627.54 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=343 +lod=5 key=(-1, -3, -1, 5) xy_distance_m=629.98 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=512 +lod=5 key=(-3, 0, -1, 5) xy_distance_m=635.24 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.4903 faces=142 +lod=6 key=(-3, 0, -1, 6) xy_distance_m=1287.71 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=2 +lod=6 key=(0, -3, -1, 6) xy_distance_m=1291.28 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=16 +lod=6 key=(1, 2, -1, 6) xy_distance_m=1520.36 boundary_median_z=-60.0000 within_tile_p05_p95_m=0.0000 faces=3 diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/boundary-before.txt b/Standalone/Research/WorldAssemblerM3/Linux17/boundary-before.txt new file mode 100644 index 0000000..3055d84 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/boundary-before.txt @@ -0,0 +1,35 @@ +camera_m=(-22.0, -19.0, -22.799999237060547) yaw=0.0 pitch=-4.0 boundary_band_m=-80.0..-45.0 +lod tiles_with_boundary_faces faces z_m_p05/median/p95 tile_span_m_p50/p95/max +1 65 144957 -60.4936/-60.4872/-59.5000 0.0059/0.9906/2.2272 +2 75 29057 -76.1525/-61.3304/-60.7788 0.8725/2.9863/8.5642 +3 87 26484 -73.0968/-63.0185/-62.4964 1.3211/11.6236/14.1057 +4 48 25679 -72.6651/-62.8690/-62.2182 3.2371/15.9700/17.0106 +5 48 26381 -67.4390/-62.7489/-61.8320 4.2721/11.9903/14.5467 +6 14 390 -73.7183/-67.0059/-62.3980 4.0318/11.7718/12.7473 +7 18 483 -74.7834/-71.1169/-67.5754 4.0317/7.3030/8.1412 +8 22 176 -75.3669/-69.9656/-63.4334 3.5327/3.5370/13.7478 +nearest_xy_boundary_tiles_by_lod: +lod=1 key=(-2, -2, -4, 1) xy_distance_m=5.39 boundary_median_z=-60.4712 within_tile_p05_p95_m=0.0177 faces=2048 +lod=1 key=(-2, -1, -4, 1) xy_distance_m=11.18 boundary_median_z=-60.4718 within_tile_p05_p95_m=0.0158 faces=2048 +lod=1 key=(-1, -2, -4, 1) xy_distance_m=14.87 boundary_median_z=-60.4550 within_tile_p05_p95_m=0.0212 faces=2048 +lod=2 key=(-1, 1, -2, 2) xy_distance_m=67.27 boundary_median_z=-60.7421 within_tile_p05_p95_m=0.2955 faces=496 +lod=2 key=(1, -1, -3, 2) xy_distance_m=70.06 boundary_median_z=-74.2743 within_tile_p05_p95_m=2.9398 faces=97 +lod=2 key=(1, -1, -2, 2) xy_distance_m=70.06 boundary_median_z=-60.7387 within_tile_p05_p95_m=1.2725 faces=496 +lod=3 key=(-3, -1, -1, 3) xy_distance_m=138.61 boundary_median_z=-62.5408 within_tile_p05_p95_m=0.3465 faces=512 +lod=3 key=(-1, -3, -1, 3) xy_distance_m=141.35 boundary_median_z=-62.5378 within_tile_p05_p95_m=1.6699 faces=512 +lod=3 key=(-3, 0, -1, 3) xy_distance_m=147.12 boundary_median_z=-62.5837 within_tile_p05_p95_m=0.3165 faces=512 +lod=4 key=(-3, -1, -1, 4) xy_distance_m=301.38 boundary_median_z=-62.3784 within_tile_p05_p95_m=4.5901 faces=546 +lod=4 key=(-1, -3, -1, 4) xy_distance_m=303.92 boundary_median_z=-62.3534 within_tile_p05_p95_m=10.4664 faces=596 +lod=4 key=(-3, 0, -1, 4) xy_distance_m=309.34 boundary_median_z=-62.3696 within_tile_p05_p95_m=6.1327 faces=544 +lod=5 key=(-3, -1, -1, 5) xy_distance_m=627.54 boundary_median_z=-62.0651 within_tile_p05_p95_m=9.5826 faces=523 +lod=5 key=(-1, -3, -1, 5) xy_distance_m=629.98 boundary_median_z=-61.9414 within_tile_p05_p95_m=2.3891 faces=526 +lod=5 key=(-3, 0, -1, 5) xy_distance_m=635.24 boundary_median_z=-62.0996 within_tile_p05_p95_m=9.3777 faces=567 +lod=6 key=(-3, 0, -1, 6) xy_distance_m=1287.71 boundary_median_z=-69.5358 within_tile_p05_p95_m=4.1243 faces=26 +lod=6 key=(0, -3, -1, 6) xy_distance_m=1291.28 boundary_median_z=-70.4254 within_tile_p05_p95_m=12.7473 faces=41 +lod=6 key=(0, 2, -1, 6) xy_distance_m=1328.41 boundary_median_z=-63.9805 within_tile_p05_p95_m=0.0000 faces=1 +lod=7 key=(0, -3, -1, 7) xy_distance_m=2596.50 boundary_median_z=-70.2015 within_tile_p05_p95_m=4.1663 faces=36 +lod=7 key=(2, -1, -1, 7) xy_distance_m=2628.64 boundary_median_z=-70.1072 within_tile_p05_p95_m=3.5366 faces=8 +lod=7 key=(-3, 1, -1, 7) xy_distance_m=2976.49 boundary_median_z=-70.9568 within_tile_p05_p95_m=4.8223 faces=24 +lod=8 key=(-1, 2, -1, 8) xy_distance_m=5235.77 boundary_median_z=-65.8628 within_tile_p05_p95_m=3.5343 faces=8 +lod=8 key=(-1, -4, -1, 8) xy_distance_m=7218.88 boundary_median_z=-71.4663 within_tile_p05_p95_m=3.5332 faces=8 +lod=8 key=(-4, 0, -1, 8) xy_distance_m=7221.71 boundary_median_z=-70.6999 within_tile_p05_p95_m=3.5335 faces=8 diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/captures/floating-islands-flat-square-after.jpg b/Standalone/Research/WorldAssemblerM3/Linux17/captures/floating-islands-flat-square-after.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0a91b53bd99f5c5fa368e224c89106fd87c841c5 GIT binary patch literal 47612 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 Q43;fMYv=RV7kqjCe_7~~e*gdg literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/captures/floating-islands-island-view-after.jpg b/Standalone/Research/WorldAssemblerM3/Linux17/captures/floating-islands-island-view-after.jpg new file mode 100644 index 0000000000000000000000000000000000000000..df1cd48fca3f47ec9231dd87e2efd7cd912d734a GIT binary patch literal 51429 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 literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/captures/floating-islands-island-view-before.jpg b/Standalone/Research/WorldAssemblerM3/Linux17/captures/floating-islands-island-view-before.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f6b6097160097f1d0b874c983d8392200319c4e2 GIT binary patch literal 70813 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 KbV|~%1pfznFhIrt literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/captures/surface-world-l1-readable-tiles.jpg b/Standalone/Research/WorldAssemblerM3/Linux17/captures/surface-world-l1-readable-tiles.jpg new file mode 100644 index 0000000000000000000000000000000000000000..138ec2105c03858fc154e6bdcc473685ff4ce176 GIT binary patch literal 53351 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 Zdz=%04C(4`252fuKI&IUQ1Gwbe*t>r$9Mn$ literal 0 HcmV?d00001 diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/mesh-after-boundary-summary.txt b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-after-boundary-summary.txt new file mode 100644 index 0000000..d581311 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-after-boundary-summary.txt @@ -0,0 +1,13 @@ +version=1 voxel_um=250000 tiles=2370 camera_m=(-22.0, -19.0, -22.799999237060547) yaw=0.0 pitch=-4.0 +lod tiles mesh_tiles vertices triangles skirt_triangles upward_surface_triangles upward_centroid_z_m_p05/median/p95 tile_up_z_span_m_p50/p95/max +0 512 15 30819 54860 9176 12102 -29.7482/-28.0275/-25.2555 0.5335/1.1856/1.9265 +1 448 64 94272 163840 32768 131072 -60.0000/-60.0000/-60.0000 0.0000/0.0000/0.0000 +2 320 40 28476 45376 15296 20480 -60.0000/-60.0000/-60.0000 0.0000/0.0000/0.0000 +3 208 48 58599 93736 30968 24576 -60.0000/-60.0000/-60.0000 0.0000/0.0000/0.0000 +4 240 48 105724 164240 27638 22945 -60.0000/-60.0000/-60.0000 0.0000/0.9167/1.8008 +5 144 96 96543 156615 22706 109798 -506.3981/-502.5195/-60.0000 1.7900/110.1491/138.3581 +6 96 48 114212 157583 28194 91871 -506.2913/-503.3460/-411.9775 78.1123/124.2575/136.4059 +7 96 48 142940 234358 31690 95029 -506.1172/-503.3633/-412.8203 90.7064/105.1855/106.9902 +8 306 153 290960 421667 73118 147296 -505.8558/-503.1657/-422.5029 82.1507/93.3314/110.2594 +near_camera_up_tiles (sorted by XY tile-centre distance): +key=(-2, -2, -4, 1) xy_distance_m=5.39 vertices=1473 triangles=2560 skirt_triangles=512 upward_triangles=2048 z_m=-60.000/-60.000/-60.000 tile_span_p05_p95_m=0.000 diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/mesh-after-summary.txt b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-after-summary.txt new file mode 100644 index 0000000..d581311 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-after-summary.txt @@ -0,0 +1,13 @@ +version=1 voxel_um=250000 tiles=2370 camera_m=(-22.0, -19.0, -22.799999237060547) yaw=0.0 pitch=-4.0 +lod tiles mesh_tiles vertices triangles skirt_triangles upward_surface_triangles upward_centroid_z_m_p05/median/p95 tile_up_z_span_m_p50/p95/max +0 512 15 30819 54860 9176 12102 -29.7482/-28.0275/-25.2555 0.5335/1.1856/1.9265 +1 448 64 94272 163840 32768 131072 -60.0000/-60.0000/-60.0000 0.0000/0.0000/0.0000 +2 320 40 28476 45376 15296 20480 -60.0000/-60.0000/-60.0000 0.0000/0.0000/0.0000 +3 208 48 58599 93736 30968 24576 -60.0000/-60.0000/-60.0000 0.0000/0.0000/0.0000 +4 240 48 105724 164240 27638 22945 -60.0000/-60.0000/-60.0000 0.0000/0.9167/1.8008 +5 144 96 96543 156615 22706 109798 -506.3981/-502.5195/-60.0000 1.7900/110.1491/138.3581 +6 96 48 114212 157583 28194 91871 -506.2913/-503.3460/-411.9775 78.1123/124.2575/136.4059 +7 96 48 142940 234358 31690 95029 -506.1172/-503.3633/-412.8203 90.7064/105.1855/106.9902 +8 306 153 290960 421667 73118 147296 -505.8558/-503.1657/-422.5029 82.1507/93.3314/110.2594 +near_camera_up_tiles (sorted by XY tile-centre distance): +key=(-2, -2, -4, 1) xy_distance_m=5.39 vertices=1473 triangles=2560 skirt_triangles=512 upward_triangles=2048 z_m=-60.000/-60.000/-60.000 tile_span_p05_p95_m=0.000 diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/mesh-before-matched-summary.txt b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-before-matched-summary.txt new file mode 100644 index 0000000..0215da6 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-before-matched-summary.txt @@ -0,0 +1,19 @@ +version=1 voxel_um=250000 tiles=2370 camera_m=(-22.0, -19.0, -22.799999237060547) yaw=0.0 pitch=-4.0 +lod tiles mesh_tiles vertices triangles skirt_triangles upward_surface_triangles upward_centroid_z_m_p05/median/p95 tile_up_z_span_m_p50/p95/max +0 512 143 588792 892284 293148 300091 3.5000/7.6738/8.2568 0.4215/4.4898/4.4913 +1 448 119 509571 954666 323268 265175 -60.4932/-60.4491/8.1722 0.3356/0.9926/4.2986 +2 320 130 93432 150346 51220 55675 -76.2021/-60.8983/8.0124 0.3035/2.9398/8.5642 +3 208 135 91227 146168 33040 51843 -70.7997/-62.4979/8.0125 1.0249/11.2411/19.6108 +4 240 103 173336 278284 61076 58421 -505.3757/-411.1270/-62.3657 8.2807/88.3431/118.1829 +5 144 96 137096 173158 40930 117557 -506.3330/-502.1182/-62.4087 10.4471/110.1491/138.5524 +6 96 48 151997 168987 43320 92193 -506.3014/-503.3398/-410.9469 78.1123/124.2575/136.4059 +7 96 96 236120 321403 61348 120078 -505.8770/-502.4482/8.0020 0.0000/103.3187/110.4079 +8 306 306 553491 741221 166096 225866 -505.4486/-472.2318/8.0020 0.0000/92.1234/110.0400 +near_camera_up_tiles (sorted by XY tile-centre distance): +key=(-3, -3, 0, 0) xy_distance_m=2.24 vertices=8058 triangles=11660 skirt_triangles=3796 upward_triangles=3768 z_m=3.500/3.500/7.999 tile_span_p05_p95_m=4.445 +key=(-3, -3, 1, 0) xy_distance_m=2.24 vertices=668 triangles=1052 skirt_triangles=376 upward_triangles=676 z_m=8.000/8.087/8.252 tile_span_p05_p95_m=0.203 +key=(-2, -2, -4, 1) xy_distance_m=5.39 vertices=2562 triangles=8192 skirt_triangles=2048 upward_triangles=2048 z_m=-60.480/-60.471/-60.457 tile_span_p05_p95_m=0.018 +key=(-4, -3, 0, 0) xy_distance_m=6.08 vertices=7502 triangles=10753 skirt_triangles=3764 upward_triangles=2893 z_m=3.500/3.500/8.000 tile_span_p05_p95_m=4.486 +key=(-4, -3, 1, 0) xy_distance_m=6.08 vertices=1617 triangles=2507 skirt_triangles=928 upward_triangles=1579 z_m=8.000/8.099/8.372 tile_span_p05_p95_m=0.248 +key=(-3, -2, 0, 0) xy_distance_m=7.28 vertices=7772 triangles=10994 skirt_triangles=4024 upward_triangles=2874 z_m=3.500/3.500/8.000 tile_span_p05_p95_m=4.491 +key=(-3, -2, 1, 0) xy_distance_m=7.28 vertices=1883 triangles=2904 skirt_triangles=1116 upward_triangles=1788 z_m=8.000/8.115/8.363 tile_span_p05_p95_m=0.280 diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/mesh-before-summary.txt b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-before-summary.txt new file mode 100644 index 0000000..5327401 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-before-summary.txt @@ -0,0 +1,19 @@ +version=1 voxel_um=250000 tiles=2370 camera_m=(-11.612443923950195, -118.22123718261719, -19.84520721435547) yaw=0.0 pitch=0.0 +lod tiles mesh_tiles vertices triangles skirt_triangles upward_surface_triangles upward_centroid_z_m_p05/median/p95 tile_up_z_span_m_p50/p95/max +0 512 128 579561 840946 290676 288126 3.5000/7.7495/8.2586 0.3781/4.4867/4.4932 +1 448 124 503677 964366 331082 258850 -63.8505/-60.4908/8.1722 0.2965/2.9282/5.7538 +2 320 127 83460 135059 46994 53146 -71.5347/-60.5904/8.0124 0.5224/2.7093/6.0349 +3 208 126 93575 151669 35042 52200 -75.6995/-61.9814/8.0125 0.5630/13.5938/55.4526 +4 240 103 172283 277754 60622 58086 -505.4072/-410.6667/-62.3188 6.7752/88.3431/118.1829 +5 144 96 137096 173158 40930 117557 -506.3330/-502.1182/-62.4087 10.4471/110.1491/138.5524 +6 96 48 151997 168987 43320 92193 -506.3014/-503.3398/-410.9469 78.1123/124.2575/136.4059 +7 96 96 236120 321403 61348 120078 -505.8770/-502.4482/8.0020 0.0000/103.3187/110.4079 +8 306 306 553491 741221 166096 225866 -505.4486/-472.2318/8.0020 0.0000/92.1234/110.0400 +near_camera_up_tiles (sorted by XY tile-centre distance): +key=(-2, -15, 0, 0) xy_distance_m=2.25 vertices=7941 triangles=11569 skirt_triangles=3860 upward_triangles=3613 z_m=3.500/3.500/8.000 tile_span_p05_p95_m=4.472 +key=(-2, -15, 1, 0) xy_distance_m=2.25 vertices=1159 triangles=1557 skirt_triangles=684 upward_triangles=873 z_m=8.000/8.082/8.275 tile_span_p05_p95_m=0.250 +key=(-1, -8, -4, 1) xy_distance_m=4.03 vertices=2562 triangles=8192 skirt_triangles=2048 upward_triangles=2048 z_m=-60.494/-60.494/-60.493 tile_span_p05_p95_m=0.001 +key=(-2, -16, 0, 0) xy_distance_m=5.79 vertices=8315 triangles=12274 skirt_triangles=3928 upward_triangles=4250 z_m=3.500/7.740/8.000 tile_span_p05_p95_m=4.459 +key=(-2, -16, 1, 0) xy_distance_m=5.79 vertices=677 triangles=700 skirt_triangles=520 upward_triangles=180 z_m=8.000/8.008/8.057 tile_span_p05_p95_m=0.036 +key=(-1, -15, 0, 0) xy_distance_m=7.93 vertices=6918 triangles=9878 skirt_triangles=3384 upward_triangles=2398 z_m=3.500/3.500/8.000 tile_span_p05_p95_m=4.453 +key=(-1, -15, 1, 0) xy_distance_m=7.93 vertices=1611 triangles=2700 skirt_triangles=652 upward_triangles=2048 z_m=8.001/8.202/8.323 tile_span_p05_p95_m=0.242 diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-after-summary.txt b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-after-summary.txt new file mode 100644 index 0000000..358b53a --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-after-summary.txt @@ -0,0 +1,12 @@ +version=1 voxel_um=250000 tiles=2553 camera_m=(0.0, -35.0, -487.94000244140625) yaw=0.0 pitch=-22.0 +lod tiles mesh_tiles vertices triangles skirt_triangles upward_surface_triangles upward_centroid_z_m_p05/median/p95 tile_up_z_span_m_p50/p95/max +0 512 0 0 0 0 0 nan/nan/nan nan/nan/nan +1 448 0 0 0 0 0 nan/nan/nan nan/nan/nan +2 448 0 0 0 0 0 nan/nan/nan nan/nan/nan +3 384 0 0 0 0 0 nan/nan/nan nan/nan/nan +4 320 52 139437 209316 34996 8129 -56.2002/-42.7865/-32.7998 6.2138/32.5482/53.6770 +5 144 102 100254 158707 25586 96013 -506.9092/-503.1813/-378.0397 12.8110/109.5153/138.3581 +6 96 61 110399 149031 17088 92803 -506.4873/-503.3776/-412.3926 53.2054/124.2575/136.4059 +7 48 48 132222 219052 16356 95003 -506.1172/-503.3639/-412.8861 90.7064/105.1855/106.9902 +8 153 153 229080 384768 82518 147226 -505.8568/-503.1676/-422.8789 82.0687/93.3180/110.0400 +near_camera_up_tiles (sorted by XY tile-centre distance): diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-after-summary.txt b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-after-summary.txt new file mode 100644 index 0000000..7ae14e7 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-after-summary.txt @@ -0,0 +1,5 @@ +version=1 voxel_um=250000 tiles=960 camera_m=(-11.612443923950195, -118.22123718261719, -506.7861328125) yaw=0.0 pitch=0.0 +lod tiles mesh_tiles vertices triangles skirt_triangles upward_surface_triangles upward_centroid_z_m_p05/median/p95 tile_up_z_span_m_p50/p95/max +0 512 0 0 0 0 0 nan/nan/nan nan/nan/nan +1 448 0 0 0 0 0 nan/nan/nan nan/nan/nan +near_camera_up_tiles (sorted by XY tile-centre distance): diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-cap-after-summary.txt b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-cap-after-summary.txt new file mode 100644 index 0000000..6f91307 --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-cap-after-summary.txt @@ -0,0 +1,5 @@ +version=1 voxel_um=250000 tiles=960 camera_m=(0.0, -35.0, -75.0) yaw=0.0 pitch=0.0 +lod tiles mesh_tiles vertices triangles skirt_triangles upward_surface_triangles upward_centroid_z_m_p05/median/p95 tile_up_z_span_m_p50/p95/max +0 512 0 0 0 0 0 nan/nan/nan nan/nan/nan +1 448 76 153596 265964 51168 82938 -43.9418/-14.9892/-6.3079 0.8803/5.3022/10.8345 +near_camera_up_tiles (sorted by XY tile-centre distance): diff --git a/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-ground-after-summary.txt b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-ground-after-summary.txt new file mode 100644 index 0000000..dc5d32a --- /dev/null +++ b/Standalone/Research/WorldAssemblerM3/Linux17/mesh-sw-l1-ground-after-summary.txt @@ -0,0 +1,5 @@ +version=1 voxel_um=250000 tiles=960 camera_m=(0.0, -35.0, -42.0) yaw=0.0 pitch=-8.0 +lod tiles mesh_tiles vertices triangles skirt_triangles upward_surface_triangles upward_centroid_z_m_p05/median/p95 tile_up_z_span_m_p50/p95/max +0 512 25 80260 139176 28088 34692 -43.9640/-33.5509/-32.8013 0.7072/4.9851/7.0117 +1 448 131 295583 474122 103438 230953 -33.6783/3.9507/4.1428 0.3514/4.4247/10.8345 +near_camera_up_tiles (sorted by XY tile-centre distance): diff --git a/Standalone/Source/LinuxOffscreenCapture.cpp b/Standalone/Source/LinuxOffscreenCapture.cpp index 95757cc..1dfe7f3 100644 --- a/Standalone/Source/LinuxOffscreenCapture.cpp +++ b/Standalone/Source/LinuxOffscreenCapture.cpp @@ -25,6 +25,8 @@ namespace float Position[3]; float Normal[3]; float Height; + float WorldPosition[3]; + float TileData[4]; }; struct FScene @@ -32,6 +34,8 @@ namespace std::uint32_t VoxelSizeMicrons=0; std::array CameraMeters{}; double YawDegrees=0.0,PitchDegrees=0.0; + float MinimumHeight=std::numeric_limits::infinity(); + float MaximumHeight=-std::numeric_limits::infinity(); std::vector Vertices; std::vector Indices; std::uint64_t Triangles=0,SkirtTriangles=0; @@ -70,7 +74,8 @@ namespace if(!Read(File,SurfaceVertices)||!Read(File,SkirtCount)||!Read(File,VertexCount) ||!Read(File,IndexCount)||!Read(File,MaskCount) ||VertexCount>10000000||IndexCount>60000000||MaskCount>20000000 - ||IndexCount%3!=0||(MaskCount!=0&&MaskCount!=IndexCount/3)) + ||IndexCount%3!=0||(MaskCount!=0&&MaskCount!=IndexCount/3) + ||Key[3]<0||Key[3]>8) {Error="tile mesh header is malformed";return false;} if(TotalVertices+VertexCount>std::numeric_limits::max() ||TotalIndices+IndexCount>std::numeric_limits::max()) @@ -86,6 +91,25 @@ namespace for(float& Value:Scene.Vertices[I].Normal)if(!Read(File,Value)) {Error="tile normals are truncated";return false;} Scene.Vertices[I].Height=Scene.Vertices[I].Position[2]; + Scene.MinimumHeight=std::min(Scene.MinimumHeight,Scene.Vertices[I].Height); + Scene.MaximumHeight=std::max(Scene.MaximumHeight,Scene.Vertices[I].Height); + } + const double TileVoxels=static_cast(32u<(TileVoxels + *static_cast(Scene.VoxelSizeMicrons)/1000000.0); + const float TileOriginX=static_cast(static_cast(Key[0]) + *TileExtentMeters); + const float TileOriginY=static_cast(static_cast(Key[1]) + *TileExtentMeters); + for(std::size_t I=Base;I(Key[3]); } const std::size_t IndexOffset=Scene.Indices.size(); Scene.Indices.resize(IndexOffset+IndexCount); @@ -151,8 +175,12 @@ precision highp float; layout(location=0) in vec3 inCameraPosition; layout(location=1) in vec3 inNormal; layout(location=2) in float inHeight; +layout(location=3) in vec3 inWorldPosition; +layout(location=4) in vec4 inTileData; out vec3 vNormal; out float vHeight; +out vec3 vWorldPosition; +out vec4 vTileData; uniform float uTanHalfHorizontal; uniform float uTanHalfVertical; uniform float uNear; @@ -165,19 +193,54 @@ void main() inCameraPosition.y/uTanHalfVertical,clipZ,z); vNormal=normalize(inNormal); vHeight=inHeight; + vWorldPosition=inWorldPosition; + vTileData=inTileData; })GLSL"; static constexpr char FragmentSource[]=R"GLSL(#version 300 es precision highp float; in vec3 vNormal; in float vHeight; +in vec3 vWorldPosition; +in vec4 vTileData; out vec4 outColor; +uniform int uReadableMode; +uniform int uTileEdges; +uniform float uHeightCenter; +uniform float uHeightRange; +uniform float uTileEdgeWidth; +uniform vec3 uLightDirection; void main() { vec3 n=normalize(vNormal); - vec3 normalColor=abs(n)*0.78+vec3(0.12); - float band=mod(floor((vHeight+10000.0)/80.0),2.0); - vec3 bandColor=mix(vec3(0.24,0.31,0.37),vec3(0.39,0.42,0.35),band); - outColor=vec4(mix(bandColor,normalColor,0.68),1.0); + vec3 color; + if(uReadableMode==0) + { + vec3 normalColor=abs(n)*0.78+vec3(0.12); + float band=mod(floor((vHeight+10000.0)/80.0),2.0); + vec3 bandColor=mix(vec3(0.24,0.31,0.37),vec3(0.39,0.42,0.35),band); + color=mix(bandColor,normalColor,0.68); + } + else + { + float heightT=clamp(0.5+(vHeight-uHeightCenter)/max(uHeightRange,0.001),0.0,1.0); + vec3 heightTint=mix(vec3(0.80,0.91,1.0),vec3(1.0,0.91,0.77),heightT); + float diffuse=max(dot(n,normalize(uLightDirection)),0.0); + float illumination=0.62+0.38*diffuse; + color=vec3(0.64,0.62,0.56)*heightTint*illumination; + } + if(uTileEdges!=0&&vTileData.z>0.0) + { + vec2 local=mod(vWorldPosition.xy-vTileData.xy,vTileData.z); + vec2 edge=min(local,vec2(vTileData.z)-local); + float distanceToTileEdge=min(edge.x,edge.y); + float antialias=max(fwidth(distanceToTileEdge),0.005); + float line=1.0-smoothstep(uTileEdgeWidth-antialias, + uTileEdgeWidth+antialias,distanceToTileEdge); + vec3 edgeColor=mix(vec3(0.16,0.22,0.25),vec3(0.30,0.23,0.14), + clamp(vTileData.w/8.0,0.0,1.0)); + color=mix(color,edgeColor,0.32*line); + } + outColor=vec4(color,1.0); })GLSL"; const GLuint VS=CompileShader(GL_VERTEX_SHADER,VertexSource); const GLuint FS=CompileShader(GL_FRAGMENT_SHADER,FragmentSource); @@ -224,7 +287,8 @@ void main() } bool Render(FScene& Scene,const std::filesystem::path& Output,int Width,int Height, - double HorizontalFovDegrees) + double HorizontalFovDegrees,bool ReadableMode,bool TileEdges, + double TileEdgeWidthMeters) { EGLDisplay Display=MakeDisplay(); EGLint Major=0,Minor=0; @@ -304,6 +368,10 @@ void main() reinterpret_cast(offsetof(FVertex,Normal))); glEnableVertexAttribArray(2);glVertexAttribPointer(2,1,GL_FLOAT,GL_FALSE,sizeof(FVertex), reinterpret_cast(offsetof(FVertex,Height))); + glEnableVertexAttribArray(3);glVertexAttribPointer(3,3,GL_FLOAT,GL_FALSE,sizeof(FVertex), + reinterpret_cast(offsetof(FVertex,WorldPosition))); + glEnableVertexAttribArray(4);glVertexAttribPointer(4,4,GL_FLOAT,GL_FALSE,sizeof(FVertex), + reinterpret_cast(offsetof(FVertex,TileData))); glViewport(0,0,Width,Height);glDisable(GL_CULL_FACE);glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL);glClearColor(0.035f,0.055f,0.075f,1.0f); glClearDepthf(1.0f);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); @@ -312,6 +380,14 @@ void main() glUniform1f(glGetUniformLocation(Program,"uTanHalfVertical"),static_cast(TanHalfVertical)); glUniform1f(glGetUniformLocation(Program,"uNear"),static_cast(Near)); glUniform1f(glGetUniformLocation(Program,"uFar"),static_cast(Far)); + glUniform1i(glGetUniformLocation(Program,"uReadableMode"),ReadableMode?1:0); + glUniform1i(glGetUniformLocation(Program,"uTileEdges"),TileEdges?1:0); + glUniform1f(glGetUniformLocation(Program,"uHeightCenter"), + static_cast(Scene.CameraMeters[2])); + glUniform1f(glGetUniformLocation(Program,"uHeightRange"),64.0f); + glUniform1f(glGetUniformLocation(Program,"uTileEdgeWidth"), + static_cast(TileEdgeWidthMeters)); + glUniform3f(glGetUniformLocation(Program,"uLightDirection"),-0.42f,-0.58f,0.70f); glDrawElements(GL_TRIANGLES,static_cast(Scene.Indices.size()),GL_UNSIGNED_INT,nullptr); glFinish(); std::vector Pixels(static_cast(Width)*Height*4); @@ -323,9 +399,10 @@ void main() { std::error_code SizeError; const auto Bytes=std::filesystem::file_size(Output,SizeError); - std::printf("[OffscreenCapture] triangles=%llu tiles=%u skirts=%llu png_bytes=%llu status=PASS path=%s\n", + std::printf("[OffscreenCapture] triangles=%llu tiles=%u skirts=%llu shading=%s tile_edges=%s edge_width_m=%.3f png_bytes=%llu status=PASS path=%s\n", static_cast(Scene.Triangles),Scene.TileCount, static_cast(Scene.SkirtTriangles), + ReadableMode?"readable":"normal",TileEdges?"on":"off",TileEdgeWidthMeters, static_cast(SizeError?0:Bytes),Output.string().c_str()); } glDeleteProgram(Program);glDeleteBuffers(1,&Ebo);glDeleteBuffers(1,&Vbo); @@ -341,12 +418,13 @@ int main(int argc,char** argv) { if(argc<3) { - std::fprintf(stderr,"Usage: %s scene.vfmesh output.png [--size=WIDTHxHEIGHT] [--fov-deg=90] [--camera-m=X,Y,Z] [--yaw-deg=N] [--pitch-deg=N]\n",argv[0]); + std::fprintf(stderr,"Usage: %s scene.vfmesh output.png [--size=WIDTHxHEIGHT] [--fov-deg=90] [--camera-m=X,Y,Z] [--yaw-deg=N] [--pitch-deg=N] [--shade=readable|normal] [--tile-edges=on|off] [--tile-edge-width-m=N]\n",argv[0]); return 2; } int Width=2560,Height=1440;double Fov=90.0; bool HasYaw=false,HasPitch=false;double Yaw=0.0,Pitch=0.0; bool HasCamera=false;std::array Camera{}; + bool ReadableMode=true,TileEdges=false;double TileEdgeWidthMeters=0.15; for(int I=3;I(Arg.size()),Arg.data());return 2;} } FScene Scene;std::string Error; @@ -388,10 +488,12 @@ int main(int argc,char** argv) if(HasCamera)Scene.CameraMeters=Camera; if(HasYaw)Scene.YawDegrees=Yaw; if(HasPitch)Scene.PitchDegrees=Pitch; - std::printf("[OffscreenScene] voxels_per_meter=%.6f camera_m=(%.3f,%.3f,%.3f) yaw=%.2f pitch=%.2f vertices=%zu triangles=%llu\n", + std::printf("[OffscreenScene] voxels_per_meter=%.6f camera_m=(%.3f,%.3f,%.3f) yaw=%.2f pitch=%.2f height_m=%.3f..%.3f shade=%s tile_edges=%s vertices=%zu triangles=%llu\n", 1000000.0/Scene.VoxelSizeMicrons,Scene.CameraMeters[0],Scene.CameraMeters[1],Scene.CameraMeters[2], - Scene.YawDegrees,Scene.PitchDegrees,Scene.Vertices.size(), + Scene.YawDegrees,Scene.PitchDegrees,Scene.MinimumHeight,Scene.MaximumHeight, + ReadableMode?"readable":"normal",TileEdges?"on":"off",Scene.Vertices.size(), static_cast(Scene.Triangles)); - return Render(Scene,argv[2],Width,Height,Fov)?0:3; + return Render(Scene,argv[2],Width,Height,Fov,ReadableMode,TileEdges, + TileEdgeWidthMeters)?0:3; } diff --git a/Standalone/Source/StreamBenchmarkHeadless.cpp b/Standalone/Source/StreamBenchmarkHeadless.cpp index 973591b..6f052b9 100644 --- a/Standalone/Source/StreamBenchmarkHeadless.cpp +++ b/Standalone/Source/StreamBenchmarkHeadless.cpp @@ -63,6 +63,7 @@ namespace float CameraYawDegrees=0.0f; float CameraPitchDegrees=0.0f; std::filesystem::path MeshExportPath; + std::filesystem::path WorldAssemblyManifestOutputPath; }; bool ParseInteger(std::string_view text,int& output) @@ -115,6 +116,7 @@ namespace " --region-crossing (compile entering Core regions at the camera step)\n" " --column-cache=shared|thread-local (default: shared)\n" " --mesh-export=FILE (write the exact generated tile meshes for offline rendering)\n" + " --world-assembler-manifest-output=FILE (write the resolved plan for diagnostics)\n" " --profile-column-overlap --far-horizon-lod8-step=N --force-generate\n" " --seed=N --recipe=surface-world|floating-islands\n" " --auto-surface-camera (place the 27-tile cube on this seed's surface)\n" @@ -204,6 +206,13 @@ namespace if(options.MeshExportPath.empty()) {std::fprintf(stderr,"--mesh-export needs a file path\n");return false;} } + else if(arg.starts_with("--world-assembler-manifest-output=")) + { + options.WorldAssemblyManifestOutputPath=std::filesystem::path( + arg.substr(std::string_view("--world-assembler-manifest-output=").size())); + if(options.WorldAssemblyManifestOutputPath.empty()) + {std::fprintf(stderr,"--world-assembler-manifest-output needs a file path\n");return false;} + } else if(arg.starts_with("--workers=")) {if(!readInt("--workers=",options.WorkerCount))return false;} else if(arg.starts_with("--clip-radius=")) @@ -314,6 +323,22 @@ int main(int argc,char** argv) &&!StandaloneWorldAssemblyPrototype::AttachFloatingIslandWorldAssembly( *ownerWorld,ownerJsonRoot,worldAssembly,error)) {std::fprintf(stderr,"Floating-island assembly setup failed: %s\n",error.c_str());return 2;} + if(!options.WorldAssemblyManifestOutputPath.empty()) + { + std::error_code directoryError; + const auto parent=options.WorldAssemblyManifestOutputPath.parent_path(); + if(!parent.empty())std::filesystem::create_directories(parent,directoryError); + if(directoryError) + {std::fprintf(stderr,"Manifest output directory failed: %s\n",directoryError.message().c_str());return 2;} + std::ofstream manifestFile(options.WorldAssemblyManifestOutputPath,std::ios::binary|std::ios::trunc); + if(!manifestFile) + {std::fprintf(stderr,"Cannot write manifest output: %s\n",options.WorldAssemblyManifestOutputPath.string().c_str());return 2;} + manifestFile<