wip(assembler): M1 repair round -- raised block and cliff fixed; native 7x faster than legacy
Luna, M1 repair round: the rectangular raised block and the broken cliff shared one cause, a type-2 solid AABB in the generated plan; it is now a tapered, terrain-following shelf, and a negative-control audit catches the old box behaviour; seam classification check passes. Bound audit 298 boxes / 8,046 samples, 0 misses. Evaluator and 120-tile density/mesh/payload/ topology hashes identical at W1/W8/W16. Cave regression: walkability 5,642/5,642, 64/64 tiles. Legacy mismatch unchanged (0 biome mismatches, 18.14% signs). Speed (matched workloads): 120-tile full detail 0.089 s native vs 0.625 s legacy; 529-tile clipmap 3.858 s vs 11.687 s -- 2.29 s above the ~1.57 s aim; LOD8 dominates (165 unknown tiles, 13.27 M field calls, 10.88 M column-cache misses). My capture review: coast matches legacy closely; surface clean but a dark flat slab on the far horizon; cliff shelf renders as a stack of thin plates with back faces showing (sub-voxel shelf thickness suspected). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
fcb16fd265
commit
2c20f9eaea
61 files changed
+4308
-165
No files matched your search
@@ -6919,6 +6919,10 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
std::vector<FHashedTile> DensityRows,MeshRows,PayloadRows,TopologyRows;
|
||||
int32 Finished=0,NeighborhoodFinished=0,FullDetailFinished=0;
|
||||
int32 FullDetailExpected=0;
|
||||
uint64 NativeSolidBoxes=0,NativeAirBoxes=0,NativeMixedBoxes=0,NativeUnknownBoxes=0;
|
||||
uint64 NativeFieldCalls=0,NativeColumnHits=0,NativeColumnMisses=0,NativeMeshingSkips=0;
|
||||
double NativeClassificationMilliseconds=0.0,NativeColumnComputeMilliseconds=0.0;
|
||||
double NativeMeshingMilliseconds=0.0;
|
||||
for(const FVoxelTileKey& Tile:Desired.Tiles)
|
||||
if(Tile.Level<World.FullResClipLevels)++FullDetailExpected;
|
||||
Clock::time_point NeighborhoodReady{},FullDetailReady{},WholeViewReady{};
|
||||
@@ -6940,6 +6944,17 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
{
|
||||
++FullDetailFinished;
|
||||
FullDetailReady=std::max(FullDetailReady,Tile.CompletedAt);
|
||||
NativeSolidBoxes+=Tile.CoreDiagnostics.solidBoxes;
|
||||
NativeAirBoxes+=Tile.CoreDiagnostics.airBoxes;
|
||||
NativeMixedBoxes+=Tile.CoreDiagnostics.mixedBoxes;
|
||||
NativeUnknownBoxes+=Tile.CoreDiagnostics.unknownBoxes;
|
||||
NativeFieldCalls+=Tile.CoreDiagnostics.fieldCalls;
|
||||
NativeColumnHits+=Tile.CoreDiagnostics.columnCacheHits;
|
||||
NativeColumnMisses+=Tile.CoreDiagnostics.columnCacheMisses;
|
||||
NativeMeshingSkips+=Tile.CoreDiagnostics.meshingSkipped?1u:0u;
|
||||
NativeClassificationMilliseconds+=Tile.CoreDiagnostics.classificationMilliseconds;
|
||||
NativeColumnComputeMilliseconds+=Tile.CoreDiagnostics.columnComputeMilliseconds;
|
||||
NativeMeshingMilliseconds+=Tile.CoreDiagnostics.meshingMilliseconds;
|
||||
}
|
||||
if(bHashDensity)
|
||||
{
|
||||
@@ -6973,6 +6988,17 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
WorkerCount,ShapeSeconds,NeighborhoodMeshSeconds,NeighborhoodSeconds,
|
||||
FullDetailSeconds,WholeViewSeconds,NeighborhoodFinished,
|
||||
FullDetailFinished,FullDetailExpected,Finished,Desired.Tiles.size(),StreamSeconds);
|
||||
std::printf("[WorldAssemblerTilePipeline] full_detail_tiles=%d solid_boxes=%llu air_boxes=%llu mixed_boxes=%llu unknown_boxes=%llu whole_tile_skips=%llu field_calls=%llu column_cache_hits=%llu column_cache_misses=%llu column_compute_worker_ms=%.3f classification_worker_ms=%.3f meshing_worker_ms=%.3f\n",
|
||||
FullDetailExpected,static_cast<unsigned long long>(NativeSolidBoxes),
|
||||
static_cast<unsigned long long>(NativeAirBoxes),
|
||||
static_cast<unsigned long long>(NativeMixedBoxes),
|
||||
static_cast<unsigned long long>(NativeUnknownBoxes),
|
||||
static_cast<unsigned long long>(NativeMeshingSkips),
|
||||
static_cast<unsigned long long>(NativeFieldCalls),
|
||||
static_cast<unsigned long long>(NativeColumnHits),
|
||||
static_cast<unsigned long long>(NativeColumnMisses),
|
||||
NativeColumnComputeMilliseconds,NativeClassificationMilliseconds,
|
||||
NativeMeshingMilliseconds);
|
||||
|
||||
bool bHashesPassing=true;
|
||||
if(bHashDensity)
|
||||
@@ -7066,6 +7092,25 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
auto PlayerNeighborhoodCompleted=std::chrono::steady_clock::time_point{};
|
||||
std::vector<FStandaloneCpuTile> CacheTiles;
|
||||
if(!BakeCachePath.empty())CacheTiles.reserve(Desired.Tiles.size());
|
||||
uint64 NativeSolidBoxes=0,NativeAirBoxes=0,NativeMixedBoxes=0,NativeUnknownBoxes=0;
|
||||
uint64 NativeFieldCalls=0,NativeColumnHits=0,NativeColumnMisses=0,NativeMeshingSkips=0;
|
||||
uint64 NativeFloatFieldCalls=0,NativeLatticeFieldCalls=0,NativeUnclampedFieldCalls=0;
|
||||
double NativeClassificationMilliseconds=0.0,NativeColumnComputeMilliseconds=0.0;
|
||||
double NativeMeshingMilliseconds=0.0;
|
||||
uint64 WholeSolidBoxes=0,WholeAirBoxes=0,WholeMixedBoxes=0,WholeUnknownBoxes=0;
|
||||
uint64 WholeFieldCalls=0,WholeColumnHits=0,WholeColumnMisses=0,WholeTileSkips=0;
|
||||
uint64 WholeFloatFieldCalls=0,WholeLatticeFieldCalls=0,WholeUnclampedFieldCalls=0;
|
||||
double WholeClassificationMilliseconds=0.0,WholeColumnComputeMilliseconds=0.0;
|
||||
double WholeMeshingMilliseconds=0.0;
|
||||
uint64 WholeSolidBoxesByLevel[MaxLevels+1]{},WholeAirBoxesByLevel[MaxLevels+1]{};
|
||||
uint64 WholeMixedBoxesByLevel[MaxLevels+1]{},WholeUnknownBoxesByLevel[MaxLevels+1]{};
|
||||
uint64 WholeFieldCallsByLevel[MaxLevels+1]{},WholeColumnHitsByLevel[MaxLevels+1]{};
|
||||
uint64 WholeFloatFieldCallsByLevel[MaxLevels+1]{},WholeLatticeFieldCallsByLevel[MaxLevels+1]{};
|
||||
uint64 WholeUnclampedFieldCallsByLevel[MaxLevels+1]{};
|
||||
uint64 WholeColumnMissesByLevel[MaxLevels+1]{},WholeTileSkipsByLevel[MaxLevels+1]{};
|
||||
double WholeClassificationMillisecondsByLevel[MaxLevels+1]{};
|
||||
double WholeColumnComputeMillisecondsByLevel[MaxLevels+1]{};
|
||||
double WholeMeshingMillisecondsByLevel[MaxLevels+1]{};
|
||||
if(CoreWorld&&!FarAudit)
|
||||
{
|
||||
// Tile keys and band limits are already captured in Desired. Core owns field and
|
||||
@@ -7115,6 +7160,43 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
if(FarAudit)FarAudit->AuditTile(Tile);
|
||||
++Finished;
|
||||
const int32 Level=Tile.Key.Level;
|
||||
if(CoreWorld)
|
||||
{
|
||||
WholeSolidBoxes+=Tile.CoreDiagnostics.solidBoxes;
|
||||
WholeAirBoxes+=Tile.CoreDiagnostics.airBoxes;
|
||||
WholeMixedBoxes+=Tile.CoreDiagnostics.mixedBoxes;
|
||||
WholeUnknownBoxes+=Tile.CoreDiagnostics.unknownBoxes;
|
||||
WholeFieldCalls+=Tile.CoreDiagnostics.fieldCalls;
|
||||
WholeFloatFieldCalls+=Tile.CoreDiagnostics.floatFieldCalls;
|
||||
WholeLatticeFieldCalls+=Tile.CoreDiagnostics.latticeFieldCalls;
|
||||
WholeUnclampedFieldCalls+=Tile.CoreDiagnostics.unclampedFieldCalls;
|
||||
WholeColumnHits+=Tile.CoreDiagnostics.columnCacheHits;
|
||||
WholeColumnMisses+=Tile.CoreDiagnostics.columnCacheMisses;
|
||||
WholeTileSkips+=Tile.CoreDiagnostics.meshingSkipped?1u:0u;
|
||||
WholeClassificationMilliseconds+=Tile.CoreDiagnostics.classificationMilliseconds;
|
||||
WholeColumnComputeMilliseconds+=Tile.CoreDiagnostics.columnComputeMilliseconds;
|
||||
WholeMeshingMilliseconds+=Tile.CoreDiagnostics.meshingMilliseconds;
|
||||
if(Level>=0&&Level<=MaxLevels)
|
||||
{
|
||||
WholeSolidBoxesByLevel[Level]+=Tile.CoreDiagnostics.solidBoxes;
|
||||
WholeAirBoxesByLevel[Level]+=Tile.CoreDiagnostics.airBoxes;
|
||||
WholeMixedBoxesByLevel[Level]+=Tile.CoreDiagnostics.mixedBoxes;
|
||||
WholeUnknownBoxesByLevel[Level]+=Tile.CoreDiagnostics.unknownBoxes;
|
||||
WholeFieldCallsByLevel[Level]+=Tile.CoreDiagnostics.fieldCalls;
|
||||
WholeFloatFieldCallsByLevel[Level]+=Tile.CoreDiagnostics.floatFieldCalls;
|
||||
WholeLatticeFieldCallsByLevel[Level]+=Tile.CoreDiagnostics.latticeFieldCalls;
|
||||
WholeUnclampedFieldCallsByLevel[Level]+=Tile.CoreDiagnostics.unclampedFieldCalls;
|
||||
WholeColumnHitsByLevel[Level]+=Tile.CoreDiagnostics.columnCacheHits;
|
||||
WholeColumnMissesByLevel[Level]+=Tile.CoreDiagnostics.columnCacheMisses;
|
||||
WholeTileSkipsByLevel[Level]+=Tile.CoreDiagnostics.meshingSkipped?1u:0u;
|
||||
WholeClassificationMillisecondsByLevel[Level]
|
||||
+=Tile.CoreDiagnostics.classificationMilliseconds;
|
||||
WholeColumnComputeMillisecondsByLevel[Level]
|
||||
+=Tile.CoreDiagnostics.columnComputeMilliseconds;
|
||||
WholeMeshingMillisecondsByLevel[Level]
|
||||
+=Tile.CoreDiagnostics.meshingMilliseconds;
|
||||
}
|
||||
}
|
||||
if(PlayerNeighborhoodTiles.contains(Tile.Key))
|
||||
{
|
||||
PlayerNeighborhoodReady.insert(Tile.Key);
|
||||
@@ -7140,7 +7222,24 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
if(Tile.bHasPayloadHash)PayloadHashRows[Level].push_back({Tile.Key,Tile.PayloadHash});
|
||||
if(Tile.bHasTopologyHash)TopologyHashRows[Level].push_back({Tile.Key,Tile.TopologyHash});
|
||||
}
|
||||
if(Level<World.FullResClipLevels)++FullDetailFinished;
|
||||
if(Level<World.FullResClipLevels)
|
||||
{
|
||||
++FullDetailFinished;
|
||||
NativeSolidBoxes+=Tile.CoreDiagnostics.solidBoxes;
|
||||
NativeAirBoxes+=Tile.CoreDiagnostics.airBoxes;
|
||||
NativeMixedBoxes+=Tile.CoreDiagnostics.mixedBoxes;
|
||||
NativeUnknownBoxes+=Tile.CoreDiagnostics.unknownBoxes;
|
||||
NativeFieldCalls+=Tile.CoreDiagnostics.fieldCalls;
|
||||
NativeFloatFieldCalls+=Tile.CoreDiagnostics.floatFieldCalls;
|
||||
NativeLatticeFieldCalls+=Tile.CoreDiagnostics.latticeFieldCalls;
|
||||
NativeUnclampedFieldCalls+=Tile.CoreDiagnostics.unclampedFieldCalls;
|
||||
NativeColumnHits+=Tile.CoreDiagnostics.columnCacheHits;
|
||||
NativeColumnMisses+=Tile.CoreDiagnostics.columnCacheMisses;
|
||||
NativeMeshingSkips+=Tile.CoreDiagnostics.meshingSkipped?1u:0u;
|
||||
NativeClassificationMilliseconds+=Tile.CoreDiagnostics.classificationMilliseconds;
|
||||
NativeColumnComputeMilliseconds+=Tile.CoreDiagnostics.columnComputeMilliseconds;
|
||||
NativeMeshingMilliseconds+=Tile.CoreDiagnostics.meshingMilliseconds;
|
||||
}
|
||||
if(bShardAudit&&Level==0)
|
||||
{
|
||||
const FMeshSheetAudit TileAudit=AuditThinMeshSheets(Tile,CameraPositionVoxels,
|
||||
@@ -7265,6 +7364,21 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
else
|
||||
std::printf("[StreamFullDetail] wall=%.3fs generated=%d/%d resident_tiles_cpu_only=1 hash=off\n",
|
||||
FullDetailSeconds,FullDetailFinished,FullDetailExpected);
|
||||
if(CoreWorld)
|
||||
std::printf("[WorldAssemblerTilePipeline] full_detail_tiles=%d solid_boxes=%llu air_boxes=%llu mixed_boxes=%llu unknown_boxes=%llu whole_tile_skips=%llu field_calls=%llu float_field_calls=%llu lattice_field_calls=%llu unclamped_field_calls=%llu column_cache_hits=%llu column_cache_misses=%llu column_compute_worker_ms=%.3f classification_worker_ms=%.3f meshing_worker_ms=%.3f\n",
|
||||
FullDetailExpected,static_cast<unsigned long long>(NativeSolidBoxes),
|
||||
static_cast<unsigned long long>(NativeAirBoxes),
|
||||
static_cast<unsigned long long>(NativeMixedBoxes),
|
||||
static_cast<unsigned long long>(NativeUnknownBoxes),
|
||||
static_cast<unsigned long long>(NativeMeshingSkips),
|
||||
static_cast<unsigned long long>(NativeFieldCalls),
|
||||
static_cast<unsigned long long>(NativeFloatFieldCalls),
|
||||
static_cast<unsigned long long>(NativeLatticeFieldCalls),
|
||||
static_cast<unsigned long long>(NativeUnclampedFieldCalls),
|
||||
static_cast<unsigned long long>(NativeColumnHits),
|
||||
static_cast<unsigned long long>(NativeColumnMisses),
|
||||
NativeColumnComputeMilliseconds,NativeClassificationMilliseconds,
|
||||
NativeMeshingMilliseconds);
|
||||
std::fflush(stdout);
|
||||
}
|
||||
}
|
||||
@@ -7312,6 +7426,40 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
std::max(0.0,100.0-WorkerBusyPercent),
|
||||
static_cast<double>(TotalMeshPayloadAllocatedBytes)/1048576.0,
|
||||
static_cast<double>(TotalViewerOutputBytes)/1048576.0,DesiredTotal);
|
||||
if(CoreWorld)
|
||||
std::printf("[WorldAssemblerWholeViewPipeline] tiles=%d solid_boxes=%llu air_boxes=%llu mixed_boxes=%llu unknown_boxes=%llu whole_tile_skips=%llu field_calls=%llu float_field_calls=%llu lattice_field_calls=%llu unclamped_field_calls=%llu column_cache_hits=%llu column_cache_misses=%llu column_compute_worker_ms=%.3f classification_worker_ms=%.3f meshing_worker_ms=%.3f\n",
|
||||
DesiredTotal,static_cast<unsigned long long>(WholeSolidBoxes),
|
||||
static_cast<unsigned long long>(WholeAirBoxes),
|
||||
static_cast<unsigned long long>(WholeMixedBoxes),
|
||||
static_cast<unsigned long long>(WholeUnknownBoxes),
|
||||
static_cast<unsigned long long>(WholeTileSkips),
|
||||
static_cast<unsigned long long>(WholeFieldCalls),
|
||||
static_cast<unsigned long long>(WholeFloatFieldCalls),
|
||||
static_cast<unsigned long long>(WholeLatticeFieldCalls),
|
||||
static_cast<unsigned long long>(WholeUnclampedFieldCalls),
|
||||
static_cast<unsigned long long>(WholeColumnHits),
|
||||
static_cast<unsigned long long>(WholeColumnMisses),
|
||||
WholeColumnComputeMilliseconds,WholeClassificationMilliseconds,
|
||||
WholeMeshingMilliseconds);
|
||||
if(CoreWorld)
|
||||
for(int32 Level=0;Level<=MaxLevels;++Level)
|
||||
if(TilesByLevel[Level]>0)
|
||||
std::printf("[WorldAssemblerLODProfile] lod=%d tiles=%llu solid_boxes=%llu air_boxes=%llu mixed_boxes=%llu unknown_boxes=%llu whole_tile_skips=%llu field_calls=%llu float_field_calls=%llu lattice_field_calls=%llu unclamped_field_calls=%llu column_hits=%llu column_misses=%llu column_compute_worker_ms=%.3f classification_worker_ms=%.3f meshing_worker_ms=%.3f\n",
|
||||
Level,static_cast<unsigned long long>(TilesByLevel[Level]),
|
||||
static_cast<unsigned long long>(WholeSolidBoxesByLevel[Level]),
|
||||
static_cast<unsigned long long>(WholeAirBoxesByLevel[Level]),
|
||||
static_cast<unsigned long long>(WholeMixedBoxesByLevel[Level]),
|
||||
static_cast<unsigned long long>(WholeUnknownBoxesByLevel[Level]),
|
||||
static_cast<unsigned long long>(WholeTileSkipsByLevel[Level]),
|
||||
static_cast<unsigned long long>(WholeFieldCallsByLevel[Level]),
|
||||
static_cast<unsigned long long>(WholeFloatFieldCallsByLevel[Level]),
|
||||
static_cast<unsigned long long>(WholeLatticeFieldCallsByLevel[Level]),
|
||||
static_cast<unsigned long long>(WholeUnclampedFieldCallsByLevel[Level]),
|
||||
static_cast<unsigned long long>(WholeColumnHitsByLevel[Level]),
|
||||
static_cast<unsigned long long>(WholeColumnMissesByLevel[Level]),
|
||||
WholeColumnComputeMillisecondsByLevel[Level],
|
||||
WholeClassificationMillisecondsByLevel[Level],
|
||||
WholeMeshingMillisecondsByLevel[Level]);
|
||||
std::printf("[StreamCacheUse] hits=%llu requested=%d\n",
|
||||
static_cast<unsigned long long>(Streamer.GetCacheHits()),DesiredTotal);
|
||||
if(bShardAudit)
|
||||
@@ -7883,16 +8031,39 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
{
|
||||
VoxelForgeCore::WorldAssemblyFeatureV1 shelf;
|
||||
shelf.stableId=WorldAssemblyFeatureId(recipe.seed,cliffX,cliffY,0x4f564552u);
|
||||
shelf.type=2;
|
||||
const int reach=72,width=36;
|
||||
const int minX=xAxis?cliffX+(downhill<0?-reach:0)-4:cliffX-width;
|
||||
const int maxX=xAxis?cliffX+(downhill>0?reach:0)+4:cliffX+width;
|
||||
const int minY=xAxis?cliffY-width:cliffY+(downhill<0?-reach:0)-4;
|
||||
const int maxY=xAxis?cliffY+width:cliffY+(downhill>0?reach:0)+4;
|
||||
shelf.type=4;
|
||||
constexpr int reach=72,width=36,height=64,feather=8;
|
||||
const int dirX=xAxis?downhill:0,dirY=xAxis?0:downhill;
|
||||
const int minX=xAxis?(dirX>0?cliffX-feather:cliffX-reach-feather)
|
||||
:cliffX-width-feather;
|
||||
const int maxX=xAxis?(dirX>0?cliffX+reach+feather:cliffX+feather)
|
||||
:cliffX+width+feather;
|
||||
const int minY=xAxis?cliffY-width-feather
|
||||
:(dirY>0?cliffY-feather:cliffY-reach-feather);
|
||||
const int maxY=xAxis?cliffY+width+feather
|
||||
:(dirY>0?cliffY+reach+feather:cliffY+feather);
|
||||
VoxelForgeCore::Heightfield2D baseField(recipe,stratum);
|
||||
double lowestGround=std::numeric_limits<double>::infinity();
|
||||
double highestGround=-std::numeric_limits<double>::infinity();
|
||||
for(int sampleY=minY;sampleY<=maxY;sampleY+=4)
|
||||
for(int sampleX=minX;sampleX<=maxX;sampleX+=4)
|
||||
{
|
||||
const auto sample=baseField.point(WorldAssemblyFixed(sampleX),
|
||||
WorldAssemblyFixed(sampleY),0);
|
||||
const double heightQ=static_cast<double>(sample.groundHeightSubvoxels)
|
||||
/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
lowestGround=std::min(lowestGround,heightQ);
|
||||
highestGround=std::max(highestGround,heightQ);
|
||||
}
|
||||
if(!std::isfinite(lowestGround)||!std::isfinite(highestGround))
|
||||
{error="world assembler cliff shelf could not bound its terrain columns";return false;}
|
||||
shelf.minimumSubvoxels={WorldAssemblyFixed(minX),WorldAssemblyFixed(minY),
|
||||
WorldAssemblyFixed(std::max<double>(bottomVoxel,ground-12.0))};
|
||||
WorldAssemblyFixed(std::max<double>(bottomVoxel,lowestGround-4.0))};
|
||||
shelf.maximumSubvoxels={WorldAssemblyFixed(maxX),WorldAssemblyFixed(maxY),
|
||||
WorldAssemblyFixed(std::min<double>((topChunkZ+1)*CHUNK_SIZE,ground+5.0))};
|
||||
WorldAssemblyFixed(std::min<double>((topChunkZ+1)*CHUNK_SIZE,
|
||||
highestGround+height+4.0))};
|
||||
shelf.parametersSubvoxels={WorldAssemblyFixed(dirX),WorldAssemblyFixed(dirY),
|
||||
WorldAssemblyFixed(height),WorldAssemblyFixed(reach)};
|
||||
stratum.features.push_back(shelf);
|
||||
}
|
||||
}
|
||||
@@ -7963,6 +8134,101 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
static_cast<unsigned long long>(bounds.exceptionPointSamples),
|
||||
bounds.negativeControlDetected?"true":"false",bounds.passed?"PASS":"FAIL");
|
||||
|
||||
bool cliffRegressionPassing=false;
|
||||
const auto cliffIt=std::find_if(plan.features.begin(),plan.features.end(),
|
||||
[](const auto& feature){return feature.type==4;});
|
||||
if(cliffIt!=plan.features.end())
|
||||
{
|
||||
const std::size_t cliffIndex=static_cast<std::size_t>(cliffIt-plan.features.begin());
|
||||
auto basePlan=plan;basePlan.features.erase(basePlan.features.begin()+cliffIndex);
|
||||
auto boxControlPlan=plan;boxControlPlan.features[cliffIndex].type=2;
|
||||
const VoxelForgeCore::Heightfield2D baseBlock(manifest->recipe,basePlan);
|
||||
const VoxelForgeCore::Heightfield2D boxControlBlock(manifest->recipe,boxControlPlan);
|
||||
const auto& feature=*cliffIt;
|
||||
const std::int64_t cx=(feature.minimumSubvoxels[0]+feature.maximumSubvoxels[0])/2;
|
||||
const std::int64_t cy=(feature.minimumSubvoxels[1]+feature.maximumSubvoxels[1])/2;
|
||||
const std::int64_t z=feature.maximumSubvoxels[2]
|
||||
-VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
std::uint64_t airSamples=0,controlSlabSamples=0,taperedTopSamples=0;
|
||||
for(int gy=-2;gy<=2;++gy)
|
||||
for(int gx=-2;gx<=2;++gx)
|
||||
{
|
||||
const std::int64_t x=cx+gx*8*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
const std::int64_t y=cy+gy*8*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
const auto base=baseBlock.point(x,y,z);
|
||||
const auto control=boxControlBlock.point(x,y,z);
|
||||
const auto tapered=block.point(x,y,z);
|
||||
if(base.densitySubvoxels>0)
|
||||
{
|
||||
++airSamples;
|
||||
if(control.densitySubvoxels<0)++controlSlabSamples;
|
||||
if(tapered.densitySubvoxels<0)++taperedTopSamples;
|
||||
}
|
||||
}
|
||||
const bool negativeControl=airSamples>=8&&controlSlabSamples==airSamples;
|
||||
cliffRegressionPassing=negativeControl&&taperedTopSamples*2<airSamples;
|
||||
std::printf("[WorldAssemblerCliffShapeAudit] top_plane_q=%lld baseline_air_samples=%llu old_type2_blocked=%llu tapered_type4_blocked=%llu negative_control_detected=%s status=%s\n",
|
||||
static_cast<long long>(z),static_cast<unsigned long long>(airSamples),
|
||||
static_cast<unsigned long long>(controlSlabSamples),
|
||||
static_cast<unsigned long long>(taperedTopSamples),
|
||||
negativeControl?"true":"false",cliffRegressionPassing?"PASS":"FAIL");
|
||||
}
|
||||
else std::printf("[WorldAssemblerCliffShapeAudit] type4_shelf=missing status=FAIL\n");
|
||||
|
||||
std::uint64_t seamBoxes=0,seamLatticeSamples=0,seamClassificationFailures=0;
|
||||
for(int boundaryY=-64;boundaryY<=64;boundaryY+=32)
|
||||
for(int boundaryX=-64;boundaryX<=64;boundaryX+=32)
|
||||
{
|
||||
const std::int64_t minX=static_cast<std::int64_t>(boundaryX-8)
|
||||
*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
const std::int64_t maxX=static_cast<std::int64_t>(boundaryX+8)
|
||||
*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
const std::int64_t minY=static_cast<std::int64_t>(boundaryY-8)
|
||||
*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
const std::int64_t maxY=static_cast<std::int64_t>(boundaryY+8)
|
||||
*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
std::int64_t groundMin=std::numeric_limits<std::int64_t>::max();
|
||||
std::int64_t groundMax=std::numeric_limits<std::int64_t>::min();
|
||||
std::int64_t capMin=std::numeric_limits<std::int64_t>::max();
|
||||
for(std::int64_t y=minY;y<=maxY;y+=8*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel)
|
||||
for(std::int64_t x=minX;x<=maxX;x+=8*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel)
|
||||
{
|
||||
const auto column=block.point(x,y,0);
|
||||
groundMin=std::min(groundMin,column.groundHeightSubvoxels);
|
||||
groundMax=std::max(groundMax,column.groundHeightSubvoxels);
|
||||
capMin=std::min(capMin,column.capHeightSubvoxels);
|
||||
}
|
||||
for(const bool bAir:{true,false})
|
||||
{
|
||||
const std::int64_t minZ=bAir?groundMax+16*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel
|
||||
:groundMin-24*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
const std::int64_t maxZ=bAir?minZ+8*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel
|
||||
:minZ+8*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
if(bAir&&maxZ>=capMin)continue;
|
||||
const auto verdict=block.classifyLatticeBox(minX,minY,minZ,maxX,maxY,maxZ,8);
|
||||
const auto expected=bAir?VoxelForgeCore::HeightfieldBoxClass::allAir
|
||||
:VoxelForgeCore::HeightfieldBoxClass::allSolid;
|
||||
++seamBoxes;
|
||||
if(verdict!=expected){++seamClassificationFailures;continue;}
|
||||
for(std::int64_t zq=minZ;zq<=maxZ;zq+=8*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel)
|
||||
for(std::int64_t y=minY;y<=maxY;y+=8*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel)
|
||||
for(std::int64_t x=minX;x<=maxX;x+=8*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel)
|
||||
{
|
||||
const auto sample=block.point(x,y,zq);
|
||||
if((bAir&&sample.densitySubvoxels<=0)||(!bAir&&sample.densitySubvoxels>=0))
|
||||
++seamClassificationFailures;
|
||||
++seamLatticeSamples;
|
||||
}
|
||||
}
|
||||
}
|
||||
const bool seamClassificationPassing=seamBoxes>0&&seamClassificationFailures==0
|
||||
&&seamLatticeSamples>0;
|
||||
std::printf("[WorldAssemblerTileSeamAudit] boxes=%llu lattice_samples=%llu false_classifications=%llu seam_spacing_vox=32 box_span_vox=16 status=%s\n",
|
||||
static_cast<unsigned long long>(seamBoxes),
|
||||
static_cast<unsigned long long>(seamLatticeSamples),
|
||||
static_cast<unsigned long long>(seamClassificationFailures),
|
||||
seamClassificationPassing?"PASS":"FAIL");
|
||||
|
||||
struct Query {std::int64_t x=0,y=0,z=0;};
|
||||
constexpr int side=64;
|
||||
std::vector<Query> queries;
|
||||
@@ -8148,7 +8414,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel,0.0,true});
|
||||
printCaptureSite("biome_border",borderSite);
|
||||
printCaptureSite("coast",coastSite);
|
||||
if(!plan.features.empty()&&plan.features.front().type==2)
|
||||
if(!plan.features.empty()&&(plan.features.front().type==2||plan.features.front().type==4))
|
||||
{
|
||||
const auto& feature=plan.features.front();
|
||||
const double fx=(feature.minimumSubvoxels[0]+feature.maximumSubvoxels[0])
|
||||
@@ -8316,7 +8582,8 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
ownerSaved&&nativeSaved?"PASS":"FAIL");
|
||||
}
|
||||
std::printf("[WorldAssemblerFullViewTiming] status=NOT_MEASURED_IN_AUDIT_MODE; capture_viewer_runs_report_separately\n");
|
||||
return bounds.passed&&deterministic&&coreQueryPass?0:11;
|
||||
return bounds.passed&&cliffRegressionPassing&&seamClassificationPassing
|
||||
&&deterministic&&coreQueryPass?0:11;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8683,10 +8950,18 @@ int main(int Argc,char** Argv)
|
||||
std::printf("Standalone max clip level override: exported=%d -> max_level=%d.\n",
|
||||
ExportMaxClipLevel,MaxClipLevelOverride);
|
||||
}
|
||||
if(App.bWorldAssemblerPrototype
|
||||
&&!AttachRound1WorldAssemblyPrototype(*App.World,App.OwnerJsonRoot,Error,
|
||||
WorldAssemblyManifestOutputPath))
|
||||
{std::fprintf(stderr,"World assembler prototype setup failed: %s\n",Error.c_str());return 2;}
|
||||
if(App.bWorldAssemblerPrototype)
|
||||
{
|
||||
const auto PlanStart=std::chrono::steady_clock::now();
|
||||
const bool bPlanReady=AttachRound1WorldAssemblyPrototype(*App.World,App.OwnerJsonRoot,
|
||||
Error,WorldAssemblyManifestOutputPath);
|
||||
const double PlanMilliseconds=std::chrono::duration<double,std::milli>(
|
||||
std::chrono::steady_clock::now()-PlanStart).count();
|
||||
std::printf("[WorldAssemblerPlanTiming] total_ms=%.3f status=%s\n",
|
||||
PlanMilliseconds,bPlanReady?"PASS":"FAIL");
|
||||
if(!bPlanReady)
|
||||
{std::fprintf(stderr,"World assembler prototype setup failed: %s\n",Error.c_str());return 2;}
|
||||
}
|
||||
if(App.bWorldAssemblerAuditOnly)
|
||||
{
|
||||
App.Snapshot=VoxelForgeCore::MakeStandaloneSnapshotFromParsedJson(App.OwnerJsonRoot,
|
||||
|
||||
@@ -57,6 +57,7 @@ struct FStandaloneCpuTile
|
||||
uint64 TopologyHash=14695981039346656037ull;
|
||||
bool bHasTopologyHash=false;
|
||||
uint64 MeshPayloadAllocatedBytes=0;
|
||||
VoxelForgeCore::TileGenerationStats CoreDiagnostics{};
|
||||
std::array<uint64,VoxelDensityProfile::BucketCount> ProfileCycles{};
|
||||
|
||||
};
|
||||
@@ -417,7 +418,7 @@ public:
|
||||
bool bInSkipUV=false,
|
||||
bool bInSkipColors=false,
|
||||
VoxelForgeCore::World* InCoreWorld=nullptr)
|
||||
:World(&InWorld),WorkerCount(FMath::Clamp(InWorkerCount,1,8)),bHashDensity(bInHashDensity),
|
||||
:World(&InWorld),WorkerCount(FMath::Clamp(InWorkerCount,1,16)),bHashDensity(bInHashDensity),
|
||||
MeshCache(InMeshCache),MaxLevelFilter(InMaxLevelFilter),
|
||||
CoreWorld(InCoreWorld),bSkipUvAndColors(bInSkipUvAndColors),bSkipMaterialGroups(bInSkipMaterialGroups),
|
||||
bSkipUV(bInSkipUV),bSkipColors(bInSkipColors)
|
||||
@@ -736,6 +737,7 @@ private:
|
||||
Out.CompletedAt=FClock::now();return Out;
|
||||
}
|
||||
Out.DensitySamples=Result->densitySampleCount;
|
||||
Out.CoreDiagnostics=Result->diagnostics;
|
||||
Out.SurfaceVertexCount=Result->groups.surfaceVertexCount;
|
||||
Out.SkirtTriangleCount=Result->groups.skirtTriangleCount;
|
||||
Out.MeshPayloadAllocatedBytes=Result->meshPayloadAllocatedBytes;
|
||||
|
||||
Reference in new issue
Block a user