wip(L26, side branch): every passage style walkable in both recipes (0/0/0); SW bridges look wrong
All 4 styles x both recipes pass capsule, open-air and naturalness audits, and full-view hashes are deterministic. But the SW passage crosses 355 m of open SurfaceWorld sky as a ~2 km fragmented rock ramp, which is not natural. L27 replaces long bridges with a shared ceiling-to-ground rock column. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
1 parent
ef789aaa00
commit
37a223046c
13 files changed
+878
-41
No files matched your search
@@ -458,15 +458,26 @@ namespace StandaloneStreamBenchmark
|
||||
bool hasDeepUnsupported=false;
|
||||
bool passed=false;
|
||||
};
|
||||
struct FPassageSegmentSupportAudit
|
||||
{
|
||||
std::uint64_t centers=0,unsupported=0,nativeUnsupported=0;
|
||||
std::array<double,3> firstUnsupported{};
|
||||
std::array<double,4> firstNativeDensities{};
|
||||
std::uint32_t firstNativeSupportedProbes=0;
|
||||
bool hasUnsupported=false;
|
||||
};
|
||||
const double coreMetres=static_cast<double>(World.CoreVoxelSizeMicrons)/1000000.0;
|
||||
const auto auditPlayerPath=[&](const VoxelForgeCore::World& Field,
|
||||
const std::vector<std::array<double,3>>& path,
|
||||
double supportStartMetres,double supportStepMetres,
|
||||
double supportMaximumMetres,std::uint32_t minimumSupportProbes,
|
||||
double supportProbeRadiusMetres)
|
||||
double supportProbeRadiusMetres,
|
||||
const VoxelForgeCore::World* nativeField=nullptr,
|
||||
std::vector<FPassageSegmentSupportAudit>* segmentSupport=nullptr)
|
||||
{
|
||||
FWalkAudit audit;
|
||||
if(path.size()<2)return audit;
|
||||
if(segmentSupport)segmentSupport->assign(path.size()-1,{});
|
||||
constexpr std::array<double,7> heights{{-0.84,-0.60,-0.30,0.0,0.30,0.60,0.84}};
|
||||
constexpr std::array<std::array<double,2>,8> directions{{
|
||||
{{1.0,0.0}},{{0.7071067811865475,0.7071067811865475}},{{0.0,1.0}},
|
||||
@@ -510,6 +521,9 @@ namespace StandaloneStreamBenchmark
|
||||
const double y=(a[1]+dy*t)*coreMetres;
|
||||
const double z=(a[2]+dz*t)*coreMetres;
|
||||
++audit.centers;
|
||||
FPassageSegmentSupportAudit* segmentAudit=segmentSupport
|
||||
?&(*segmentSupport)[segment-1]:nullptr;
|
||||
if(segmentAudit)++segmentAudit->centers;
|
||||
for(const double h:heights)
|
||||
{
|
||||
const double capOffset=std::max(0.0,std::abs(h)-0.54);
|
||||
@@ -526,6 +540,7 @@ namespace StandaloneStreamBenchmark
|
||||
{{0.0,supportProbeRadiusMetres}},
|
||||
{{0.0,-supportProbeRadiusMetres}}}};
|
||||
std::uint32_t supportedProbes=0;
|
||||
std::uint32_t nativeSupportedProbes=0;
|
||||
double firstUnsupportedX=x,firstUnsupportedY=y,lastUnsupportedDensity=0.0;
|
||||
std::array<bool,5> supportMask{};
|
||||
for(std::size_t offsetIndex=0;offsetIndex<supportOffsets.size();++offsetIndex)
|
||||
@@ -544,12 +559,41 @@ namespace StandaloneStreamBenchmark
|
||||
supported=true;break;
|
||||
}
|
||||
}
|
||||
if(nativeField)
|
||||
{
|
||||
for(double depth=supportStartMetres;
|
||||
depth<=supportMaximumMetres+1.0e-6;depth+=supportStepMetres)
|
||||
if(nativeField->densityAt({supportX/coreMetres,
|
||||
supportY/coreMetres,(footZ-depth)/coreMetres})<0.0f)
|
||||
{++nativeSupportedProbes;break;}
|
||||
}
|
||||
if(supported){++supportedProbes;supportMask[offsetIndex]=true;}
|
||||
else{firstUnsupportedX=supportX;firstUnsupportedY=supportY;}
|
||||
}
|
||||
if(nativeField&&segmentAudit
|
||||
&&nativeSupportedProbes<minimumSupportProbes)
|
||||
++segmentAudit->nativeUnsupported;
|
||||
if(supportedProbes<minimumSupportProbes)
|
||||
{
|
||||
++audit.unsupported;
|
||||
if(segmentAudit)
|
||||
{
|
||||
++segmentAudit->unsupported;
|
||||
if(!segmentAudit->hasUnsupported)
|
||||
{
|
||||
segmentAudit->hasUnsupported=true;
|
||||
segmentAudit->firstUnsupported={x,y,footZ};
|
||||
segmentAudit->firstNativeSupportedProbes=nativeSupportedProbes;
|
||||
if(nativeField)
|
||||
{
|
||||
constexpr std::array<double,4> depths{{0.125,1.0,2.0,4.0}};
|
||||
for(std::size_t depthIndex=0;depthIndex<depths.size();++depthIndex)
|
||||
segmentAudit->firstNativeDensities[depthIndex]=nativeField->densityAt({
|
||||
x/coreMetres,y/coreMetres,
|
||||
(footZ-depths[depthIndex])/coreMetres});
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!audit.hasDeepUnsupported&&footZ<-80.0)
|
||||
{
|
||||
audit.hasDeepUnsupported=true;
|
||||
@@ -682,7 +726,7 @@ namespace StandaloneStreamBenchmark
|
||||
}
|
||||
struct FPassageOpenAirAudit
|
||||
{
|
||||
std::uint64_t supportSamples=0,violations=0,legacyViolations=0;
|
||||
std::uint64_t supportSamples=0,violations=0,legacyViolations=0,bridgeSamples=0;
|
||||
std::uint64_t routeSupportSamples=0,routeSupportViolations=0;
|
||||
std::array<std::array<double,4>,8> firstViolations{};
|
||||
std::size_t firstViolationCount=0;
|
||||
@@ -708,11 +752,13 @@ namespace StandaloneStreamBenchmark
|
||||
{{0.9238795325112867,-0.3826834323650898}}}};
|
||||
const auto auditPassageOpenAir=[&](const VoxelForgeCore::World& Field,
|
||||
const VoxelForgeCore::World& Native,
|
||||
const VoxelForgeCore::ResolvedLayoutPassageV1& passage)
|
||||
const VoxelForgeCore::ResolvedLayoutPassageV1& passage,
|
||||
std::size_t passageIndex)
|
||||
{
|
||||
FPassageOpenAirAudit audit;
|
||||
const auto inspect=[&](double xMetres,double yMetres,double floorMetres,
|
||||
double depthMetres,double supportThicknessMetres,bool routeSupport=false)
|
||||
double depthMetres,double supportThicknessMetres,bool routeSupport=false,
|
||||
std::size_t passageSegment=std::numeric_limits<std::size_t>::max())
|
||||
{
|
||||
if(depthMetres<=0.0||depthMetres>supportThicknessMetres+1.0e-6)return;
|
||||
++audit.supportSamples;
|
||||
@@ -727,6 +773,10 @@ namespace StandaloneStreamBenchmark
|
||||
++audit.legacyViolations;
|
||||
if(nativeDensity>=0.0f&&passageDensity<0.0f)
|
||||
{
|
||||
const bool connectedBridge=!routeSupport
|
||||
&&passageSegment!=std::numeric_limits<std::size_t>::max()
|
||||
&&Field.isPassageBridgeSample(passageIndex,passageSegment,sample);
|
||||
if(connectedBridge){++audit.bridgeSamples;return;}
|
||||
audit.routeSupportViolations+=routeSupport;
|
||||
if(audit.firstViolationCount<audit.firstViolations.size())
|
||||
audit.firstViolations[audit.firstViolationCount++]={xMetres,yMetres,
|
||||
@@ -736,7 +786,8 @@ namespace StandaloneStreamBenchmark
|
||||
};
|
||||
const auto inspectFloorDisc=[&](double xMetres,double yMetres,double floorMetres,
|
||||
double supportRadiusMetres,double depthMetres,double supportThicknessMetres,
|
||||
bool routeSupport=false)
|
||||
bool routeSupport=false,
|
||||
std::size_t passageSegment=std::numeric_limits<std::size_t>::max())
|
||||
{
|
||||
const std::size_t radialSteps=static_cast<std::size_t>(std::ceil(
|
||||
supportRadiusMetres/PassageSupportAuditSpacingMetres));
|
||||
@@ -746,7 +797,8 @@ namespace StandaloneStreamBenchmark
|
||||
radialStep*PassageSupportAuditSpacingMetres);
|
||||
for(const auto& direction:PassageSupportAuditDirections)
|
||||
inspect(xMetres+direction[0]*radial,yMetres+direction[1]*radial,
|
||||
floorMetres,depthMetres,supportThicknessMetres,routeSupport);
|
||||
floorMetres,depthMetres,supportThicknessMetres,routeSupport,
|
||||
passageSegment);
|
||||
}
|
||||
};
|
||||
for(std::size_t segment=1;segment<passage.controlPoints.size();++segment)
|
||||
@@ -772,7 +824,8 @@ namespace StandaloneStreamBenchmark
|
||||
+(qToMetres(b.radiusSubvoxels)-qToMetres(a.radiusSubvoxels))*t;
|
||||
const double floorZ=centerZ-radius+0.20;
|
||||
for(const double depth:PassageSupportAuditDepthsMetres)
|
||||
inspectFloorDisc(centerX,centerY,floorZ,radius,depth,1.0);
|
||||
inspectFloorDisc(centerX,centerY,floorZ,radius,depth,1.0,
|
||||
false,segment-1);
|
||||
}
|
||||
}
|
||||
const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(),
|
||||
@@ -841,6 +894,124 @@ namespace StandaloneStreamBenchmark
|
||||
}
|
||||
return audit;
|
||||
};
|
||||
struct FPassageBridgeAudit
|
||||
{
|
||||
std::uint64_t spans=0,connectedEnds=0,crossSections=0,crossSectionFailures=0;
|
||||
double minimumThicknessMetres=std::numeric_limits<double>::infinity();
|
||||
double maximumThicknessMetres=0.0;
|
||||
double thicknessReliefPeakToPeakMetres=0.0;
|
||||
bool passed=true;
|
||||
};
|
||||
const auto auditPassageBridges=[&](const VoxelForgeCore::World& Field,
|
||||
const VoxelForgeCore::World& Native,
|
||||
const VoxelForgeCore::ResolvedLayoutPassageV1& passage,
|
||||
std::size_t passageIndex)
|
||||
{
|
||||
FPassageBridgeAudit audit;
|
||||
const double qMetres=coreMetres
|
||||
/VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
constexpr std::array<std::array<double,2>,5> supportOffsets{{
|
||||
{{0.0,0.0}},{{0.45,0.0}},{{-0.45,0.0}},{{0.0,0.45}},{{0.0,-0.45}}}};
|
||||
const auto endpointConnected=[&](const std::array<double,4>& point)
|
||||
{
|
||||
const double x=point[0]*qMetres,y=point[1]*qMetres;
|
||||
const double floor=point[2]*qMetres-point[3]*qMetres+0.13;
|
||||
std::uint32_t supported=0;
|
||||
for(const auto& offset:supportOffsets)
|
||||
{
|
||||
bool solid=false;
|
||||
for(const double depth:{0.125,0.25})
|
||||
if(Native.densityAt({(x+offset[0])/coreMetres,
|
||||
(y+offset[1])/coreMetres,(floor-depth)/coreMetres})<0.0f)
|
||||
{solid=true;break;}
|
||||
supported+=solid;
|
||||
}
|
||||
return supported>=3;
|
||||
};
|
||||
const auto bridgeSolidAt=[&](std::size_t segment,double x,double y,double z)
|
||||
{
|
||||
return Field.isPassageBridgeSample(passageIndex,segment,
|
||||
{x/coreMetres,y/coreMetres,z/coreMetres});
|
||||
};
|
||||
const auto thicknessAt=[&](std::size_t segment,double x,double y,double floor)
|
||||
{
|
||||
double thickness=0.0;
|
||||
for(double depth=0.125;depth<=6.0+1.0e-6;depth+=0.125)
|
||||
{
|
||||
if(!bridgeSolidAt(segment,x,y,floor-depth))break;
|
||||
thickness=depth;
|
||||
}
|
||||
return thickness;
|
||||
};
|
||||
for(const auto& range:Field.passageBridgeRanges())
|
||||
{
|
||||
if(range.passageIndex!=passageIndex
|
||||
||range.lastSegment+1>=passage.controlPoints.size())continue;
|
||||
++audit.spans;
|
||||
const bool connectedStart=endpointConnected(range.startPointSubvoxels);
|
||||
const bool connectedEnd=endpointConnected(range.endPointSubvoxels);
|
||||
audit.connectedEnds+=connectedStart+connectedEnd;
|
||||
const std::size_t segmentCount=range.lastSegment-range.firstSegment+1;
|
||||
const std::size_t probeCount=std::min<std::size_t>(256,segmentCount);
|
||||
double spanMinimumThickness=std::numeric_limits<double>::infinity();
|
||||
double spanMaximumThickness=0.0;
|
||||
std::uint64_t spanCrossSections=0,spanCrossSectionFailures=0;
|
||||
for(std::size_t probe=0;probe<probeCount;++probe)
|
||||
{
|
||||
const std::size_t segment=range.firstSegment
|
||||
+std::min(segmentCount-1,(probe*segmentCount)/probeCount);
|
||||
const auto& a=passage.controlPoints[segment];
|
||||
const auto& b=passage.controlPoints[segment+1];
|
||||
const double ax=qToMetres(a.positionSubvoxels[0]);
|
||||
const double ay=qToMetres(a.positionSubvoxels[1]);
|
||||
const double az=qToMetres(a.positionSubvoxels[2]);
|
||||
const double bx=qToMetres(b.positionSubvoxels[0]);
|
||||
const double by=qToMetres(b.positionSubvoxels[1]);
|
||||
const double bz=qToMetres(b.positionSubvoxels[2]);
|
||||
const double x=(ax+bx)*0.5,y=(ay+by)*0.5;
|
||||
const double z=(az+bz)*0.5;
|
||||
const double radius=(qToMetres(a.radiusSubvoxels)
|
||||
+qToMetres(b.radiusSubvoxels))*0.5;
|
||||
const double floor=z-radius+0.13;
|
||||
const double thickness=thicknessAt(segment,x,y,floor);
|
||||
spanMinimumThickness=std::min(spanMinimumThickness,thickness);
|
||||
spanMaximumThickness=std::max(spanMaximumThickness,thickness);
|
||||
audit.minimumThicknessMetres=std::min(audit.minimumThicknessMetres,thickness);
|
||||
audit.maximumThicknessMetres=std::max(audit.maximumThicknessMetres,thickness);
|
||||
const double dx=bx-ax,dy=by-ay,horizontal=std::hypot(dx,dy);
|
||||
if(horizontal<=1.0e-6)continue;
|
||||
const double nx=dy/horizontal,ny=-dx/horizontal;
|
||||
bool crossSectionSolid=true;
|
||||
for(const double offset:{-2.5,0.0,2.5})
|
||||
crossSectionSolid&=bridgeSolidAt(segment,x+nx*offset,
|
||||
y+ny*offset,floor-2.0);
|
||||
++audit.crossSections;
|
||||
++spanCrossSections;
|
||||
spanCrossSectionFailures+=!crossSectionSolid;
|
||||
audit.crossSectionFailures+=!crossSectionSolid;
|
||||
}
|
||||
const double relief=std::isfinite(spanMinimumThickness)
|
||||
?spanMaximumThickness-spanMinimumThickness:0.0;
|
||||
audit.thicknessReliefPeakToPeakMetres=std::max(
|
||||
audit.thicknessReliefPeakToPeakMetres,relief);
|
||||
const bool spanPass=connectedStart&&connectedEnd
|
||||
&&spanCrossSections>=3&&spanCrossSectionFailures==0
|
||||
&&spanMinimumThickness>=2.75
|
||||
&&spanMaximumThickness<=6.5
|
||||
&&audit.thicknessReliefPeakToPeakMetres>=0.20;
|
||||
audit.passed&=spanPass;
|
||||
std::printf("[PassageRockBridgeAudit] id=%s segments=%zu..%zu gap_m=%.3f connected_ends=%d/2 width_at_least_m=5.000 cross_sections=%llu/%llu thickness_m=%.3f..%.3f relief_p2p_m=%.3f status=%s\n",
|
||||
passage.stableId.c_str(),range.firstSegment,range.lastSegment,
|
||||
range.unsupportedLengthMetres,static_cast<int>(connectedStart)
|
||||
+static_cast<int>(connectedEnd),
|
||||
static_cast<unsigned long long>(spanCrossSections-spanCrossSectionFailures),
|
||||
static_cast<unsigned long long>(spanCrossSections),
|
||||
std::isfinite(spanMinimumThickness)?spanMinimumThickness:0.0,
|
||||
spanMaximumThickness,relief,
|
||||
spanPass?"PASS":"FAIL");
|
||||
}
|
||||
return audit;
|
||||
};
|
||||
if(Assembly)
|
||||
for(const auto& stratum:ResolvedLayout->strates)
|
||||
{
|
||||
@@ -939,9 +1110,12 @@ namespace StandaloneStreamBenchmark
|
||||
};
|
||||
std::uint64_t passageCount=0,passagePasses=0,blockedControls=0,naturalPasses=0;
|
||||
std::uint64_t openAirViolations=0,openAirLegacyViolations=0,openAirSamples=0;
|
||||
std::uint64_t openAirAudits=0;
|
||||
for(const auto& passage:ResolvedLayout->passages)
|
||||
std::uint64_t openAirAudits=0,openAirBridgeSamples=0,bridgeSpans=0,
|
||||
bridgeConnectedEnds=0;
|
||||
bool bridgeAuditsPassed=true;
|
||||
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();++passageIndex)
|
||||
{
|
||||
const auto& passage=ResolvedLayout->passages[passageIndex];
|
||||
std::vector<std::array<double,3>> path;path.reserve(passage.controlPoints.size());
|
||||
for(const auto& point:passage.controlPoints)
|
||||
{
|
||||
@@ -951,12 +1125,21 @@ namespace StandaloneStreamBenchmark
|
||||
path.push_back({qToMetres(point.positionSubvoxels[0])/coreMetres,
|
||||
qToMetres(point.positionSubvoxels[1])/coreMetres,playerZ/256.0});
|
||||
}
|
||||
const FWalkAudit passageAudit=auditPlayerPath(Shape,path,0.125,0.125,0.25,3,0.45);
|
||||
std::vector<FPassageSegmentSupportAudit> segmentSupport;
|
||||
const FWalkAudit passageAudit=auditPlayerPath(Shape,path,0.125,0.125,0.25,3,0.45,
|
||||
&blockedWorld,&segmentSupport);
|
||||
const FPassageNaturalnessAudit naturalAudit=auditPassageNaturalness(Shape,passage);
|
||||
const FPassageOpenAirAudit openAirAudit=auditPassageOpenAir(Shape,blockedWorld,passage);
|
||||
const FPassageOpenAirAudit openAirAudit=auditPassageOpenAir(Shape,blockedWorld,
|
||||
passage,passageIndex);
|
||||
const FPassageBridgeAudit bridgeAudit=auditPassageBridges(Shape,blockedWorld,
|
||||
passage,passageIndex);
|
||||
openAirSamples+=openAirAudit.supportSamples;
|
||||
openAirViolations+=openAirAudit.violations;
|
||||
openAirLegacyViolations+=openAirAudit.legacyViolations;
|
||||
openAirBridgeSamples+=openAirAudit.bridgeSamples;
|
||||
bridgeSpans+=bridgeAudit.spans;
|
||||
bridgeConnectedEnds+=bridgeAudit.connectedEnds;
|
||||
bridgeAuditsPassed&=bridgeAudit.passed;
|
||||
++openAirAudits;
|
||||
const auto radialSquared=[](const std::array<std::int64_t,3>& p)
|
||||
{return p[0]*p[0]+p[1]*p[1];};
|
||||
@@ -984,9 +1167,10 @@ namespace StandaloneStreamBenchmark
|
||||
static_cast<unsigned long long>(naturalAudit.wallSamples),
|
||||
static_cast<unsigned long long>(naturalAudit.missingWallSamples),
|
||||
naturalAudit.passed?"PASS":"FAIL");
|
||||
std::printf("[PassageOpenAirAudit] id=%s support_samples=%llu violations=%llu l24_ungated_violations=%llu route_support_samples=%llu route_support_violations=%llu spacing_m=%.3f status=%s\n",
|
||||
std::printf("[PassageOpenAirAudit] id=%s support_samples=%llu violations=%llu bridge_samples=%llu l24_ungated_violations=%llu route_support_samples=%llu route_support_violations=%llu spacing_m=%.3f status=%s\n",
|
||||
passage.stableId.c_str(),static_cast<unsigned long long>(openAirAudit.supportSamples),
|
||||
static_cast<unsigned long long>(openAirAudit.violations),
|
||||
static_cast<unsigned long long>(openAirAudit.bridgeSamples),
|
||||
static_cast<unsigned long long>(openAirAudit.legacyViolations),
|
||||
static_cast<unsigned long long>(openAirAudit.routeSupportSamples),
|
||||
static_cast<unsigned long long>(openAirAudit.routeSupportViolations),
|
||||
@@ -1000,8 +1184,58 @@ namespace StandaloneStreamBenchmark
|
||||
for(std::size_t i=0;i<passageAudit.firstBlockedCount;++i)
|
||||
{
|
||||
const auto& sample=passageAudit.firstBlocked[i];
|
||||
std::printf("[ResolvedPassageAuditSample] id=%s kind=blocked xyz_m=(%.3f,%.3f,%.3f) density=%.6f\n",
|
||||
passage.stableId.c_str(),sample[0],sample[1],sample[2],sample[3]);
|
||||
double nearestDistanceSquared=std::numeric_limits<double>::infinity();
|
||||
std::size_t nearestSegment=0;
|
||||
double nearestT=0.0;
|
||||
double nearestPassageSdf=std::numeric_limits<double>::infinity();
|
||||
std::size_t nearestPassageSegment=0;
|
||||
for(std::size_t segment=0;segment+1<path.size();++segment)
|
||||
{
|
||||
const auto& a=path[segment];const auto& b=path[segment+1];
|
||||
const double dx=b[0]-a[0],dy=b[1]-a[1],dz=b[2]-a[2];
|
||||
const double lengthSquared=dx*dx+dy*dy+dz*dz;
|
||||
const double t=lengthSquared>0.0?std::clamp(
|
||||
((sample[0]/coreMetres-a[0])*dx+(sample[1]/coreMetres-a[1])*dy
|
||||
+(sample[2]/coreMetres-a[2])*dz)/lengthSquared,0.0,1.0):0.0;
|
||||
const double ex=sample[0]/coreMetres-(a[0]+t*dx);
|
||||
const double ey=sample[1]/coreMetres-(a[1]+t*dy);
|
||||
const double ez=sample[2]/coreMetres-(a[2]+t*dz);
|
||||
const double distanceSquared=ex*ex+ey*ey+ez*ez;
|
||||
if(distanceSquared<nearestDistanceSquared)
|
||||
{nearestDistanceSquared=distanceSquared;nearestSegment=segment;nearestT=t;}
|
||||
}
|
||||
for(std::size_t segment=0;segment+1<passage.controlPoints.size();++segment)
|
||||
{
|
||||
const auto& a=passage.controlPoints[segment];
|
||||
const auto& b=passage.controlPoints[segment+1];
|
||||
const double ax=qToMetres(a.positionSubvoxels[0]);
|
||||
const double ay=qToMetres(a.positionSubvoxels[1]);
|
||||
const double az=qToMetres(a.positionSubvoxels[2]);
|
||||
const double dx=qToMetres(b.positionSubvoxels[0]-a.positionSubvoxels[0]);
|
||||
const double dy=qToMetres(b.positionSubvoxels[1]-a.positionSubvoxels[1]);
|
||||
const double dz=qToMetres(b.positionSubvoxels[2]-a.positionSubvoxels[2]);
|
||||
const double lengthSquared=dx*dx+dy*dy+dz*dz;
|
||||
const double t=lengthSquared>0.0?std::clamp(
|
||||
((sample[0]-ax)*dx+(sample[1]-ay)*dy+(sample[2]-az)*dz)
|
||||
/lengthSquared,0.0,1.0):0.0;
|
||||
const double ex=sample[0]-(ax+t*dx),ey=sample[1]-(ay+t*dy),
|
||||
ez=sample[2]-(az+t*dz);
|
||||
const double radius=qToMetres(a.radiusSubvoxels)
|
||||
+(qToMetres(b.radiusSubvoxels)-qToMetres(a.radiusSubvoxels))*t;
|
||||
const double signedDistance=std::sqrt(ex*ex+ey*ey+ez*ez)-radius;
|
||||
if(signedDistance<nearestPassageSdf)
|
||||
{nearestPassageSdf=signedDistance;nearestPassageSegment=segment;}
|
||||
}
|
||||
const VoxelForgeCore::Vec3d nativePosition{sample[0]/coreMetres,
|
||||
sample[1]/coreMetres,sample[2]/coreMetres};
|
||||
const float nativeDensity=blockedWorld.densityAt(nativePosition);
|
||||
const bool bridgeVolume=Shape.isPassageBridgeSample(passageIndex,
|
||||
nearestSegment,nativePosition);
|
||||
std::printf("[ResolvedPassageAuditSample] id=%s kind=blocked xyz_m=(%.3f,%.3f,%.3f) density=%.6f native_density=%.6f segment=%zu t=%.3f passage_segment=%zu passage_sdf_m=%.3f bridge_volume=%d native_path=%s\n",
|
||||
passage.stableId.c_str(),sample[0],sample[1],sample[2],sample[3],
|
||||
nativeDensity,nearestSegment,nearestT,nearestPassageSegment,
|
||||
nearestPassageSdf,bridgeVolume?1:0,
|
||||
blockedWorld.densityDispatchPathAt(nativePosition).c_str());
|
||||
}
|
||||
for(std::size_t i=0;i<passageAudit.firstUnsupportedCount;++i)
|
||||
{
|
||||
@@ -1010,6 +1244,30 @@ namespace StandaloneStreamBenchmark
|
||||
passageAudit.firstUnsupported[i][1],passageAudit.firstUnsupported[i][2],
|
||||
passageAudit.firstUnsupported[i][3]);
|
||||
}
|
||||
for(std::size_t segment=0;segment<segmentSupport.size();++segment)
|
||||
{
|
||||
const auto& item=segmentSupport[segment];
|
||||
if(!item.hasUnsupported)continue;
|
||||
const auto& a=path[segment];const auto& b=path[segment+1];
|
||||
const auto& sample=item.firstUnsupported;
|
||||
const double firstX=sample[0]/coreMetres;
|
||||
const double firstY=sample[1]/coreMetres;
|
||||
const double firstZ=(sample[2]-0.125)/coreMetres;
|
||||
const VoxelForgeCore::Vec3d bridgeProbe{sample[0]/coreMetres,
|
||||
sample[1]/coreMetres,(sample[2]-0.25)/coreMetres};
|
||||
const bool bridgeAtSupport=Shape.isPassageBridgeSample(passageIndex,
|
||||
segment,bridgeProbe);
|
||||
std::printf("[ResolvedPassageSupportSegment] id=%s segment=%zu route_z_m=%.3f..%.3f centers=%llu unsupported=%llu native_unsupported=%llu first_foot_m=(%.3f,%.3f,%.3f) bridge_at_d025=%d native_support_probes=%u/5 native_density_d0125_d1_d2_d4=(%.6f,%.6f,%.6f,%.6f) native_path=%s\n",
|
||||
passage.stableId.c_str(),segment,
|
||||
std::min(a[2],b[2])*coreMetres,std::max(a[2],b[2])*coreMetres,
|
||||
static_cast<unsigned long long>(item.centers),
|
||||
static_cast<unsigned long long>(item.unsupported),
|
||||
static_cast<unsigned long long>(item.nativeUnsupported),
|
||||
sample[0],sample[1],sample[2],bridgeAtSupport?1:0,
|
||||
item.firstNativeSupportedProbes,item.firstNativeDensities[0],item.firstNativeDensities[1],
|
||||
item.firstNativeDensities[2],item.firstNativeDensities[3],
|
||||
blockedWorld.densityDispatchPathAt({firstX,firstY,firstZ}).c_str());
|
||||
}
|
||||
}
|
||||
std::uint64_t routePoints=0,routePasses=0,routeWalkPasses=0,routeBindings=0,routeBindingFailures=0;
|
||||
struct FRouteAuditInput
|
||||
@@ -1082,7 +1340,7 @@ namespace StandaloneStreamBenchmark
|
||||
}
|
||||
const FWalkAudit routeAudit=auditPlayerPath(Shape,route,supportStartMetres,
|
||||
supportStepMetres,supportMaximumMetres,minimumSupportProbes,
|
||||
supportProbeRadiusMetres);
|
||||
supportProbeRadiusMetres,nullptr,nullptr);
|
||||
routeAuditInputs.push_back({stratum.strateIndex,route,supportStartMetres,
|
||||
supportStepMetres,supportMaximumMetres,supportProbeRadiusMetres,
|
||||
minimumSupportProbes});
|
||||
@@ -1151,7 +1409,7 @@ namespace StandaloneStreamBenchmark
|
||||
qToMetres(point.positionSubvoxels[1])/coreMetres,playerZ/256.0});
|
||||
}
|
||||
const FWalkAudit blockedAudit=auditPlayerPath(blockedWorld,path,
|
||||
0.125,0.125,0.25,3,0.45);
|
||||
0.125,0.125,0.25,3,0.45,nullptr,nullptr);
|
||||
blockedControls+=blockedAudit.blocked>0&&!blockedAudit.passed;
|
||||
std::printf("[ResolvedPassageBlockedControl] id=%s blocked_capsule_samples=%llu detected=%s\n",
|
||||
passage.stableId.c_str(),static_cast<unsigned long long>(blockedAudit.blocked),
|
||||
@@ -1161,7 +1419,7 @@ namespace StandaloneStreamBenchmark
|
||||
{
|
||||
const FWalkAudit controlRoute=auditPlayerPath(blockedWorld,input.path,
|
||||
input.supportStart,input.supportStep,input.supportMaximum,
|
||||
input.minimumSupportProbes,input.supportProbeRadius);
|
||||
input.minimumSupportProbes,input.supportProbeRadius,nullptr,nullptr);
|
||||
std::printf("[ResolvedStrateRouteBlockedControl] strate=%d blocked=%llu unsupported=%llu status=%s\n",
|
||||
input.strateIndex,static_cast<unsigned long long>(controlRoute.blocked),
|
||||
static_cast<unsigned long long>(controlRoute.unsupported),
|
||||
@@ -1171,13 +1429,19 @@ namespace StandaloneStreamBenchmark
|
||||
std::printf("[PassageOpenAirNegativeControl] source=L24_ungated_support unsupported_samples=%llu detected=%s\n",
|
||||
static_cast<unsigned long long>(openAirLegacyViolations),
|
||||
l24OpenAirControlDetected?"true":"false");
|
||||
std::printf("[PassageOpenAirAuditSummary] interfaces=%llu samples=%llu violations=%llu l24_negative_control=%s status=%s\n",
|
||||
std::printf("[PassageOpenAirAuditSummary] interfaces=%llu samples=%llu violations=%llu bridge_samples=%llu l24_negative_control=%s status=%s\n",
|
||||
static_cast<unsigned long long>(openAirAudits),
|
||||
static_cast<unsigned long long>(openAirSamples),
|
||||
static_cast<unsigned long long>(openAirViolations),
|
||||
static_cast<unsigned long long>(openAirBridgeSamples),
|
||||
l24OpenAirControlDetected?"DETECTED":"MISSED",
|
||||
openAirAudits==passageCount&&openAirViolations==0&&l24OpenAirControlDetected
|
||||
?"PASS":"FAIL");
|
||||
std::printf("[PassageRockBridgeAuditSummary] spans=%llu connected_ends=%llu/%llu status=%s\n",
|
||||
static_cast<unsigned long long>(bridgeSpans),
|
||||
static_cast<unsigned long long>(bridgeConnectedEnds),
|
||||
static_cast<unsigned long long>(bridgeSpans*2),
|
||||
bridgeAuditsPassed?"PASS":"FAIL");
|
||||
const bool l23SmoothWallDetected=!looksNatural(0.0,0.0);
|
||||
std::printf("[PassageNaturalnessNegativeControl] source=L23_smooth_unrelieved_wall relief_p2p_m=0.000 threshold_m=%.3f detected=%s\n",
|
||||
MinimumWallReliefMetres,l23SmoothWallDetected?"true":"false");
|
||||
@@ -1188,6 +1452,7 @@ namespace StandaloneStreamBenchmark
|
||||
const bool auditPassed=passageCount>0&&passagePasses==passageCount
|
||||
&&naturalPasses==passageCount&&l23SmoothWallDetected
|
||||
&&openAirAudits==passageCount&&openAirViolations==0&&l24OpenAirControlDetected
|
||||
&&bridgeAuditsPassed
|
||||
&&routePasses>0&&routePasses==routeWalkPasses&&routePasses==routeBindings
|
||||
&&routeBindingFailures==0
|
||||
&&blockedCompiled&&blockedControls==passageCount;
|
||||
|
||||
Reference in new issue
Block a user