core: one tunnel for two strates with landing chambers (L151, owner design; v238, grade open)
Each passage records upper and lower landing chambers (floor, gradient, radius, 4.5 m clear height) composed with the tunnel shell; cave route endpoints bind to the chambers; envelope audit permits only the named chamber joints. Seed 2: 0 solid in 319,579 passage+chamber capsule samples, 0 shell violations, 0 envelope conflicts, controls fire. Open: tunnel-to-chamber floor blend leaves 19.1/19.0 deg grades (limit 15); sweeps/timing not run. 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
9ac60d5d18
commit
5bd158d4eb
21 files changed
+1949
-105
No files matched your search
@@ -3090,7 +3090,16 @@ namespace StandaloneStreamBenchmark
|
||||
const double horizontal=std::hypot(dx,dy)*coreMetres;
|
||||
const double vertical=std::abs(dz)*coreMetres;
|
||||
if(horizontal<=1.0e-6||vertical>horizontal*0.2679491924311227)
|
||||
{
|
||||
if(audit.gradeFailures<8)
|
||||
std::printf("[ResolvedWalkGradeFailure] segment=%zu a_xyz_m=(%.3f,%.3f,%.3f) b_xyz_m=(%.3f,%.3f,%.3f) horizontal_m=%.6f vertical_m=%.6f grade_deg=%.3f\n",
|
||||
segment-1,a[0]*coreMetres,a[1]*coreMetres,
|
||||
a[2]*coreMetres,b[0]*coreMetres,b[1]*coreMetres,
|
||||
b[2]*coreMetres,horizontal,vertical,
|
||||
std::atan2(vertical,horizontal)
|
||||
*180.0/3.14159265358979323846);
|
||||
++audit.gradeFailures;
|
||||
}
|
||||
const double length=std::sqrt(dx*dx+dy*dy+dz*dz)*coreMetres;
|
||||
const std::uint64_t intervals=std::max<std::uint64_t>(1,
|
||||
static_cast<std::uint64_t>(std::ceil(length/0.5)));
|
||||
@@ -3193,7 +3202,8 @@ namespace StandaloneStreamBenchmark
|
||||
-qToMetres(passage.upperMouthSubvoxels[2])+mouthCenterHeight);
|
||||
if(upperStratum==ResolvedLayout->strates.end()
|
||||
||(upperStratum->generatorKind!="FloatingIslands"
|
||||
&&upperStratum->generatorKind!="TunnelNetwork"))
|
||||
&&upperStratum->generatorKind!="TunnelNetwork"
|
||||
&&upperStratum->generatorKind!="SurfaceWorld"))
|
||||
return authoredMouthDepth;
|
||||
std::vector<std::array<double,3>> route;
|
||||
for(const auto& anchor:upperStratum->anchors)
|
||||
@@ -3246,7 +3256,8 @@ namespace StandaloneStreamBenchmark
|
||||
{return candidate.strateIndex==strateIndex;});
|
||||
if(stratum!=ResolvedLayout->strates.end()
|
||||
&&(stratum->generatorKind=="TunnelNetwork"
|
||||
||stratum->generatorKind=="FloatingIslands"))
|
||||
||stratum->generatorKind=="FloatingIslands"
|
||||
||stratum->generatorKind=="SurfaceWorld"))
|
||||
for(const auto& anchor:stratum->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
|
||||
route.push_back({qToMetres(anchor.values[0]),
|
||||
@@ -3256,17 +3267,20 @@ namespace StandaloneStreamBenchmark
|
||||
const auto upper=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.upperStrateIndex;});
|
||||
if(upper!=ResolvedLayout->strates.end()
|
||||
&&upper->generatorKind=="TunnelNetwork"&&!controls.empty())
|
||||
if(upper!=ResolvedLayout->strates.end()&&!controls.empty()
|
||||
&&(upper->generatorKind=="TunnelNetwork"
|
||||
||upper->generatorKind=="SurfaceWorld"))
|
||||
{
|
||||
auto route=routeForStrate(passage.upperStrateIndex);
|
||||
if(route.size()>2)route.erase(route.begin(),route.end()-2);
|
||||
if(upper->generatorKind=="TunnelNetwork"&&route.size()>2)
|
||||
route.erase(route.begin(),route.end()-2);
|
||||
double routeHeight=0.0,distanceSquared=0.0;
|
||||
if(VoxelForgeCore::PassageSpline::ClosestRouteHeightAtXY(route,
|
||||
controls.front()[0],controls.front()[1],routeHeight,distanceSquared)
|
||||
&&distanceSquared<=std::pow(controls.front()[3]+2.0,2.0))
|
||||
VoxelForgeCore::PassageSpline::BlendEndpointFloorToRoute(
|
||||
controls,profile,0,route,1.0);
|
||||
controls,profile,0,route,1.0,
|
||||
upper->generatorKind=="SurfaceWorld"?0.98:1.13);
|
||||
}
|
||||
const auto lower=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
@@ -3325,6 +3339,44 @@ namespace StandaloneStreamBenchmark
|
||||
double x=0.0,y=0.0,z=0.0,floorZ=0.0,radius=0.0,distance=0.0;
|
||||
std::size_t segmentIndex=0;
|
||||
};
|
||||
const auto blendLandingChamberFloor=[&](
|
||||
const VoxelForgeCore::ResolvedLayoutPassageV1& passage,
|
||||
double alongMetres,double totalLengthMetres,double x,double y,
|
||||
double plannedFloor)
|
||||
{
|
||||
constexpr double LandingFloorBlendMetres=12.0;
|
||||
const auto weight=[&](double distanceMetres,
|
||||
const VoxelForgeCore::ResolvedLayoutPassageLandingChamberV1& chamber)
|
||||
{
|
||||
const double radius=qToMetres(chamber.radiusSubvoxels);
|
||||
if(!(radius>0.0))return 0.0;
|
||||
if(distanceMetres<=radius)return 1.0;
|
||||
if(distanceMetres>=radius+LandingFloorBlendMetres)return 0.0;
|
||||
const double t=(distanceMetres-radius)/LandingFloorBlendMetres;
|
||||
return 1.0-t*t*(3.0-2.0*t);
|
||||
};
|
||||
const double upperWeight=weight(std::max(0.0,alongMetres),
|
||||
passage.upperLandingChamber);
|
||||
const double lowerWeight=weight(std::max(0.0,
|
||||
totalLengthMetres-alongMetres),passage.lowerLandingChamber);
|
||||
if(upperWeight<=0.0&&lowerWeight<=0.0)return plannedFloor;
|
||||
const auto floorAt=[&](
|
||||
const VoxelForgeCore::ResolvedLayoutPassageLandingChamberV1& chamber)
|
||||
{
|
||||
const double cx=qToMetres(chamber.floorCenterSubvoxels[0]);
|
||||
const double cy=qToMetres(chamber.floorCenterSubvoxels[1]);
|
||||
const double cz=qToMetres(chamber.floorCenterSubvoxels[2]);
|
||||
return cz+chamber.floorGradientQ16[0]/65536.0*(x-cx)
|
||||
+chamber.floorGradientQ16[1]/65536.0*(y-cy);
|
||||
};
|
||||
const double upperFloor=floorAt(passage.upperLandingChamber);
|
||||
const double lowerFloor=floorAt(passage.lowerLandingChamber);
|
||||
const double totalWeight=upperWeight+lowerWeight;
|
||||
if(totalWeight<=1.0)
|
||||
return plannedFloor*(1.0-totalWeight)
|
||||
+upperFloor*upperWeight+lowerFloor*lowerWeight;
|
||||
return (upperFloor*upperWeight+lowerFloor*lowerWeight)/totalWeight;
|
||||
};
|
||||
const auto passageSmoothRoute=[&](
|
||||
const VoxelForgeCore::ResolvedLayoutPassageV1& passage,double bodyDepth)
|
||||
{
|
||||
@@ -3354,6 +3406,16 @@ namespace StandaloneStreamBenchmark
|
||||
segment.alongMetres+segment.lengthMetres,
|
||||
segment.controlSpan+1});
|
||||
}
|
||||
if(route.size()>=2)
|
||||
{
|
||||
const double totalLength=route.back().distance;
|
||||
for(auto& point:route)
|
||||
{
|
||||
point.floorZ=blendLandingChamberFloor(passage,point.distance,
|
||||
totalLength,point.x,point.y,point.floorZ);
|
||||
point.z=point.floorZ+passageTubeDepthAt(point.radius,bodyDepth);
|
||||
}
|
||||
}
|
||||
return route;
|
||||
};
|
||||
std::vector<double> allPassageBodyFloorDepths;
|
||||
@@ -3389,7 +3451,8 @@ namespace StandaloneStreamBenchmark
|
||||
{return stratum.strateIndex==passage.upperStrateIndex;});
|
||||
if(upperStratum!=ResolvedLayout->strates.end()
|
||||
&&(upperStratum->generatorKind=="FloatingIslands"
|
||||
||upperStratum->generatorKind=="TunnelNetwork"))
|
||||
||upperStratum->generatorKind=="TunnelNetwork"
|
||||
||upperStratum->generatorKind=="SurfaceWorld"))
|
||||
{
|
||||
for(const auto& anchor:upperStratum->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
|
||||
@@ -3466,16 +3529,49 @@ namespace StandaloneStreamBenchmark
|
||||
if(passageIndex>=allPassageFloorBlends.size())return plannedFloor;
|
||||
const auto& blends=allPassageFloorBlends[passageIndex];
|
||||
double floor=plannedFloor;
|
||||
const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex
|
||||
==ResolvedLayout->passages[passageIndex].upperStrateIndex;});
|
||||
const double upperPlayerCenterHeight=upperStratum
|
||||
!=ResolvedLayout->strates.end()
|
||||
&&upperStratum->generatorKind=="SurfaceWorld"?0.98:1.13;
|
||||
floor=VoxelForgeCore::PassageSpline::BlendUpperMouthFloorAtXY(
|
||||
blends.upper.receivingRoute,x,y,floor,blends.upper.mouthX,
|
||||
blends.upper.mouthY,blends.upper.mouthFloor,
|
||||
blends.upper.tangentX,blends.upper.tangentY,
|
||||
VoxelForgeCore::PassageSpline::UpperMouthFloorBlendRadiusMetres,1.13);
|
||||
return VoxelForgeCore::PassageSpline::BlendUpperMouthFloorAtXY(
|
||||
VoxelForgeCore::PassageSpline::UpperMouthFloorBlendRadiusMetres,
|
||||
upperPlayerCenterHeight);
|
||||
floor=VoxelForgeCore::PassageSpline::BlendUpperMouthFloorAtXY(
|
||||
blends.lower.receivingRoute,x,y,floor,blends.lower.mouthX,
|
||||
blends.lower.mouthY,blends.lower.mouthFloor,
|
||||
-blends.lower.tangentX,-blends.lower.tangentY,
|
||||
VoxelForgeCore::PassageSpline::UpperMouthFloorBlendRadiusMetres,1.13);
|
||||
if(passageIndex>=allPassageSmoothRoutes.size())return floor;
|
||||
const auto& route=allPassageSmoothRoutes[passageIndex];
|
||||
if(route.size()<2)return floor;
|
||||
double closestDistanceSquared=std::numeric_limits<double>::infinity();
|
||||
double closestAlong=0.0;
|
||||
for(std::size_t index=1;index<route.size();++index)
|
||||
{
|
||||
const auto& a=route[index-1];
|
||||
const auto& b=route[index];
|
||||
const double dx=b.x-a.x,dy=b.y-a.y;
|
||||
const double lengthSquared=dx*dx+dy*dy;
|
||||
const double t=lengthSquared>1.0e-12
|
||||
?std::clamp(((x-a.x)*dx+(y-a.y)*dy)/lengthSquared,0.0,1.0):0.0;
|
||||
const double nearestX=a.x+t*dx,nearestY=a.y+t*dy;
|
||||
const double ex=x-nearestX,ey=y-nearestY;
|
||||
const double distanceSquared=ex*ex+ey*ey;
|
||||
if(distanceSquared<closestDistanceSquared)
|
||||
{
|
||||
closestDistanceSquared=distanceSquared;
|
||||
closestAlong=std::lerp(a.distance,b.distance,t);
|
||||
}
|
||||
}
|
||||
return blendLandingChamberFloor(
|
||||
ResolvedLayout->passages[passageIndex],closestAlong,
|
||||
route.back().distance,x,y,floor);
|
||||
};
|
||||
const auto interpolatePassageRoute=[](
|
||||
const std::vector<FPassageAuditRoutePoint>& route,double distance)
|
||||
@@ -3627,6 +3723,26 @@ namespace StandaloneStreamBenchmark
|
||||
&&passageIndex!=selectedPassage)continue;
|
||||
const auto& passage=ResolvedLayout->passages[passageIndex];
|
||||
if(passage.controlPoints.size()<2)continue;
|
||||
const auto inLandingChamber=[&](
|
||||
const VoxelForgeCore::ResolvedLayoutPassageLandingChamberV1& chamber)
|
||||
{
|
||||
if(chamber.radiusSubvoxels<=0||chamber.clearHeightSubvoxels<=0)
|
||||
return false;
|
||||
const double centerX=qToMetres(chamber.floorCenterSubvoxels[0]);
|
||||
const double centerY=qToMetres(chamber.floorCenterSubvoxels[1]);
|
||||
const double floorCenterZ=qToMetres(
|
||||
chamber.floorCenterSubvoxels[2])
|
||||
+chamber.floorGradientQ16[0]/65536.0*(xMetres-centerX)
|
||||
+chamber.floorGradientQ16[1]/65536.0*(yMetres-centerY);
|
||||
const double radialDistance=std::hypot(xMetres-centerX,
|
||||
yMetres-centerY)-qToMetres(chamber.radiusSubvoxels);
|
||||
const double floorDistance=floorCenterZ-zMetres;
|
||||
const double ceilingDistance=zMetres-(floorCenterZ
|
||||
+qToMetres(chamber.clearHeightSubvoxels));
|
||||
return std::max({radialDistance,floorDistance,ceilingDistance})<=0.0;
|
||||
};
|
||||
if(inLandingChamber(passage.upperLandingChamber)
|
||||
||inLandingChamber(passage.lowerLandingChamber))return true;
|
||||
const auto& route=allPassageSmoothRoutes[passageIndex];
|
||||
if(route.size()<2)continue;
|
||||
double bestRoundDistance=std::numeric_limits<double>::infinity();
|
||||
@@ -4580,6 +4696,78 @@ namespace StandaloneStreamBenchmark
|
||||
[index](const auto& s){return s.strateIndex==index;});
|
||||
return it==ResolvedLayout->strates.end()?nullptr:&*it;
|
||||
};
|
||||
const auto landingChamberConnectionContains=[&](
|
||||
const VoxelForgeCore::ResolvedLayoutPassageV1& passage,bool upper,
|
||||
double xMetres,double yMetres,double zMetres)
|
||||
{
|
||||
const auto& chamber=upper?passage.upperLandingChamber
|
||||
:passage.lowerLandingChamber;
|
||||
const auto* stratum=findStratum(upper?passage.upperStrateIndex
|
||||
:passage.lowerStrateIndex);
|
||||
if(!stratum||chamber.radiusSubvoxels<=0)return false;
|
||||
std::vector<const VoxelForgeCore::ResolvedLayoutAnchorV2*> route;
|
||||
for(const auto& anchor:stratum->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
|
||||
route.push_back(&anchor);
|
||||
if(route.size()<2)return false;
|
||||
const double cx=qToMetres(chamber.floorCenterSubvoxels[0]);
|
||||
const double cy=qToMetres(chamber.floorCenterSubvoxels[1]);
|
||||
const double mouthZ=qToMetres(upper?passage.upperMouthSubvoxels[2]
|
||||
:passage.lowerMouthSubvoxels[2]);
|
||||
std::size_t endpoint=route.size();
|
||||
double endpointDistanceSquared=1.0;
|
||||
for(std::size_t index=0;index<route.size();++index)
|
||||
{
|
||||
const double dx=qToMetres(route[index]->values[0])-cx;
|
||||
const double dy=qToMetres(route[index]->values[1])-cy;
|
||||
const double z=qToMetres(route[index]->values[2]);
|
||||
const double distanceSquared=dx*dx+dy*dy;
|
||||
if(distanceSquared<endpointDistanceSquared
|
||||
&&std::abs(z-mouthZ)<=1.5)
|
||||
{endpoint=index;endpointDistanceSquared=distanceSquared;}
|
||||
}
|
||||
if(endpoint==route.size())return false;
|
||||
std::vector<double> routeDistance(route.size(),0.0);
|
||||
for(std::size_t index=1;index<route.size();++index)
|
||||
{
|
||||
const double dx=qToMetres(route[index]->values[0]
|
||||
-route[index-1]->values[0]);
|
||||
const double dy=qToMetres(route[index]->values[1]
|
||||
-route[index-1]->values[1]);
|
||||
routeDistance[index]=routeDistance[index-1]+std::hypot(dx,dy);
|
||||
}
|
||||
for(std::size_t index=1;index<route.size();++index)
|
||||
{
|
||||
const auto& a=*route[index-1];
|
||||
const auto& b=*route[index];
|
||||
const double ax=qToMetres(a.values[0]),ay=qToMetres(a.values[1]);
|
||||
const double az=qToMetres(a.values[2]);
|
||||
const double dx=qToMetres(b.values[0]-a.values[0]);
|
||||
const double dy=qToMetres(b.values[1]-a.values[1]);
|
||||
const double lengthSquared=dx*dx+dy*dy;
|
||||
if(lengthSquared<=1.0e-12)continue;
|
||||
const double t=std::clamp(((xMetres-ax)*dx+(yMetres-ay)*dy)
|
||||
/lengthSquared,0.0,1.0);
|
||||
const double fromEndpoint=std::abs(std::lerp(
|
||||
routeDistance[index-1],routeDistance[index],t)
|
||||
-routeDistance[endpoint]);
|
||||
if(fromEndpoint>9.0)continue;
|
||||
const double routeX=ax+t*dx,routeY=ay+t*dy;
|
||||
const double routeZ=az+t*qToMetres(b.values[2]-a.values[2]);
|
||||
const double lateralDistance=std::hypot(xMetres-routeX,
|
||||
yMetres-routeY);
|
||||
if(stratum->generatorKind=="TunnelNetwork"
|
||||
||stratum->generatorKind=="VerticalShafts")
|
||||
{
|
||||
const double routeFloor=routeZ-1.13;
|
||||
if(lateralDistance<=0.80&&zMetres>=routeFloor-0.30
|
||||
&&zMetres<=routeFloor+2.25)return true;
|
||||
}
|
||||
else if(lateralDistance<=1.25
|
||||
&&std::abs(zMetres-routeZ)<=1.5)return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const auto controlSnapshot=CoreSnapshot.withoutResolvedLayoutPassages();
|
||||
VoxelForgeCore::World blockedWorld(controlSnapshot);
|
||||
std::string blockedCompileError;
|
||||
@@ -4596,6 +4784,9 @@ namespace StandaloneStreamBenchmark
|
||||
{
|
||||
std::uint64_t floorSamples=0,floorViolations=0,openAirSamples=0;
|
||||
std::uint64_t wallSamples=0,wallViolations=0;
|
||||
std::uint64_t chamberFloorSamples=0,chamberFloorViolations=0;
|
||||
std::uint64_t chamberWallSamples=0,chamberWallViolations=0;
|
||||
std::uint64_t chamberConnectionSkips=0;
|
||||
std::uint64_t floorInteriorWins=0,wallInteriorWins=0;
|
||||
std::uint64_t floorMouthBlendSkips=0,wallMouthBlendSkips=0;
|
||||
std::uint64_t interiorSamples=0,interiorViolations=0;
|
||||
@@ -4782,6 +4973,27 @@ namespace StandaloneStreamBenchmark
|
||||
shellDistance);
|
||||
}
|
||||
}
|
||||
constexpr double LandingChamberShellThicknessMetres=0.75;
|
||||
for(const auto& passage:ResolvedLayout->passages)
|
||||
for(const auto* chamber:{&passage.upperLandingChamber,
|
||||
&passage.lowerLandingChamber})
|
||||
{
|
||||
if(chamber->radiusSubvoxels<=0)continue;
|
||||
const double centerX=qToMetres(chamber->floorCenterSubvoxels[0]);
|
||||
const double centerY=qToMetres(chamber->floorCenterSubvoxels[1]);
|
||||
const double floorCenterZ=qToMetres(
|
||||
chamber->floorCenterSubvoxels[2])
|
||||
+chamber->floorGradientQ16[0]/65536.0*(xMetres-centerX)
|
||||
+chamber->floorGradientQ16[1]/65536.0*(yMetres-centerY);
|
||||
const double radialDistance=std::hypot(xMetres-centerX,
|
||||
yMetres-centerY)-qToMetres(chamber->radiusSubvoxels);
|
||||
const double floorDistance=floorCenterZ-zMetres;
|
||||
const double shellDistance=std::max({-floorDistance,
|
||||
floorDistance-LandingChamberShellThicknessMetres,
|
||||
radialDistance});
|
||||
minimumShellDistance=std::min(minimumShellDistance,
|
||||
shellDistance);
|
||||
}
|
||||
return minimumShellDistance;
|
||||
};
|
||||
for(std::size_t segment=1;segment<route.size();++segment)
|
||||
@@ -4934,6 +5146,89 @@ namespace StandaloneStreamBenchmark
|
||||
if(interior<=0.0f)++audit.interiorViolations;
|
||||
}
|
||||
}
|
||||
constexpr std::array<double,3> chamberFloorRadii{{0.0,2.5,5.0}};
|
||||
constexpr std::array<double,2> chamberWallHeights{{1.13,3.20}};
|
||||
constexpr std::size_t ChamberAngularSamples=16;
|
||||
for(const bool upper:{true,false})
|
||||
{
|
||||
const auto& chamber=upper?passage.upperLandingChamber
|
||||
:passage.lowerLandingChamber;
|
||||
if(chamber.radiusSubvoxels<=0||chamber.clearHeightSubvoxels<=0)continue;
|
||||
const double centerX=qToMetres(chamber.floorCenterSubvoxels[0]);
|
||||
const double centerY=qToMetres(chamber.floorCenterSubvoxels[1]);
|
||||
const double baseFloorZ=qToMetres(chamber.floorCenterSubvoxels[2]);
|
||||
const double radius=qToMetres(chamber.radiusSubvoxels);
|
||||
const double gx=chamber.floorGradientQ16[0]/65536.0;
|
||||
const double gy=chamber.floorGradientQ16[1]/65536.0;
|
||||
for(const double radial:chamberFloorRadii)
|
||||
{
|
||||
if(radial>=radius-1.0)continue;
|
||||
const std::size_t angles=radial==0.0?1:ChamberAngularSamples;
|
||||
for(std::size_t angleIndex=0;angleIndex<angles;++angleIndex)
|
||||
{
|
||||
const double angle=2.0*3.14159265358979323846
|
||||
*static_cast<double>(angleIndex)/ChamberAngularSamples;
|
||||
const double sampleX=centerX+radial*std::cos(angle);
|
||||
const double sampleY=centerY+radial*std::sin(angle);
|
||||
const double floorZ=baseFloorZ+gx*(sampleX-centerX)
|
||||
+gy*(sampleY-centerY);
|
||||
for(const double depth:PassageShellAuditDepthsMetres)
|
||||
{
|
||||
const double sampleZ=floorZ-depth;
|
||||
const VoxelForgeCore::Vec3d position{sampleX/coreMetres,
|
||||
sampleY/coreMetres,sampleZ/coreMetres};
|
||||
if(Native.densityAt(position)<0.0f)continue;
|
||||
if(landingChamberConnectionContains(passage,upper,
|
||||
sampleX,sampleY,sampleZ))
|
||||
{++audit.chamberConnectionSkips;continue;}
|
||||
++audit.chamberFloorSamples;
|
||||
const float density=Field.densityAt(position);
|
||||
if(density>=PassageShellDensityTolerance)
|
||||
{
|
||||
++audit.chamberFloorViolations;
|
||||
std::printf("[PassageLandingChamberShellSample] id=%s side=%s kind=floor_missing xyz_m=(%.3f,%.3f,%.3f) native=%.6f density=%.6f\n",
|
||||
passage.stableId.c_str(),upper?"upper":"lower",
|
||||
sampleX,sampleY,sampleZ,Native.densityAt(position),density);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(std::size_t angleIndex=0;angleIndex<ChamberAngularSamples;
|
||||
++angleIndex)
|
||||
{
|
||||
const double angle=2.0*3.14159265358979323846
|
||||
*static_cast<double>(angleIndex)/ChamberAngularSamples;
|
||||
const double nx=std::cos(angle),ny=std::sin(angle);
|
||||
for(const double depth:PassageShellAuditDepthsMetres)
|
||||
for(const double height:chamberWallHeights)
|
||||
{
|
||||
const double sampleX=centerX+(radius+depth)*nx;
|
||||
const double sampleY=centerY+(radius+depth)*ny;
|
||||
const double floorZ=baseFloorZ+gx*(sampleX-centerX)
|
||||
+gy*(sampleY-centerY);
|
||||
const double sampleZ=floorZ+height;
|
||||
const VoxelForgeCore::Vec3d position{sampleX/coreMetres,
|
||||
sampleY/coreMetres,sampleZ/coreMetres};
|
||||
if(Native.densityAt(position)<0.0f)continue;
|
||||
if(passageInteriorWinsAt(sampleX,sampleY,sampleZ,
|
||||
std::numeric_limits<std::size_t>::max(),
|
||||
std::numeric_limits<std::size_t>::max(),passageIndex)
|
||||
||landingChamberConnectionContains(passage,upper,
|
||||
sampleX,sampleY,sampleZ))
|
||||
{++audit.chamberConnectionSkips;continue;}
|
||||
++audit.chamberWallSamples;
|
||||
const float density=Field.densityAt(position);
|
||||
if(density>=PassageShellDensityTolerance)
|
||||
{
|
||||
++audit.chamberWallViolations;
|
||||
std::printf("[PassageLandingChamberShellSample] id=%s side=%s kind=wall_missing xyz_m=(%.3f,%.3f,%.3f) native=%.6f density=%.6f radial_m=%.3f height_m=%.3f\n",
|
||||
passage.stableId.c_str(),upper?"upper":"lower",
|
||||
sampleX,sampleY,sampleZ,Native.densityAt(position),density,
|
||||
radius+depth,height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return audit;
|
||||
};
|
||||
const auto mouthInContent=[&](std::int32_t index,
|
||||
@@ -4947,14 +5242,74 @@ namespace StandaloneStreamBenchmark
|
||||
return zUm>=stratum->content.bottomMicrometres
|
||||
&&zUm<stratum->content.topMicrometres;
|
||||
};
|
||||
const auto auditLandingChamber=[&](const VoxelForgeCore::World& field,
|
||||
const VoxelForgeCore::ResolvedLayoutPassageV1& passage,
|
||||
std::size_t passageIndex,bool upper)
|
||||
{
|
||||
FWalkAudit total;total.passed=true;
|
||||
const auto& chamber=upper?passage.upperLandingChamber
|
||||
:passage.lowerLandingChamber;
|
||||
if(chamber.radiusSubvoxels<=0||chamber.clearHeightSubvoxels<=0)
|
||||
{total.passed=false;return total;}
|
||||
constexpr std::array<std::array<double,2>,8> directions{{
|
||||
{{1.0,0.0}},{{0.7071067811865475,0.7071067811865475}},
|
||||
{{0.0,1.0}},{{-0.7071067811865475,0.7071067811865475}},
|
||||
{{-1.0,0.0}},{{-0.7071067811865475,-0.7071067811865475}},
|
||||
{{0.0,-1.0}},{{0.7071067811865475,-0.7071067811865475}}}};
|
||||
const double centerX=qToMetres(chamber.floorCenterSubvoxels[0]);
|
||||
const double centerY=qToMetres(chamber.floorCenterSubvoxels[1]);
|
||||
const double centerZ=qToMetres(chamber.floorCenterSubvoxels[2]);
|
||||
const double radius=std::min(5.75,
|
||||
qToMetres(chamber.radiusSubvoxels)-1.5);
|
||||
const double gx=chamber.floorGradientQ16[0]/65536.0;
|
||||
const double gy=chamber.floorGradientQ16[1]/65536.0;
|
||||
const std::function<bool(double,double,double)> interiorPredicate=
|
||||
[&](double x,double y,double z)
|
||||
{return passageInteriorWinsAt(x,y,z,
|
||||
std::numeric_limits<std::size_t>::max(),
|
||||
std::numeric_limits<std::size_t>::max(),passageIndex);};
|
||||
for(const auto& direction:directions)
|
||||
{
|
||||
std::vector<std::array<double,3>> chamberPath;
|
||||
const std::size_t intervals=std::max<std::size_t>(1,
|
||||
static_cast<std::size_t>(std::ceil(radius/0.5)));
|
||||
chamberPath.reserve(intervals+1);
|
||||
for(std::size_t step=0;step<=intervals;++step)
|
||||
{
|
||||
const double distance=radius*step/intervals;
|
||||
const double x=centerX+direction[0]*distance;
|
||||
const double y=centerY+direction[1]*distance;
|
||||
const double floorZ=centerZ+gx*(x-centerX)+gy*(y-centerY);
|
||||
chamberPath.push_back({x/coreMetres,y/coreMetres,
|
||||
(floorZ+1.13)/coreMetres});
|
||||
}
|
||||
const FWalkAudit part=auditPlayerPath(field,chamberPath,
|
||||
0.125,0.125,1.125,3,0.45,{},interiorPredicate);
|
||||
total.segments+=part.segments;total.centers+=part.centers;
|
||||
total.capsuleSamples+=part.capsuleSamples;
|
||||
total.blocked+=part.blocked;
|
||||
total.passageInteriorCapsuleSamples+=part.passageInteriorCapsuleSamples;
|
||||
total.passageInteriorSolidSamples+=part.passageInteriorSolidSamples;
|
||||
total.supportSamples+=part.supportSamples;
|
||||
total.unsupported+=part.unsupported;
|
||||
total.gradeFailures+=part.gradeFailures;
|
||||
total.supportOverlapSkips+=part.supportOverlapSkips;
|
||||
total.passed=total.passed&&part.passed;
|
||||
}
|
||||
return total;
|
||||
};
|
||||
std::uint64_t passageCount=0,passagePasses=0,blockedControls=0,naturalPasses=0;
|
||||
std::uint64_t passageInteriorCapsuleSamples=0,passageInteriorSolidSamples=0;
|
||||
std::uint64_t passageInteriorControls=0;
|
||||
std::uint64_t landingChamberCount=0,landingChamberNegativeControls=0;
|
||||
std::uint64_t mouthProfilePasses=0,ripplePasses=0,rippleControlsDetected=0;
|
||||
std::uint64_t floorRippleControlsDetected=0,floorStepRippleControlsDetected=0;
|
||||
std::uint64_t shellAudits=0,shellFloorSamples=0,shellFloorViolations=0;
|
||||
std::uint64_t shellFloorMouthBlendSkips=0;
|
||||
std::uint64_t shellOpenAirSamples=0,shellWallSamples=0,shellWallViolations=0;
|
||||
std::uint64_t shellChamberFloorSamples=0,shellChamberFloorViolations=0;
|
||||
std::uint64_t shellChamberWallSamples=0,shellChamberWallViolations=0;
|
||||
std::uint64_t shellChamberConnectionSkips=0;
|
||||
std::uint64_t shellInteriorSamples=0,shellInteriorViolations=0;
|
||||
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();++passageIndex)
|
||||
{
|
||||
@@ -4980,11 +5335,26 @@ namespace StandaloneStreamBenchmark
|
||||
std::numeric_limits<std::size_t>::max(),passageIndex);};
|
||||
const FWalkAudit passageAudit=auditPlayerPath(Shape,path,0.375,0.125,
|
||||
1.125,3,0.45,passageSupportExemption,passageInteriorPredicate);
|
||||
const FWalkAudit upperChamberAudit=auditLandingChamber(Shape,
|
||||
passage,passageIndex,true);
|
||||
const FWalkAudit lowerChamberAudit=auditLandingChamber(Shape,
|
||||
passage,passageIndex,false);
|
||||
const bool landingChambersWalkable=upperChamberAudit.passed
|
||||
&&lowerChamberAudit.passed;
|
||||
const bool passageInteriorAirPassed=
|
||||
passageAudit.passageInteriorCapsuleSamples>0
|
||||
&&passageAudit.passageInteriorSolidSamples==0;
|
||||
passageInteriorCapsuleSamples+=passageAudit.passageInteriorCapsuleSamples;
|
||||
passageInteriorSolidSamples+=passageAudit.passageInteriorSolidSamples;
|
||||
&&passageAudit.passageInteriorSolidSamples==0
|
||||
&&upperChamberAudit.passageInteriorCapsuleSamples>0
|
||||
&&lowerChamberAudit.passageInteriorCapsuleSamples>0
|
||||
&&upperChamberAudit.passageInteriorSolidSamples==0
|
||||
&&lowerChamberAudit.passageInteriorSolidSamples==0;
|
||||
passageInteriorCapsuleSamples+=passageAudit.passageInteriorCapsuleSamples
|
||||
+upperChamberAudit.passageInteriorCapsuleSamples
|
||||
+lowerChamberAudit.passageInteriorCapsuleSamples;
|
||||
passageInteriorSolidSamples+=passageAudit.passageInteriorSolidSamples
|
||||
+upperChamberAudit.passageInteriorSolidSamples
|
||||
+lowerChamberAudit.passageInteriorSolidSamples;
|
||||
landingChamberCount+=2;
|
||||
const FPassageNaturalnessAudit naturalAudit=
|
||||
auditPassageNaturalness(Shape,passageIndex);
|
||||
const auto lowerProfileStratum=std::find_if(ResolvedLayout->strates.begin(),
|
||||
@@ -5027,6 +5397,11 @@ namespace StandaloneStreamBenchmark
|
||||
shellOpenAirSamples+=shellAudit.openAirSamples;
|
||||
shellWallSamples+=shellAudit.wallSamples;
|
||||
shellWallViolations+=shellAudit.wallViolations;
|
||||
shellChamberFloorSamples+=shellAudit.chamberFloorSamples;
|
||||
shellChamberFloorViolations+=shellAudit.chamberFloorViolations;
|
||||
shellChamberWallSamples+=shellAudit.chamberWallSamples;
|
||||
shellChamberWallViolations+=shellAudit.chamberWallViolations;
|
||||
shellChamberConnectionSkips+=shellAudit.chamberConnectionSkips;
|
||||
shellInteriorSamples+=shellAudit.interiorSamples;
|
||||
shellInteriorViolations+=shellAudit.interiorViolations;
|
||||
const auto radialSquared=[](const std::array<std::int64_t,3>& p)
|
||||
@@ -5043,7 +5418,8 @@ namespace StandaloneStreamBenchmark
|
||||
rippleControlsDetected+=rippleAudit.controlDetected;
|
||||
floorRippleControlsDetected+=rippleAudit.floorControlDetected;
|
||||
floorStepRippleControlsDetected+=rippleAudit.floorStepControlDetected;
|
||||
passagePasses+=passageAudit.passed&&passageInteriorAirPassed
|
||||
passagePasses+=passageAudit.passed&&landingChambersWalkable
|
||||
&&passageInteriorAirPassed
|
||||
&&mouthsInRadius&&mouthsInContent
|
||||
&&naturalAudit.passed&&mouthProfileAudit.passed&&rippleAudit.passed;
|
||||
std::printf("[ResolvedPassageAudit] id=%s interface=%d-%d control_points=%zu center_samples=%llu capsule_samples=%llu blocked=%llu passage_interior_capsule_samples=%llu passage_interior_solid_samples=%llu interior_air=%s support_samples=%llu support_overlap_skips=%llu unsupported=%llu grade_failures=%llu mouth_content=%d/2 mouth_radius=%d/2 walkability=%s\n",
|
||||
@@ -5058,7 +5434,26 @@ namespace StandaloneStreamBenchmark
|
||||
static_cast<unsigned long long>(passageAudit.supportOverlapSkips),
|
||||
static_cast<unsigned long long>(passageAudit.unsupported),
|
||||
static_cast<unsigned long long>(passageAudit.gradeFailures),mouthsInContent?2:0,
|
||||
mouthsInRadius?2:0,passageAudit.passed?"PASS":"FAIL");
|
||||
mouthsInRadius?2:0,
|
||||
passageAudit.passed&&landingChambersWalkable?"PASS":"FAIL");
|
||||
std::printf("[PassageLandingChamberAudit] id=%s side=upper capsule_samples=%llu solid_samples=%llu support_samples=%llu unsupported=%llu grade_failures=%llu status=%s\n",
|
||||
passage.stableId.c_str(),
|
||||
static_cast<unsigned long long>(upperChamberAudit.passageInteriorCapsuleSamples),
|
||||
static_cast<unsigned long long>(upperChamberAudit.passageInteriorSolidSamples),
|
||||
static_cast<unsigned long long>(upperChamberAudit.supportSamples),
|
||||
static_cast<unsigned long long>(upperChamberAudit.unsupported),
|
||||
static_cast<unsigned long long>(upperChamberAudit.gradeFailures),
|
||||
upperChamberAudit.passed&&upperChamberAudit.passageInteriorSolidSamples==0
|
||||
&&upperChamberAudit.passageInteriorCapsuleSamples>0?"PASS":"FAIL");
|
||||
std::printf("[PassageLandingChamberAudit] id=%s side=lower capsule_samples=%llu solid_samples=%llu support_samples=%llu unsupported=%llu grade_failures=%llu status=%s\n",
|
||||
passage.stableId.c_str(),
|
||||
static_cast<unsigned long long>(lowerChamberAudit.passageInteriorCapsuleSamples),
|
||||
static_cast<unsigned long long>(lowerChamberAudit.passageInteriorSolidSamples),
|
||||
static_cast<unsigned long long>(lowerChamberAudit.supportSamples),
|
||||
static_cast<unsigned long long>(lowerChamberAudit.unsupported),
|
||||
static_cast<unsigned long long>(lowerChamberAudit.gradeFailures),
|
||||
lowerChamberAudit.passed&&lowerChamberAudit.passageInteriorSolidSamples==0
|
||||
&&lowerChamberAudit.passageInteriorCapsuleSamples>0?"PASS":"FAIL");
|
||||
std::printf("[PassageNaturalnessAudit] id=%s flat_run_max_m=%.3f limit_m=%.3f wall_relief_p2p_m=%.3f minimum_m=%.3f samples=%llu missing=%llu status=%s\n",
|
||||
passage.stableId.c_str(),naturalAudit.maximumFlatRunMetres,MaximumFlatRunMetres,
|
||||
naturalAudit.wallReliefPeakToPeakMetres,MinimumWallReliefMetres,
|
||||
@@ -5114,12 +5509,17 @@ namespace StandaloneStreamBenchmark
|
||||
passage.stableId.c_str(),value[0],value[1],value[2],value[2]-value[1],
|
||||
value[3],value[4],value[5]);
|
||||
}
|
||||
std::printf("[PassageShellAudit] id=%s floor_samples=%llu floor_violations=%llu floor_overlap_skips=%llu floor_mouth_blend_skips=%llu open_air_shell_samples=%llu wall_samples=%llu wall_violations=%llu wall_overlap_skips=%llu wall_mouth_blend_skips=%llu interior_samples=%llu interior_violations=%llu spacing_m=%.3f status=%s\n",
|
||||
std::printf("[PassageShellAudit] id=%s floor_samples=%llu floor_violations=%llu floor_overlap_skips=%llu floor_mouth_blend_skips=%llu chamber_floor_samples=%llu chamber_floor_violations=%llu chamber_wall_samples=%llu chamber_wall_violations=%llu chamber_connection_skips=%llu open_air_shell_samples=%llu wall_samples=%llu wall_violations=%llu wall_overlap_skips=%llu wall_mouth_blend_skips=%llu interior_samples=%llu interior_violations=%llu spacing_m=%.3f status=%s\n",
|
||||
passage.stableId.c_str(),
|
||||
static_cast<unsigned long long>(shellAudit.floorSamples),
|
||||
static_cast<unsigned long long>(shellAudit.floorViolations),
|
||||
static_cast<unsigned long long>(shellAudit.floorInteriorWins),
|
||||
static_cast<unsigned long long>(shellAudit.floorMouthBlendSkips),
|
||||
static_cast<unsigned long long>(shellAudit.chamberFloorSamples),
|
||||
static_cast<unsigned long long>(shellAudit.chamberFloorViolations),
|
||||
static_cast<unsigned long long>(shellAudit.chamberWallSamples),
|
||||
static_cast<unsigned long long>(shellAudit.chamberWallViolations),
|
||||
static_cast<unsigned long long>(shellAudit.chamberConnectionSkips),
|
||||
static_cast<unsigned long long>(shellAudit.openAirSamples),
|
||||
static_cast<unsigned long long>(shellAudit.wallSamples),
|
||||
static_cast<unsigned long long>(shellAudit.wallViolations),
|
||||
@@ -5129,6 +5529,8 @@ namespace StandaloneStreamBenchmark
|
||||
static_cast<unsigned long long>(shellAudit.interiorViolations),
|
||||
PassageShellAuditSpacingMetres,
|
||||
shellAudit.floorViolations==0&&shellAudit.wallViolations==0
|
||||
&&shellAudit.chamberFloorViolations==0
|
||||
&&shellAudit.chamberWallViolations==0
|
||||
&&shellAudit.interiorViolations==0
|
||||
?"PASS":"FAIL");
|
||||
for(std::size_t i=0;i<shellAudit.firstViolationCount;++i)
|
||||
@@ -5425,7 +5827,19 @@ namespace StandaloneStreamBenchmark
|
||||
std::numeric_limits<std::size_t>::max(),passageIndex);};
|
||||
const FWalkAudit blockedAudit=auditPlayerPath(blockedWorld,path,
|
||||
0.125,0.125,0.25,3,0.45,{},passageInteriorPredicate);
|
||||
const FWalkAudit upperChamberBlocked=auditLandingChamber(blockedWorld,
|
||||
passage,passageIndex,true);
|
||||
const FWalkAudit lowerChamberBlocked=auditLandingChamber(blockedWorld,
|
||||
passage,passageIndex,false);
|
||||
blockedControls+=blockedAudit.blocked>0&&!blockedAudit.passed;
|
||||
const bool upperChamberControlDetected=
|
||||
upperChamberBlocked.passageInteriorCapsuleSamples>0
|
||||
&&upperChamberBlocked.passageInteriorSolidSamples>0;
|
||||
const bool lowerChamberControlDetected=
|
||||
lowerChamberBlocked.passageInteriorCapsuleSamples>0
|
||||
&&lowerChamberBlocked.passageInteriorSolidSamples>0;
|
||||
landingChamberNegativeControls+=upperChamberControlDetected
|
||||
+lowerChamberControlDetected;
|
||||
const bool passageInteriorControlDetected=
|
||||
blockedAudit.passageInteriorCapsuleSamples>0
|
||||
&&blockedAudit.passageInteriorSolidSamples>0;
|
||||
@@ -5433,6 +5847,16 @@ namespace StandaloneStreamBenchmark
|
||||
std::printf("[ResolvedPassageBlockedControl] id=%s blocked_capsule_samples=%llu detected=%s\n",
|
||||
passage.stableId.c_str(),static_cast<unsigned long long>(blockedAudit.blocked),
|
||||
blockedAudit.blocked>0&&!blockedAudit.passed?"true":"false");
|
||||
std::printf("[PassageLandingChamberNegativeControl] id=%s side=upper capsule_samples=%llu interior_solid_samples=%llu detected=%s\n",
|
||||
passage.stableId.c_str(),
|
||||
static_cast<unsigned long long>(upperChamberBlocked.passageInteriorCapsuleSamples),
|
||||
static_cast<unsigned long long>(upperChamberBlocked.passageInteriorSolidSamples),
|
||||
upperChamberControlDetected?"true":"false");
|
||||
std::printf("[PassageLandingChamberNegativeControl] id=%s side=lower capsule_samples=%llu interior_solid_samples=%llu detected=%s\n",
|
||||
passage.stableId.c_str(),
|
||||
static_cast<unsigned long long>(lowerChamberBlocked.passageInteriorCapsuleSamples),
|
||||
static_cast<unsigned long long>(lowerChamberBlocked.passageInteriorSolidSamples),
|
||||
lowerChamberControlDetected?"true":"false");
|
||||
std::printf("[ResolvedPassageInteriorNegativeControl] id=%s passage_interior_capsule_samples=%llu interior_solid_samples=%llu detected=%s status=%s\n",
|
||||
passage.stableId.c_str(),
|
||||
static_cast<unsigned long long>(blockedAudit.passageInteriorCapsuleSamples),
|
||||
@@ -5443,21 +5867,35 @@ namespace StandaloneStreamBenchmark
|
||||
const bool passageInteriorAuditPassed=passageCount>0
|
||||
&&passageInteriorCapsuleSamples>0&&passageInteriorSolidSamples==0
|
||||
&&passageInteriorControls==passageCount;
|
||||
std::printf("[PassageInteriorCapsuleAuditSummary] interfaces=%llu capsule_samples=%llu solid_samples=%llu negative_controls=%llu/%llu status=%s\n",
|
||||
std::printf("[PassageInteriorCapsuleAuditSummary] interfaces=%llu capsule_samples=%llu solid_samples=%llu negative_controls=%llu/%llu landing_chambers=%llu chamber_negative_controls=%llu/%llu status=%s\n",
|
||||
static_cast<unsigned long long>(passageCount),
|
||||
static_cast<unsigned long long>(passageInteriorCapsuleSamples),
|
||||
static_cast<unsigned long long>(passageInteriorSolidSamples),
|
||||
static_cast<unsigned long long>(passageInteriorControls),
|
||||
static_cast<unsigned long long>(passageCount),
|
||||
static_cast<unsigned long long>(landingChamberCount),
|
||||
static_cast<unsigned long long>(landingChamberNegativeControls),
|
||||
static_cast<unsigned long long>(landingChamberCount),
|
||||
passageInteriorAuditPassed?"PASS":"FAIL");
|
||||
std::printf("[PassageLandingChamberNegativeControlSummary] detected=%llu/%llu naturally_open_baselines=%llu status=OBSERVED\n",
|
||||
static_cast<unsigned long long>(landingChamberNegativeControls),
|
||||
static_cast<unsigned long long>(landingChamberCount),
|
||||
static_cast<unsigned long long>(landingChamberCount
|
||||
-landingChamberNegativeControls));
|
||||
const bool shellAuditPassed=shellAudits==passageCount
|
||||
&&shellFloorViolations==0&&shellWallViolations==0
|
||||
&&shellChamberFloorViolations==0&&shellChamberWallViolations==0
|
||||
&&shellInteriorViolations==0&&shellOpenAirSamples>0;
|
||||
std::printf("[PassageShellAuditSummary] interfaces=%llu floor_samples=%llu floor_violations=%llu floor_mouth_blend_skips=%llu open_air_shell_samples=%llu wall_samples=%llu wall_violations=%llu interior_samples=%llu interior_violations=%llu status=%s\n",
|
||||
std::printf("[PassageShellAuditSummary] interfaces=%llu floor_samples=%llu floor_violations=%llu floor_mouth_blend_skips=%llu chamber_floor_samples=%llu chamber_floor_violations=%llu chamber_wall_samples=%llu chamber_wall_violations=%llu chamber_connection_skips=%llu open_air_shell_samples=%llu wall_samples=%llu wall_violations=%llu interior_samples=%llu interior_violations=%llu status=%s\n",
|
||||
static_cast<unsigned long long>(shellAudits),
|
||||
static_cast<unsigned long long>(shellFloorSamples),
|
||||
static_cast<unsigned long long>(shellFloorViolations),
|
||||
static_cast<unsigned long long>(shellFloorMouthBlendSkips),
|
||||
static_cast<unsigned long long>(shellChamberFloorSamples),
|
||||
static_cast<unsigned long long>(shellChamberFloorViolations),
|
||||
static_cast<unsigned long long>(shellChamberWallSamples),
|
||||
static_cast<unsigned long long>(shellChamberWallViolations),
|
||||
static_cast<unsigned long long>(shellChamberConnectionSkips),
|
||||
static_cast<unsigned long long>(shellOpenAirSamples),
|
||||
static_cast<unsigned long long>(shellWallSamples),
|
||||
static_cast<unsigned long long>(shellWallViolations),
|
||||
|
||||
Reference in new issue
Block a user