core: cave planner holds for 16 seeds; mouth joints planned from the resolved mouth (L135, v236)
Mouth floor/profile carried into the first/last edges (fixes seeds 1 and 2); fixed a Q16/Q32 scale bug in the mouth clearance scorer; shortest grade-safe handles; bounded cave AABBs and hoisted edge-BVH normalisation. Seeds 0-15 pass all composed audits and negative controls; fast tier, Clang/GCC W1/W8/W12 green. Near-ready still +3.9..+13.7% vs assembler/world (Surface World +3.9..+8.2% with no caves). Not for merge. 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
a3c8e3687d
commit
2d89023933
25 files changed
+2516
-235
No files matched your search
@@ -3176,13 +3176,15 @@ namespace StandaloneStreamBenchmark
|
||||
const auto passageUpperMouthFloorDepth=[&](
|
||||
const VoxelForgeCore::ResolvedLayoutPassageV1& passage)
|
||||
{
|
||||
const double controlZ=qToMetres(
|
||||
passage.controlPoints.front().positionSubvoxels[2]);
|
||||
const double authoredMouthDepth=std::max(0.0,controlZ
|
||||
-qToMetres(passage.upperMouthSubvoxels[2])+1.13);
|
||||
const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.upperStrateIndex;});
|
||||
const double mouthCenterHeight=upperStratum!=ResolvedLayout->strates.end()
|
||||
&&upperStratum->generatorKind=="SurfaceWorld"?0.98:1.13;
|
||||
const double controlZ=qToMetres(
|
||||
passage.controlPoints.front().positionSubvoxels[2]);
|
||||
const double authoredMouthDepth=std::max(0.0,controlZ
|
||||
-qToMetres(passage.upperMouthSubvoxels[2])+mouthCenterHeight);
|
||||
if(upperStratum==ResolvedLayout->strates.end()
|
||||
||(upperStratum->generatorKind!="FloatingIslands"
|
||||
&&upperStratum->generatorKind!="TunnelNetwork"))
|
||||
@@ -3202,7 +3204,8 @@ namespace StandaloneStreamBenchmark
|
||||
||distanceSquared>std::pow(
|
||||
qToMetres(passage.controlPoints.front().radiusSubvoxels)+2.0,2.0))
|
||||
return authoredMouthDepth;
|
||||
const double routeAlignedDepth=std::max(0.0,controlZ-routeHeight+1.13);
|
||||
const double routeAlignedDepth=std::max(0.0,
|
||||
controlZ-routeHeight+mouthCenterHeight);
|
||||
return std::max(authoredMouthDepth,routeAlignedDepth);
|
||||
};
|
||||
const auto passageSplineControls=[&](
|
||||
@@ -3349,61 +3352,124 @@ namespace StandaloneStreamBenchmark
|
||||
};
|
||||
std::vector<double> allPassageBodyFloorDepths;
|
||||
std::vector<std::vector<FPassageAuditRoutePoint>> allPassageSmoothRoutes;
|
||||
struct FUpperMouthFloorBlend
|
||||
struct FMouthFloorBlend
|
||||
{
|
||||
std::vector<std::array<double,3>> receivingRoute;
|
||||
double mouthX=0.0,mouthY=0.0,mouthFloor=0.0;
|
||||
double tangentX=0.0,tangentY=0.0;
|
||||
};
|
||||
std::vector<FUpperMouthFloorBlend> allUpperMouthFloorBlends;
|
||||
struct FPassageFloorBlends
|
||||
{
|
||||
FMouthFloorBlend upper,lower;
|
||||
};
|
||||
std::vector<FPassageFloorBlends> allPassageFloorBlends;
|
||||
allPassageBodyFloorDepths.reserve(ResolvedLayout->passages.size());
|
||||
allPassageSmoothRoutes.reserve(ResolvedLayout->passages.size());
|
||||
allUpperMouthFloorBlends.reserve(ResolvedLayout->passages.size());
|
||||
allPassageFloorBlends.reserve(ResolvedLayout->passages.size());
|
||||
for(const auto& passage:ResolvedLayout->passages)
|
||||
{
|
||||
const double bodyDepth=passageBodyFloorDepth(passage);
|
||||
allPassageBodyFloorDepths.push_back(bodyDepth);
|
||||
allPassageSmoothRoutes.push_back(passageSmoothRoute(passage,bodyDepth));
|
||||
FUpperMouthFloorBlend blend;
|
||||
FPassageFloorBlends blends;
|
||||
const auto controls=passageSplineControls(passage);
|
||||
const auto floorProfile=passageSplineFloorProfile(passage);
|
||||
const std::size_t routeEnd=std::clamp<std::size_t>(
|
||||
passage.lowerMouthControlIndex,1,passage.controlPoints.size()-1);
|
||||
const auto segments=VoxelForgeCore::PassageSpline::BuildSegments(
|
||||
controls,routeEnd,8.0,1.0,floorProfile,0.100);
|
||||
const auto upperStratum=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.upperStrateIndex;});
|
||||
if(upperStratum!=ResolvedLayout->strates.end()
|
||||
&&upperStratum->generatorKind=="FloatingIslands")
|
||||
&&(upperStratum->generatorKind=="FloatingIslands"
|
||||
||upperStratum->generatorKind=="TunnelNetwork"))
|
||||
{
|
||||
for(const auto& anchor:upperStratum->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
|
||||
blend.receivingRoute.push_back({
|
||||
blends.upper.receivingRoute.push_back({
|
||||
qToMetres(anchor.values[0]),qToMetres(anchor.values[1]),
|
||||
qToMetres(anchor.values[2])});
|
||||
const auto controls=passageSplineControls(passage);
|
||||
const auto floorProfile=passageSplineFloorProfile(passage);
|
||||
const std::size_t routeEnd=std::clamp<std::size_t>(
|
||||
passage.lowerMouthControlIndex,1,passage.controlPoints.size()-1);
|
||||
const auto segments=VoxelForgeCore::PassageSpline::BuildSegments(
|
||||
controls,routeEnd,8.0,1.0,floorProfile,0.100);
|
||||
if(upperStratum->generatorKind=="TunnelNetwork"
|
||||
&&blends.upper.receivingRoute.size()>2)
|
||||
blends.upper.receivingRoute.erase(
|
||||
blends.upper.receivingRoute.begin(),
|
||||
blends.upper.receivingRoute.end()-2);
|
||||
if(!segments.empty())
|
||||
{
|
||||
blend.mouthX=segments.front().a[0];
|
||||
blend.mouthY=segments.front().a[1];
|
||||
blend.mouthFloor=floorProfile.front();
|
||||
blend.tangentX=segments.front().b[0]-segments.front().a[0];
|
||||
blend.tangentY=segments.front().b[1]-segments.front().a[1];
|
||||
blends.upper.mouthX=controls.front()[0];
|
||||
blends.upper.mouthY=controls.front()[1];
|
||||
blends.upper.mouthFloor=floorProfile.front();
|
||||
blends.upper.tangentX=segments.front().b[0]-segments.front().a[0];
|
||||
blends.upper.tangentY=segments.front().b[1]-segments.front().a[1];
|
||||
}
|
||||
if(upperStratum->generatorKind=="TunnelNetwork")
|
||||
for(const auto& edge:ResolvedLayout->cavernEdges)
|
||||
if(edge.startAnchorStableId==passage.stableId+"/upper-mouth"
|
||||
&&edge.controlPointsMicrometres.size()>=2)
|
||||
{
|
||||
blends.upper.tangentX=
|
||||
(edge.controlPointsMicrometres[0][0]
|
||||
-edge.controlPointsMicrometres[1][0])/1000000.0;
|
||||
blends.upper.tangentY=
|
||||
(edge.controlPointsMicrometres[0][1]
|
||||
-edge.controlPointsMicrometres[1][1])/1000000.0;
|
||||
}
|
||||
}
|
||||
allUpperMouthFloorBlends.push_back(std::move(blend));
|
||||
const auto lowerStratum=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.lowerStrateIndex;});
|
||||
if(lowerStratum!=ResolvedLayout->strates.end()
|
||||
&&lowerStratum->generatorKind=="TunnelNetwork"
|
||||
&&!controls.empty()&&routeEnd<controls.size())
|
||||
{
|
||||
for(const auto& anchor:lowerStratum->anchors)
|
||||
if(anchor.kind=="route_point"&&anchor.values.size()>=3)
|
||||
blends.lower.receivingRoute.push_back({
|
||||
qToMetres(anchor.values[0]),qToMetres(anchor.values[1]),
|
||||
qToMetres(anchor.values[2])});
|
||||
if(blends.lower.receivingRoute.size()>2)
|
||||
blends.lower.receivingRoute.resize(2);
|
||||
blends.lower.mouthX=controls[routeEnd][0];
|
||||
blends.lower.mouthY=controls[routeEnd][1];
|
||||
blends.lower.mouthFloor=floorProfile[routeEnd];
|
||||
if(!segments.empty())
|
||||
{
|
||||
blends.lower.tangentX=controls[routeEnd][0]
|
||||
-controls[routeEnd-1][0];
|
||||
blends.lower.tangentY=controls[routeEnd][1]
|
||||
-controls[routeEnd-1][1];
|
||||
}
|
||||
for(const auto& edge:ResolvedLayout->cavernEdges)
|
||||
if(edge.startAnchorStableId==passage.stableId+"/lower-mouth"
|
||||
&&edge.controlPointsMicrometres.size()>=2)
|
||||
{
|
||||
blends.lower.tangentX=
|
||||
(edge.controlPointsMicrometres[1][0]
|
||||
-edge.controlPointsMicrometres[0][0])/1000000.0;
|
||||
blends.lower.tangentY=
|
||||
(edge.controlPointsMicrometres[1][1]
|
||||
-edge.controlPointsMicrometres[0][1])/1000000.0;
|
||||
}
|
||||
}
|
||||
allPassageFloorBlends.push_back(std::move(blends));
|
||||
}
|
||||
const auto passageFloorAtXY=[&](std::size_t passageIndex,double x,double y,
|
||||
double plannedFloor)
|
||||
{
|
||||
if(passageIndex>=allUpperMouthFloorBlends.size())return plannedFloor;
|
||||
const auto& blend=allUpperMouthFloorBlends[passageIndex];
|
||||
if(passageIndex>=allPassageFloorBlends.size())return plannedFloor;
|
||||
const auto& blends=allPassageFloorBlends[passageIndex];
|
||||
double floor=plannedFloor;
|
||||
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(
|
||||
blend.receivingRoute,x,y,plannedFloor,blend.mouthX,blend.mouthY,
|
||||
blend.mouthFloor,
|
||||
blend.tangentX,blend.tangentY,
|
||||
VoxelForgeCore::PassageSpline::UpperMouthFloorBlendRadiusMetres,
|
||||
1.13);
|
||||
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);
|
||||
};
|
||||
const auto interpolatePassageRoute=[](
|
||||
const std::vector<FPassageAuditRoutePoint>& route,double distance)
|
||||
@@ -4361,7 +4427,8 @@ namespace StandaloneStreamBenchmark
|
||||
// The probes sit 0.18 m inside the authored radius. Add that
|
||||
// radius back to the signed wall distance so radius-carried ribs
|
||||
// remain visible; the cubic detrend removes the smooth mouth flare.
|
||||
radii.push_back(sampleRadius+0.5*(left+right));
|
||||
const double measuredRadius=sampleRadius+0.5*(left+right);
|
||||
radii.push_back(measuredRadius);
|
||||
++audit.samples;
|
||||
}
|
||||
if(radii.size()<static_cast<std::size_t>(WindowLengthMetres/
|
||||
@@ -4494,6 +4561,18 @@ namespace StandaloneStreamBenchmark
|
||||
constexpr double PassageShellAuditSpacingMetres=0.25;
|
||||
constexpr std::array<double,2> PassageShellAuditDepthsMetres{{0.125,0.375}};
|
||||
constexpr float PassageShellDensityTolerance=1.0e-6f;
|
||||
std::vector<bool> surfaceLandingPassages(ResolvedLayout->passages.size(),false);
|
||||
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();
|
||||
++passageIndex)
|
||||
{
|
||||
const auto& passage=ResolvedLayout->passages[passageIndex];
|
||||
const auto upper=std::find_if(ResolvedLayout->strates.begin(),
|
||||
ResolvedLayout->strates.end(),[&](const auto& stratum)
|
||||
{return stratum.strateIndex==passage.upperStrateIndex;});
|
||||
surfaceLandingPassages[passageIndex]=upper!=ResolvedLayout->strates.end()
|
||||
&&upper->generatorKind=="SurfaceWorld"
|
||||
&&upper->lowerInterfaceCapabilities.surfaceToTunnelLandingSupport;
|
||||
}
|
||||
const auto expectedPassageShellAt=[&](double xMetres,double yMetres,
|
||||
double zMetres)
|
||||
{
|
||||
@@ -4639,7 +4718,17 @@ namespace StandaloneStreamBenchmark
|
||||
const double floorBlend=std::clamp(floorDistance/0.25,0.0,1.0);
|
||||
const double smoothFloorBlend=floorBlend*floorBlend
|
||||
*(3.0-2.0*floorBlend);
|
||||
const double thickness=0.75*smoothFade*smoothFloorBlend;
|
||||
double thickness=0.75*smoothFade*smoothFloorBlend;
|
||||
if(candidatePassage<surfaceLandingPassages.size()
|
||||
&&surfaceLandingPassages[candidatePassage])
|
||||
{
|
||||
const double landingFade=std::clamp(1.0-along/8.0,
|
||||
0.0,1.0);
|
||||
const double smoothLandingFade=landingFade*landingFade
|
||||
*(3.0-2.0*landingFade);
|
||||
thickness=std::max(thickness,
|
||||
0.50*smoothLandingFade*smoothFloorBlend);
|
||||
}
|
||||
const double shellDistance=std::max(-flatDistance,
|
||||
flatDistance-thickness);
|
||||
minimumShellDistance=std::min(minimumShellDistance,
|
||||
@@ -5137,11 +5226,9 @@ namespace StandaloneStreamBenchmark
|
||||
{
|
||||
if(stratum.generatorKind!="TunnelNetwork")
|
||||
return equalPosition(authored,mouth);
|
||||
auto expected=mouth;
|
||||
expected[2]+=static_cast<std::int64_t>(std::llround(
|
||||
1130000.0*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel
|
||||
/World.CoreVoxelSizeMicrons));
|
||||
return equalPosition(authored,expected);
|
||||
// Passage mouths already encode the player center 1.13 m above
|
||||
// their floor, matching the route-point convention directly.
|
||||
return equalPosition(authored,mouth);
|
||||
};
|
||||
for(const auto& passage:ResolvedLayout->passages)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user