diag: passage source-floor clamp rejected (L91); field has steep non-distance tails
Clamping the passage-composition source density at -c (c=2..6 voxels, diagnostic, default off) changes the surface far beyond the bar: c=6 still 65 sign flips, up to 165 cm displacement, 120 deg normal change (downstream composition consumes deep values). Source gradient at crossings is distance-like at the median but has huge tails (FI p90 |grad| 512, max 894 vox/vox), so the density-dependent passage reach is inflated by non-distance values. No world change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
a7a03d42b4
commit
8805291d3e
9 files changed
+937
-11
No files matched your search
@@ -59,6 +59,7 @@ namespace
|
||||
int ShapeHelperLimit=8;
|
||||
bool AuditBasePageEquivalence=false;
|
||||
bool AuditRouteParity=false;
|
||||
bool AuditPassageSourceClamp=false;
|
||||
bool RegionCrossing=false;
|
||||
bool AuditTileShapeReadiness=false;
|
||||
int DiagnosticSlowShapeCompileMs=0;
|
||||
@@ -1460,6 +1461,7 @@ namespace
|
||||
" --shape-helper-limit=8|12 (default 8; shape build A/B)\n"
|
||||
" --audit-base-page-equivalence (hash one tile through both shape routes)\n"
|
||||
" --audit-route-parity (compare page, native-only, exact-query and mesh routes)\n"
|
||||
" --audit-passage-source-clamp (compare passage source floors 2,3,4,6 over all near tiles)\n"
|
||||
" --audit-tile-shape-readiness (run a deliberately mis-marked tile against the native-only guard)\n"
|
||||
" --diagnostic-slow-shape-compile-ms=N (diagnostic overlap control; default 0)\n"
|
||||
" --render-distance-chunks=N (0 disables the extra far ring)\n"
|
||||
@@ -1536,6 +1538,7 @@ namespace
|
||||
}
|
||||
else if(arg=="--audit-base-page-equivalence")options.AuditBasePageEquivalence=true;
|
||||
else if(arg=="--audit-route-parity")options.AuditRouteParity=true;
|
||||
else if(arg=="--audit-passage-source-clamp")options.AuditPassageSourceClamp=true;
|
||||
else if(arg=="--region-crossing")options.RegionCrossing=true;
|
||||
else if(arg=="--audit-tile-shape-readiness")options.AuditTileShapeReadiness=true;
|
||||
else if(arg=="--auto-surface-camera")options.AutoSurfaceCamera=true;
|
||||
@@ -2276,5 +2279,6 @@ int main(int argc,char** argv)
|
||||
options.StreamHashAllowUniformSkips,options.Linux77Profile,
|
||||
options.StreamingSchedulerPolicy,options.MovingCameraTrace,
|
||||
options.MovingCameraSpeedMetersPerSecond,options.MovingCameraDurationSeconds,
|
||||
options.MovingCameraDwellSeconds,options.ColdWorkerTimeline);
|
||||
options.MovingCameraDwellSeconds,options.ColdWorkerTimeline,
|
||||
options.AuditPassageSourceClamp);
|
||||
}
|
||||
@@ -132,6 +132,426 @@ namespace StandaloneStreamBenchmark
|
||||
return Result;
|
||||
}
|
||||
|
||||
struct FPassageClampComparison
|
||||
{
|
||||
std::uint64_t samples=0,changedSamples=0,signFlips=0;
|
||||
std::uint64_t crossingEdgeMismatches=0,sharedCrossingEdges=0,movedCrossingEdges=0;
|
||||
std::uint64_t normalVertices=0,normalPairingFailures=0,changedNormalVertices=0;
|
||||
double maxAbsDensityDelta=0.0,maxSurfaceDisplacementCm=0.0;
|
||||
double sumSurfaceDisplacementCm=0.0,maxNormalAngleDegrees=0.0;
|
||||
double sumNormalAngleDegrees=0.0;
|
||||
std::array<std::uint64_t,4> movedEdgeRegions{},normalVertexRegions{};
|
||||
bool meshChanged=false,valid=false;
|
||||
};
|
||||
|
||||
struct FPassageRegion
|
||||
{
|
||||
int category=3; // 0 wall, 1 floor, 2 mouth, 3 outside the passage envelope
|
||||
double signedWallDistanceVoxels=std::numeric_limits<double>::infinity();
|
||||
};
|
||||
|
||||
inline FPassageRegion ClassifyPassageRegion(
|
||||
const VoxelForgeCore::ResolvedLayoutSnapshotV3* Layout,
|
||||
const std::array<double,3>& PositionVoxels)
|
||||
{
|
||||
FPassageRegion best;
|
||||
if(!Layout)return best;
|
||||
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
||||
double bestAbsoluteWallDistance=std::numeric_limits<double>::infinity();
|
||||
for(const auto& passage:Layout->passages)
|
||||
{
|
||||
if(passage.controlPoints.size()<2)continue;
|
||||
for(std::size_t index=0;index+1<passage.controlPoints.size();++index)
|
||||
{
|
||||
const auto& a=passage.controlPoints[index];
|
||||
const auto& b=passage.controlPoints[index+1];
|
||||
std::array<double,3> delta{},fromA{};
|
||||
double lengthSquared=0.0,dot=0.0;
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
delta[axis]=(static_cast<double>(b.positionSubvoxels[axis])
|
||||
-a.positionSubvoxels[axis])/Q;
|
||||
fromA[axis]=PositionVoxels[axis]
|
||||
-static_cast<double>(a.positionSubvoxels[axis])/Q;
|
||||
lengthSquared+=delta[axis]*delta[axis];
|
||||
dot+=fromA[axis]*delta[axis];
|
||||
}
|
||||
const double t=lengthSquared>0.0
|
||||
?std::clamp(dot/lengthSquared,0.0,1.0):0.0;
|
||||
double distanceSquared=0.0;
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
const double difference=fromA[axis]-t*delta[axis];
|
||||
distanceSquared+=difference*difference;
|
||||
}
|
||||
const double radius=(static_cast<double>(a.radiusSubvoxels)+t*(
|
||||
static_cast<double>(b.radiusSubvoxels)-a.radiusSubvoxels))/Q;
|
||||
const double signedWallDistance=std::sqrt(distanceSquared)-radius;
|
||||
if(std::abs(signedWallDistance)>=bestAbsoluteWallDistance)continue;
|
||||
bestAbsoluteWallDistance=std::abs(signedWallDistance);
|
||||
best.signedWallDistanceVoxels=signedWallDistance;
|
||||
const bool endpointSegment=index<8
|
||||
||index+9>=passage.controlPoints.size();
|
||||
if(endpointSegment)
|
||||
best.category=2;
|
||||
else
|
||||
{
|
||||
const double vertical=fromA[2]-t*delta[2];
|
||||
best.category=radius>0.0&&vertical<-0.55*radius?1:0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(best.signedWallDistanceVoxels>48.0)best.category=3;
|
||||
return best;
|
||||
}
|
||||
|
||||
inline FPassageClampComparison ComparePassageClampMeshes(
|
||||
const VoxelForgeCore::TileMesh& Base,const VoxelForgeCore::TileMesh& Candidate,
|
||||
const VoxelForgeCore::ResolvedLayoutSnapshotV3* Layout,
|
||||
std::uint32_t CoreVoxelSizeMicrons)
|
||||
{
|
||||
FPassageClampComparison result;
|
||||
if(Base.debugDensitySamples.empty()
|
||||
||Base.debugDensitySamples.size()!=Candidate.debugDensitySamples.size())return result;
|
||||
const double root=std::cbrt(static_cast<double>(Base.debugDensitySamples.size()));
|
||||
const std::int32_t dim=static_cast<std::int32_t>(std::llround(root));
|
||||
if(dim<4||static_cast<std::size_t>(dim)*dim*dim!=Base.debugDensitySamples.size())return result;
|
||||
const std::int32_t gridDim=dim-3;
|
||||
const std::int32_t extent=VoxelForgeCore::CoreTileVoxelCount<<Base.key.lod;
|
||||
if(gridDim<=0||extent%gridDim!=0)return result;
|
||||
const std::int32_t step=extent/gridDim;
|
||||
const double voxelSizeCm=static_cast<double>(CoreVoxelSizeMicrons)/10000.0;
|
||||
const std::array<std::int32_t,3> origin={Base.key.coordinate.x*extent,
|
||||
Base.key.coordinate.y*extent,Base.key.coordinate.z*extent};
|
||||
const auto index=[dim](std::int32_t x,std::int32_t y,std::int32_t z)
|
||||
{return (static_cast<std::size_t>(z)*dim+y)*dim+x;};
|
||||
const auto solid=[](float density){return density<0.0f;};
|
||||
for(std::int32_t z=0;z<dim;++z)
|
||||
for(std::int32_t y=0;y<dim;++y)
|
||||
for(std::int32_t x=0;x<dim;++x)
|
||||
{
|
||||
const float a=Base.debugDensitySamples[index(x,y,z)];
|
||||
const float b=Candidate.debugDensitySamples[index(x,y,z)];
|
||||
if(!std::isfinite(a)||!std::isfinite(b))return result;
|
||||
if(a!=b)++result.changedSamples;
|
||||
if(solid(a)!=solid(b))++result.signFlips;
|
||||
result.maxAbsDensityDelta=std::max(result.maxAbsDensityDelta,
|
||||
std::abs(static_cast<double>(a)-b));
|
||||
++result.samples;
|
||||
}
|
||||
const auto inspectEdge=[&](std::int32_t x,std::int32_t y,std::int32_t z,
|
||||
std::int32_t nx,std::int32_t ny,std::int32_t nz)
|
||||
{
|
||||
const float a0=Base.debugDensitySamples[index(x,y,z)];
|
||||
const float a1=Base.debugDensitySamples[index(nx,ny,nz)];
|
||||
const float b0=Candidate.debugDensitySamples[index(x,y,z)];
|
||||
const float b1=Candidate.debugDensitySamples[index(nx,ny,nz)];
|
||||
const bool crossBase=solid(a0)!=solid(a1);
|
||||
const bool crossCandidate=solid(b0)!=solid(b1);
|
||||
if(crossBase!=crossCandidate)++result.crossingEdgeMismatches;
|
||||
if(!crossBase||!crossCandidate)return;
|
||||
const double ta=static_cast<double>(a0)/(static_cast<double>(a0)-a1);
|
||||
const double tb=static_cast<double>(b0)/(static_cast<double>(b0)-b1);
|
||||
const double displacementCm=std::abs(ta-tb)*step*voxelSizeCm;
|
||||
result.maxSurfaceDisplacementCm=std::max(result.maxSurfaceDisplacementCm,
|
||||
displacementCm);
|
||||
result.sumSurfaceDisplacementCm+=displacementCm;
|
||||
++result.sharedCrossingEdges;
|
||||
if(displacementCm<=1.0e-9)return;
|
||||
++result.movedCrossingEdges;
|
||||
std::array<double,3> location={origin[0]+(x-1)*step,
|
||||
origin[1]+(y-1)*step,origin[2]+(z-1)*step};
|
||||
location[0]+=(nx-x)*step*(ta+tb)*0.5;
|
||||
location[1]+=(ny-y)*step*(ta+tb)*0.5;
|
||||
location[2]+=(nz-z)*step*(ta+tb)*0.5;
|
||||
const int region=ClassifyPassageRegion(Layout,location).category;
|
||||
++result.movedEdgeRegions[static_cast<std::size_t>(region)];
|
||||
};
|
||||
for(std::int32_t z=0;z<dim;++z)
|
||||
for(std::int32_t y=0;y<dim;++y)
|
||||
for(std::int32_t x=0;x<dim;++x)
|
||||
{
|
||||
if(x+1<dim)inspectEdge(x,y,z,x+1,y,z);
|
||||
if(y+1<dim)inspectEdge(x,y,z,x,y+1,z);
|
||||
if(z+1<dim)inspectEdge(x,y,z,x,y,z+1);
|
||||
}
|
||||
|
||||
if(Base.vertices.size()!=Candidate.vertices.size()
|
||||
||Base.indices!=Candidate.indices)
|
||||
result.normalPairingFailures=1;
|
||||
else
|
||||
{
|
||||
constexpr double RadiansToDegrees=180.0/3.14159265358979323846;
|
||||
for(std::size_t vertex=0;vertex<Base.vertices.size();++vertex)
|
||||
{
|
||||
const auto& a=Base.vertices[vertex].normal;
|
||||
const auto& b=Candidate.vertices[vertex].normal;
|
||||
const double lengthA=std::sqrt(a.x*a.x+a.y*a.y+a.z*a.z);
|
||||
const double lengthB=std::sqrt(b.x*b.x+b.y*b.y+b.z*b.z);
|
||||
if(!(lengthA>0.0&&lengthB>0.0))continue;
|
||||
const double cosine=std::clamp((a.x*b.x+a.y*b.y+a.z*b.z)
|
||||
/(lengthA*lengthB),-1.0,1.0);
|
||||
const double angle=std::acos(cosine)*RadiansToDegrees;
|
||||
result.maxNormalAngleDegrees=std::max(result.maxNormalAngleDegrees,angle);
|
||||
result.sumNormalAngleDegrees+=angle;
|
||||
++result.normalVertices;
|
||||
if(angle>1.0e-6)
|
||||
{
|
||||
++result.changedNormalVertices;
|
||||
const double geometryVoxelSizeCm=voxelSizeCm;
|
||||
const auto& position=Candidate.vertices[vertex].position;
|
||||
const std::array<double,3> location={position.x/geometryVoxelSizeCm,
|
||||
position.y/geometryVoxelSizeCm,position.z/geometryVoxelSizeCm};
|
||||
const int region=ClassifyPassageRegion(Layout,location).category;
|
||||
++result.normalVertexRegions[static_cast<std::size_t>(region)];
|
||||
}
|
||||
}
|
||||
}
|
||||
result.meshChanged=Base.meshHash!=Candidate.meshHash
|
||||
||Base.vertices.size()!=Candidate.vertices.size()
|
||||
||Base.indices!=Candidate.indices;
|
||||
result.valid=true;
|
||||
return result;
|
||||
}
|
||||
|
||||
struct FPassageSourceGradientStats
|
||||
{
|
||||
std::uint64_t candidateCrossings=0,sourceNearZeroSamples=0;
|
||||
std::vector<double> gradientMagnitudes;
|
||||
};
|
||||
|
||||
inline void GatherPassageSourceGradients(const VoxelForgeCore::World& World,
|
||||
const VoxelForgeCore::TileMesh& Mesh,
|
||||
const VoxelForgeCore::ResolvedLayoutSnapshotV3* Layout,
|
||||
FPassageSourceGradientStats& Stats)
|
||||
{
|
||||
if(Mesh.debugDensitySamples.empty())return;
|
||||
const double root=std::cbrt(static_cast<double>(Mesh.debugDensitySamples.size()));
|
||||
const std::int32_t dim=static_cast<std::int32_t>(std::llround(root));
|
||||
if(dim<4||static_cast<std::size_t>(dim)*dim*dim!=Mesh.debugDensitySamples.size())return;
|
||||
const std::int32_t gridDim=dim-3;
|
||||
const std::int32_t extent=VoxelForgeCore::CoreTileVoxelCount<<Mesh.key.lod;
|
||||
if(gridDim<=0||extent%gridDim!=0)return;
|
||||
const std::int32_t step=extent/gridDim;
|
||||
const std::array<std::int32_t,3> origin={Mesh.key.coordinate.x*extent,
|
||||
Mesh.key.coordinate.y*extent,Mesh.key.coordinate.z*extent};
|
||||
const auto index=[dim](std::int32_t x,std::int32_t y,std::int32_t z)
|
||||
{return (static_cast<std::size_t>(z)*dim+y)*dim+x;};
|
||||
std::uint64_t eligibleCrossings=0;
|
||||
constexpr std::uint64_t SampleStride=32;
|
||||
constexpr double H=1.0;
|
||||
const auto inspect=[&](std::int32_t x,std::int32_t y,std::int32_t z,
|
||||
std::int32_t nx,std::int32_t ny,std::int32_t nz)
|
||||
{
|
||||
const float d0=Mesh.debugDensitySamples[index(x,y,z)];
|
||||
const float d1=Mesh.debugDensitySamples[index(nx,ny,nz)];
|
||||
if((d0<0.0f)==(d1<0.0f))return;
|
||||
const double t=static_cast<double>(d0)/(static_cast<double>(d0)-d1);
|
||||
std::array<double,3> location={origin[0]+(x-1)*step,
|
||||
origin[1]+(y-1)*step,origin[2]+(z-1)*step};
|
||||
location[0]+=(nx-x)*step*t;
|
||||
location[1]+=(ny-y)*step*t;
|
||||
location[2]+=(nz-z)*step*t;
|
||||
if(ClassifyPassageRegion(Layout,location).category!=3)return;
|
||||
++Stats.candidateCrossings;
|
||||
if((eligibleCrossings++%SampleStride)!=0)return;
|
||||
const VoxelForgeCore::Vec3d point{location[0],location[1],location[2]};
|
||||
const double center=World.passageSourceDensityAt(point);
|
||||
if(!std::isfinite(center)||std::abs(center)>2.0)return;
|
||||
++Stats.sourceNearZeroSamples;
|
||||
std::array<double,3> gradient{};
|
||||
for(std::size_t axis=0;axis<3;++axis)
|
||||
{
|
||||
auto before=point,after=point;
|
||||
if(axis==0){before.x-=H;after.x+=H;}
|
||||
else if(axis==1){before.y-=H;after.y+=H;}
|
||||
else {before.z-=H;after.z+=H;}
|
||||
gradient[axis]=(World.passageSourceDensityAt(after)
|
||||
-World.passageSourceDensityAt(before))/(2.0*H);
|
||||
}
|
||||
const double magnitude=std::sqrt(gradient[0]*gradient[0]
|
||||
+gradient[1]*gradient[1]+gradient[2]*gradient[2]);
|
||||
if(std::isfinite(magnitude))Stats.gradientMagnitudes.push_back(magnitude);
|
||||
};
|
||||
for(std::int32_t z=0;z<dim;++z)
|
||||
for(std::int32_t y=0;y<dim;++y)
|
||||
for(std::int32_t x=0;x<dim;++x)
|
||||
{
|
||||
if(x+1<dim)inspect(x,y,z,x+1,y,z);
|
||||
if(y+1<dim)inspect(x,y,z,x,y+1,z);
|
||||
if(z+1<dim)inspect(x,y,z,x,y,z+1);
|
||||
}
|
||||
}
|
||||
|
||||
inline int AuditPassageSourceClamp(VoxelForgeCore::World& Shape,
|
||||
const FStandaloneDesiredTileSet& Desired,
|
||||
const VoxelForgeCore::ResolvedLayoutSnapshotV3* Layout,
|
||||
std::uint32_t CoreVoxelSizeMicrons)
|
||||
{
|
||||
constexpr std::array<double,4> Floors={2.0,3.0,4.0,6.0};
|
||||
std::vector<VoxelForgeCore::TileKey> keys;
|
||||
std::array<std::uint64_t,3> expectedByLod{};
|
||||
for(const FVoxelTileKey& tile:Desired.Tiles)
|
||||
{
|
||||
if(tile.Level<0||tile.Level>2)continue;
|
||||
keys.push_back({{tile.Coord.X,tile.Coord.Y,tile.Coord.Z},tile.Level});
|
||||
++expectedByLod[static_cast<std::size_t>(tile.Level)];
|
||||
}
|
||||
if(keys.empty())
|
||||
{
|
||||
std::printf("[L91PassageClampAudit] status=FAIL reason=no_lod0_2_tiles\n");
|
||||
return 14;
|
||||
}
|
||||
std::printf("[L91PassageClampCoverage] tiles=%zu lod0=%llu lod1=%llu lod2=%llu mode=full_desired_near_set\n",
|
||||
keys.size(),static_cast<unsigned long long>(expectedByLod[0]),
|
||||
static_cast<unsigned long long>(expectedByLod[1]),
|
||||
static_cast<unsigned long long>(expectedByLod[2]));
|
||||
VoxelForgeCore::TileGenerationOptions baseOptions;
|
||||
baseOptions.hashDensity=true;
|
||||
baseOptions.captureDensitySamples=true;
|
||||
baseOptions.forceFullDensityCapture=true;
|
||||
baseOptions.skipUvAndColors=true;
|
||||
baseOptions.skipMaterialGroups=true;
|
||||
VoxelForgeCore::TileGenerationOptions candidateOptions=baseOptions;
|
||||
candidateOptions.profilePassageComposer=true;
|
||||
std::array<std::uint64_t,4> tileCount{},sampleCount{},changedSamples{},signFlips{},
|
||||
crossingMismatches{},sharedCrossings{},movedCrossings{},changedTiles{},
|
||||
normalVertices{},normalPairingFailures{},changedNormalVertices{};
|
||||
std::array<std::uint64_t,4> movedRegions[4]{},normalRegions[4]{};
|
||||
std::array<double,4> maxDisplacementCm{},sumDisplacementCm{},maxNormalAngle{};
|
||||
std::array<double,4> sumNormalAngle{};
|
||||
FPassageSourceGradientStats gradientStats;
|
||||
std::uint64_t generationFailures=0,invalidComparisons=0;
|
||||
for(const VoxelForgeCore::TileKey& key:keys)
|
||||
{
|
||||
std::string error;
|
||||
const auto base=Shape.generateTile(key,baseOptions,error);
|
||||
if(!base)
|
||||
{
|
||||
++generationFailures;
|
||||
std::printf("[L91PassageClampTileFailure] mode=base key=(%d,%d,%d,lod%d) error=%s\n",
|
||||
key.coordinate.x,key.coordinate.y,key.coordinate.z,key.lod,error.c_str());
|
||||
continue;
|
||||
}
|
||||
GatherPassageSourceGradients(Shape,*base,Layout,gradientStats);
|
||||
for(std::size_t floorIndex=0;floorIndex<Floors.size();++floorIndex)
|
||||
{
|
||||
candidateOptions.diagnosticPassageSourceFloorVoxels=Floors[floorIndex];
|
||||
error.clear();
|
||||
const auto candidate=Shape.generateTile(key,candidateOptions,error);
|
||||
if(!candidate)
|
||||
{
|
||||
++generationFailures;
|
||||
std::printf("[L91PassageClampTileFailure] floor_vox=%.0f key=(%d,%d,%d,lod%d) error=%s\n",
|
||||
Floors[floorIndex],key.coordinate.x,key.coordinate.y,key.coordinate.z,
|
||||
key.lod,error.c_str());
|
||||
continue;
|
||||
}
|
||||
const FPassageClampComparison comparison=ComparePassageClampMeshes(
|
||||
*base,*candidate,Layout,CoreVoxelSizeMicrons);
|
||||
if(!comparison.valid)
|
||||
{
|
||||
++invalidComparisons;
|
||||
continue;
|
||||
}
|
||||
++tileCount[floorIndex];
|
||||
sampleCount[floorIndex]+=comparison.samples;
|
||||
changedSamples[floorIndex]+=comparison.changedSamples;
|
||||
signFlips[floorIndex]+=comparison.signFlips;
|
||||
crossingMismatches[floorIndex]+=comparison.crossingEdgeMismatches;
|
||||
sharedCrossings[floorIndex]+=comparison.sharedCrossingEdges;
|
||||
movedCrossings[floorIndex]+=comparison.movedCrossingEdges;
|
||||
changedTiles[floorIndex]+=comparison.meshChanged?1u:0u;
|
||||
normalVertices[floorIndex]+=comparison.normalVertices;
|
||||
normalPairingFailures[floorIndex]+=comparison.normalPairingFailures;
|
||||
changedNormalVertices[floorIndex]+=comparison.changedNormalVertices;
|
||||
maxDisplacementCm[floorIndex]=std::max(maxDisplacementCm[floorIndex],
|
||||
comparison.maxSurfaceDisplacementCm);
|
||||
sumDisplacementCm[floorIndex]+=comparison.sumSurfaceDisplacementCm;
|
||||
maxNormalAngle[floorIndex]=std::max(maxNormalAngle[floorIndex],
|
||||
comparison.maxNormalAngleDegrees);
|
||||
sumNormalAngle[floorIndex]+=comparison.sumNormalAngleDegrees;
|
||||
for(std::size_t region=0;region<4;++region)
|
||||
{
|
||||
movedRegions[floorIndex][region]+=comparison.movedEdgeRegions[region];
|
||||
normalRegions[floorIndex][region]+=comparison.normalVertexRegions[region];
|
||||
}
|
||||
std::printf("[L91PassageClampTile] floor_vox=%.0f key=(%d,%d,%d,lod%d) samples=%llu changed=%llu sign_flips=%llu moved_edges=%llu max_displacement_cm=%.6g normal_vertices=%llu max_normal_degrees=%.6g changed_mesh=%d\n",
|
||||
Floors[floorIndex],key.coordinate.x,key.coordinate.y,key.coordinate.z,key.lod,
|
||||
static_cast<unsigned long long>(comparison.samples),
|
||||
static_cast<unsigned long long>(comparison.changedSamples),
|
||||
static_cast<unsigned long long>(comparison.signFlips),
|
||||
static_cast<unsigned long long>(comparison.movedCrossingEdges),
|
||||
comparison.maxSurfaceDisplacementCm,
|
||||
static_cast<unsigned long long>(comparison.normalVertices),
|
||||
comparison.maxNormalAngleDegrees,comparison.meshChanged?1:0);
|
||||
}
|
||||
}
|
||||
bool acceptedAtAllFloors=generationFailures==0&&invalidComparisons==0
|
||||
&&keys.size()>0;
|
||||
for(std::size_t floorIndex=0;floorIndex<Floors.size();++floorIndex)
|
||||
{
|
||||
const double meanDisplacement=sharedCrossings[floorIndex]
|
||||
?sumDisplacementCm[floorIndex]/sharedCrossings[floorIndex]:0.0;
|
||||
const double meanNormal=normalVertices[floorIndex]
|
||||
?sumNormalAngle[floorIndex]/normalVertices[floorIndex]:0.0;
|
||||
const bool accepted=tileCount[floorIndex]==keys.size()
|
||||
&&signFlips[floorIndex]==0&&crossingMismatches[floorIndex]==0
|
||||
&&maxDisplacementCm[floorIndex]<=1.0
|
||||
&&maxNormalAngle[floorIndex]<=2.0
|
||||
&&normalPairingFailures[floorIndex]==0;
|
||||
acceptedAtAllFloors=acceptedAtAllFloors&&accepted;
|
||||
std::printf("[L91PassageClampSummary] floor_vox=%.0f tiles=%llu/%zu samples=%llu changed_samples=%llu sign_flips=%llu edge_crossing_mismatches=%llu shared_crossings=%llu moved_crossings=%llu max_displacement_cm=%.6g mean_displacement_cm=%.6g changed_mesh_tiles=%llu normal_vertices=%llu changed_normal_vertices=%llu max_normal_degrees=%.6g mean_normal_degrees=%.6g normal_pairing_failures=%llu moved_regions=(wall:%llu,floor:%llu,mouth:%llu,other:%llu) normal_regions=(wall:%llu,floor:%llu,mouth:%llu,other:%llu) status=%s\n",
|
||||
Floors[floorIndex],static_cast<unsigned long long>(tileCount[floorIndex]),
|
||||
keys.size(),static_cast<unsigned long long>(sampleCount[floorIndex]),
|
||||
static_cast<unsigned long long>(changedSamples[floorIndex]),
|
||||
static_cast<unsigned long long>(signFlips[floorIndex]),
|
||||
static_cast<unsigned long long>(crossingMismatches[floorIndex]),
|
||||
static_cast<unsigned long long>(sharedCrossings[floorIndex]),
|
||||
static_cast<unsigned long long>(movedCrossings[floorIndex]),
|
||||
maxDisplacementCm[floorIndex],meanDisplacement,
|
||||
static_cast<unsigned long long>(changedTiles[floorIndex]),
|
||||
static_cast<unsigned long long>(normalVertices[floorIndex]),
|
||||
static_cast<unsigned long long>(changedNormalVertices[floorIndex]),
|
||||
maxNormalAngle[floorIndex],meanNormal,
|
||||
static_cast<unsigned long long>(normalPairingFailures[floorIndex]),
|
||||
static_cast<unsigned long long>(movedRegions[floorIndex][0]),
|
||||
static_cast<unsigned long long>(movedRegions[floorIndex][1]),
|
||||
static_cast<unsigned long long>(movedRegions[floorIndex][2]),
|
||||
static_cast<unsigned long long>(movedRegions[floorIndex][3]),
|
||||
static_cast<unsigned long long>(normalRegions[floorIndex][0]),
|
||||
static_cast<unsigned long long>(normalRegions[floorIndex][1]),
|
||||
static_cast<unsigned long long>(normalRegions[floorIndex][2]),
|
||||
static_cast<unsigned long long>(normalRegions[floorIndex][3]),
|
||||
accepted?"PASS":"FAIL");
|
||||
}
|
||||
std::sort(gradientStats.gradientMagnitudes.begin(),
|
||||
gradientStats.gradientMagnitudes.end());
|
||||
const auto percentile=[](const std::vector<double>& values,double p)
|
||||
{
|
||||
if(values.empty())return 0.0;
|
||||
const std::size_t index=std::min(values.size()-1,
|
||||
static_cast<std::size_t>(std::ceil(p*values.size())-1));
|
||||
return values[index];
|
||||
};
|
||||
const double gradientMean=gradientStats.gradientMagnitudes.empty()?0.0:
|
||||
std::accumulate(gradientStats.gradientMagnitudes.begin(),
|
||||
gradientStats.gradientMagnitudes.end(),0.0)
|
||||
/gradientStats.gradientMagnitudes.size();
|
||||
std::printf("[L91PassageSourceGradient] surface_source_crossings=%llu sampled_near_zero=%llu gradient_samples=%zu step_vox=1 source_abs_limit_vox=2 p50=%.6g p90=%.6g max=%.6g mean=%.6g status=%s\n",
|
||||
static_cast<unsigned long long>(gradientStats.candidateCrossings),
|
||||
static_cast<unsigned long long>(gradientStats.sourceNearZeroSamples),
|
||||
gradientStats.gradientMagnitudes.size(),percentile(gradientStats.gradientMagnitudes,0.5),
|
||||
percentile(gradientStats.gradientMagnitudes,0.9),
|
||||
gradientStats.gradientMagnitudes.empty()?0.0:gradientStats.gradientMagnitudes.back(),
|
||||
gradientMean,gradientStats.gradientMagnitudes.size()>=64?"MEASURED":"LOW_SAMPLE");
|
||||
std::printf("[L91PassageClampAudit] tiles=%zu generation_failures=%llu invalid_comparisons=%llu status=%s\n",
|
||||
keys.size(),static_cast<unsigned long long>(generationFailures),
|
||||
static_cast<unsigned long long>(invalidComparisons),
|
||||
acceptedAtAllFloors?"PASS":"FAIL");
|
||||
return acceptedAtAllFloors?0:14;
|
||||
}
|
||||
|
||||
struct FLandmarkReachabilityResult
|
||||
{
|
||||
std::uint64_t pathSamples=0,capsuleSamples=0,blockedCapsuleSamples=0;
|
||||
@@ -1885,7 +2305,7 @@ namespace StandaloneStreamBenchmark
|
||||
bool bLinux77Profile=false,int32 SchedulerPolicy=-1,
|
||||
bool bMovingCameraTrace=false,double MovingCameraSpeedMetersPerSecond=0.0,
|
||||
double MovingCameraDurationSeconds=12.0,double MovingCameraDwellSeconds=5.0,
|
||||
bool bColdWorkerTimeline=false)
|
||||
bool bColdWorkerTimeline=false,bool bAuditPassageSourceClamp=false)
|
||||
{
|
||||
using Clock=std::chrono::steady_clock;
|
||||
const std::clock_t ColdCpuOrigin=std::clock();
|
||||
@@ -2054,7 +2474,8 @@ namespace StandaloneStreamBenchmark
|
||||
const bool bFarWorldAudit=bAuditNativeCaves||bAuditNativeLattice||bAuditMotifIntervals
|
||||
||bAuditOreVeinYield||bAuditLandmarkReachability||bAuditStrateTransitions
|
||||
||bAuditResolvedLayoutPassages||bAuditResolvedLayoutBoundaries
|
||||
||bAuditTileShapeReadiness||bAuditBasePageEquivalence||bAuditRouteParity;
|
||||
||bAuditTileShapeReadiness||bAuditBasePageEquivalence||bAuditRouteParity
|
||||
||bAuditPassageSourceClamp;
|
||||
const bool bDeferFarWorld=bIncludeFarWorld&&!bMovingCameraTrace&&!bFarWorldAudit;
|
||||
VoxelForgeCore::ShapeBuildRequest ShapeRequest;
|
||||
ShapeRequest.minVoxel={FineMin.X,FineMin.Y,FineMin.Z};
|
||||
@@ -2134,6 +2555,12 @@ namespace StandaloneStreamBenchmark
|
||||
Streamer.Stop();
|
||||
std::fprintf(stderr,"[StreamPipeline] full shape build failed: %s\n",BuildError.c_str());return 2;
|
||||
}
|
||||
if(bAuditPassageSourceClamp)
|
||||
{
|
||||
Streamer.Stop();
|
||||
return AuditPassageSourceClamp(Shape,Desired,ResolvedLayout,
|
||||
World.CoreVoxelSizeMicrons);
|
||||
}
|
||||
if(bAuditNativeCaves)
|
||||
{
|
||||
Streamer.Stop();
|
||||
|
||||
Reference in new issue
Block a user