passages: floor profile by nearest centreline + metric distance outside voids (L114, v222) - WIP

Floor ribs are present in L109/L112/L113 rock tunnels too: the floor height comes from the
nearest segment, so it jumps (up to 5.9-7.3 cm) where the nearest segment switches. v222 reduces
them; faint ribs remain. Quiet-machine timing (load 0.64): near-ready 9-17% slower than L109
(FI W12 0.95 -> 1.10 s); candidate totals ~5x L109. Fast tier FAIL: 2 SW wall-shell probes of
31,381 read host air. Walk/grade audits pass; Clang/GCC deterministic; UE builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-29 23:18:40 +01:00
1 parent 36d954cf2f
commit 5e875ae504
45 files changed
+3081 -53

No files matched your search

@@ -472,7 +472,9 @@ namespace VoxelForgeCore
// Version 218 sweeps passages around a dense smooth spline and limits exposed shells to a trough.
// Version 219 smooths passage XY while mapping each planned height chord over its sampled horizontal arc.
// Version 220 adaptively samples passage curves and rounds open-air wall crests.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 220;
// Version 221 ranks passage segments before floor shaping and preserves their signed exterior distance.
// Version 222 selects the floor profile by centerline position, independent of tube radius.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 222;
enum class FieldChannel : std::uint32_t
{
+84 -37
View File
@@ -266,8 +266,10 @@ public:
double roundSignedDistance=std::numeric_limits<double>::infinity();
double centerZSubvoxels=0.0,floorCenterZSubvoxels=0.0;
double radiusSubvoxels=0.0,floorDepthSubvoxels=0.0;
double t=0.0;
double floorCenterDistanceSq=std::numeric_limits<double>::infinity();
double t=0.0,floorT=0.0;
std::uint32_t segmentIndex=std::numeric_limits<std::uint32_t>::max();
std::uint32_t floorSegmentIndex=std::numeric_limits<std::uint32_t>::max();
float wallRelief=0.0f;
bool valid=false,hasWallRelief=false;
};
@@ -1216,8 +1218,9 @@ public:
double signedDistance=std::numeric_limits<double>::infinity();
double shellSignedDistance=std::numeric_limits<double>::infinity();
double roundSignedDistance=std::numeric_limits<double>::infinity();
double centerZ=0.0,floorCenterZ=0.0,radius=0.0,floorDepth=0.0,t=0.0;
std::size_t segmentIndex=0;
double centerZ=0.0,floorCenterZ=0.0,radius=0.0,floorDepth=0.0;
double t=0.0,floorT=0.0;
std::size_t segmentIndex=0,floorSegmentIndex=0;
bool valid=false;
const FScopedPassageTileQueries::FPassageSweepSample* swept=nullptr;
};
@@ -1255,6 +1258,8 @@ public:
nearest.floorCenterZ=swept->floorCenterZSubvoxels;
nearest.radius=swept->radiusSubvoxels;
nearest.floorDepth=swept->floorDepthSubvoxels;
nearest.floorSegmentIndex=swept->floorSegmentIndex;
nearest.floorT=swept->floorT;
nearest.valid=true;
nearest.swept=swept;
}
@@ -1273,6 +1278,7 @@ public:
const std::ptrdiff_t lastIndex=static_cast<std::ptrdiff_t>(
PassageSegmentData[passageIndex].size())-1;
double bestDistance=std::numeric_limits<double>::infinity();
double bestFloorCenterDistanceSq=std::numeric_limits<double>::infinity();
const auto visitSegment=[&](std::size_t segmentIndex,int)
{
if(passageProfile)++passageProfile->passageCarveSegmentVisits;
@@ -1289,6 +1295,7 @@ public:
const double ex=qx-cx,ey=qy-cy,ez=qz-cz;
const double roundDistance=DeterministicSqrt(
ex*ex+ey*ey+ez*ez)-radius;
const double floorCenterDistanceSq=ex*ex+ey*ey+ez*ez;
const double floorT=segment.horizontalLengthSq>1.0e-12
?std::clamp(((qx-segment.a[0])*segment.delta[0]
+(qy-segment.a[1])*segment.delta[1])
@@ -1300,24 +1307,43 @@ public:
constants,segmentIndex,floorT,segment,qx,qy,floorDepth,qPerMetre);
const double flatDistance=PassageFlatBottomDistance(
static_cast<float>(roundDistance),floorCenterZ,qz,floorDepth,qPerMetre);
if(flatDistance<bestDistance
||(flatDistance==bestDistance
// Radius-based tube selection can favor a wider downhill segment
// and carry its lower floor plane backward. Select the floor profile
// by the centerline position, independently of tube radius.
if(floorCenterDistanceSq<bestFloorCenterDistanceSq
||(floorCenterDistanceSq==bestFloorCenterDistanceSq
&&segmentIndex<nearest.floorSegmentIndex))
{
bestFloorCenterDistanceSq=floorCenterDistanceSq;
nearest.floorCenterZ=floorCenterZ;
nearest.floorDepth=floorDepth;
nearest.floorSegmentIndex=segmentIndex;
nearest.floorT=floorT;
}
// Select the tube segment before applying its floor plane. Taking the
// minimum of each segment's flattened distance lets a lower, downhill
// floor plane extend backward through the overlapping tube and makes
// the floor jump at the prepared-segment spacing.
if(roundDistance<bestDistance
||(roundDistance==bestDistance
&&(!nearest.valid||segmentIndex<nearest.segmentIndex)))
{
bestDistance=flatDistance;
bestDistance=roundDistance;
nearest.signedDistance=flatDistance;
nearest.roundSignedDistance=roundDistance;
nearest.segmentIndex=segmentIndex;
nearest.t=t;
nearest.centerZ=cz;
nearest.floorCenterZ=floorCenterZ;
nearest.radius=radius;
nearest.floorDepth=floorDepth;
nearest.valid=true;
}
};
VisitNearestPassageSegmentRange(passageIndex,0,lastIndex-1,
qx,qy,qz,0,bestDistance,visitSegment);
qx,qy,qz,0,bestDistance,bestFloorCenterDistanceSq,visitSegment);
if(nearest.valid)
nearest.signedDistance=PassageFlatBottomDistance(
static_cast<float>(nearest.roundSignedDistance),
nearest.floorCenterZ,qz,nearest.floorDepth,qPerMetre);
// Shells form a union over nearby route segments, even when another
// segment supplies the nearest interior distance. The hierarchy bound
@@ -1388,8 +1414,10 @@ public:
nearest.shellSignedDistance=std::min(nearest.shellSignedDistance,
localShellDistance);
};
double shellFloorSearchBoundSq=-1.0;
VisitNearestPassageSegmentRange(passageIndex,0,lastIndex-1,
qx,qy,qz,0,shellSearchBound,visitShellSegment);
qx,qy,qz,0,shellSearchBound,shellFloorSearchBoundSq,
visitShellSegment);
}
if(!nearest.valid)continue;
const double wallElevationMetres=(qz-(nearest.floorCenterZ
@@ -1420,6 +1448,7 @@ public:
static_cast<float>(roughRoundDistance),nearest.floorCenterZ,qz,
nearest.floorDepth,qPerMetre);
const auto& segment=PassageSegmentData[passageIndex][nearest.segmentIndex];
const auto& floorSegment=PassageSegmentData[passageIndex][nearest.floorSegmentIndex];
const double alongMetres=segment.authoredAlongMetres
+nearest.t*segment.authoredLengthMetres;
const double mouthDistanceMetres=std::max(0.0,std::min(alongMetres,
@@ -1437,9 +1466,11 @@ public:
const double mouthWallThickness=segment.routeSegment
?smoothShellFade*shellThickness:0.0;
double floorExtensionFade=1.0;
if(!segment.routeSegment)
if(!floorSegment.routeSegment)
{
const double pastMouthMetres=std::max(0.0,alongMetres
const double floorAlongMetres=floorSegment.authoredAlongMetres
+nearest.floorT*floorSegment.authoredLengthMetres;
const double pastMouthMetres=std::max(0.0,floorAlongMetres
-constants.totalPathLengthMetres);
const double extensionFade=std::clamp(1.0
-pastMouthMetres/MouthShellBlendMetres,0.0,1.0);
@@ -1461,31 +1492,22 @@ public:
}
if(!std::isfinite(unionDistance))return density;
// The union's interior is unconditional air. Its one exterior shell is
// solid only in air, so it leaves host rock unchanged. Taking the union
// before writing either polarity makes every tunnel interior beat every
// overlapping tunnel shell.
// Preserve both native graph air and passage interior before any shell
// can change their sign. If they overlap, their positive air fields combine.
const float passageAirDistance=static_cast<float>(-unionDistance/Q);
// Air is the union of the native graph and passage voids. Keeping the
// signed passage distance outside the void as well gives marching cubes
// a real negative distance through the floor instead of the terrain's
// saturated deep-rock value.
if(nativeTunnelFieldDensity>=0.0f)
{
const float passageAir=unionDistance<=0.0
?static_cast<float>(-unionDistance/Q)
:std::numeric_limits<float>::lowest();
return std::max(nativeTunnelFieldDensity,passageAir);
}
return std::max(nativeTunnelFieldDensity,passageAirDistance);
if(nativeFloorSupport!=std::numeric_limits<float>::lowest()
&&nativeFloorSupport<0.0f)
return std::min(nativeFloorSupport,unionDistance<=0.0
?static_cast<float>(-unionDistance/Q):density);
?passageAirDistance:density);
if(nativeTunnelFieldDensity!=std::numeric_limits<float>::lowest())
return unionDistance<=0.0
?static_cast<float>(-unionDistance/Q):density;
if(unionDistance<=0.0)
return static_cast<float>(-unionDistance/Q);
if(unionShellDistance<0.0&&density>=0.0f)
return std::max(density,passageAirDistance);
if(unionDistance>0.0&&unionShellDistance<0.0&&density>=0.0f)
return static_cast<float>(unionShellDistance/Q);
return density;
return std::max(density,passageAirDistance);
}
float ApplyResolvedStrateComposition(float density,float X,float Y,float Z) const
@@ -4303,7 +4325,8 @@ private:
template<class FVisitor>
void VisitNearestPassageSegmentRange(std::size_t passageIndex,
std::ptrdiff_t first,std::ptrdiff_t last,double qx,double qy,double qz,
int priority,double& bestDistance,FVisitor&& visitor) const
int priority,double& bestDistance,double& bestCenterDistanceSq,
FVisitor&& visitor) const
{
(void)priority;
if(first>last||passageIndex>=PassageNearestNodes.size()
@@ -4322,13 +4345,22 @@ private:
return DeterministicSqrt(dx*dx+dy*dy+dz*dz)-node.maximumRadius
-SmoothDistanceSlackMetres*qPerMetre;
};
const auto centerDistanceLowerBoundSq=[&](const FPassageNearestNode& node)
{
const double dx=std::max({node.minimum[0]-qx,0.0,qx-node.maximum[0]});
const double dy=std::max({node.minimum[1]-qy,0.0,qy-node.maximum[1]});
const double dz=std::max({node.minimum[2]-qz,0.0,qz-node.maximum[2]});
return dx*dx+dy*dy+dz*dz;
};
const auto visit=[&](auto&& self,int nodeIndex)->void
{
if(nodeIndex<0)return;
const auto& node=nodes[static_cast<std::size_t>(nodeIndex)];
if(static_cast<std::ptrdiff_t>(node.maximumSegment)<first
||static_cast<std::ptrdiff_t>(node.minimumSegment)>last
||lowerBound(node)>bestDistance)return;
||(lowerBound(node)>bestDistance
&&(bestCenterDistanceSq<0.0
||centerDistanceLowerBoundSq(node)>bestCenterDistanceSq)))return;
if(node.left<0)
{
for(const std::size_t segment:node.segments)
@@ -11430,6 +11462,7 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
const double ex=qx-cx,ey=qy-cy,ez=qz-cz;
const double signedDistance=FStandaloneShapeWorld::DeterministicSqrt(
ex*ex+ey*ey+ez*ez)-radius;
const double floorCenterDistanceSq=ex*ex+ey*ey+ez*ez;
const double floorT=segment.horizontalLengthSq>1.0e-12
?std::clamp(projectionXY/segment.horizontalLengthSq,0.0,1.0):t;
const double floorRadius=segment.radiusA+floorT*segment.radiusDelta;
@@ -11450,6 +11483,17 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
*static_cast<std::size_t>(sweep->dimension)+static_cast<std::size_t>(gy))
*static_cast<std::size_t>(sweep->dimension)+static_cast<std::size_t>(gx);
auto& sample=passageSamples.samples[sampleIndex];
if(floorCenterDistanceSq<sample.floorCenterDistanceSq
||(floorCenterDistanceSq==sample.floorCenterDistanceSq
&&candidate.segmentIndex<sample.floorSegmentIndex))
{
sample.floorCenterDistanceSq=floorCenterDistanceSq;
sample.floorCenterZSubvoxels=floorCenterZ;
sample.floorDepthSubvoxels=floorDepth;
sample.floorT=floorT;
sample.floorSegmentIndex=static_cast<std::uint32_t>(
candidate.segmentIndex);
}
const double alongMetres=segment.authoredAlongMetres
+t*segment.authoredLengthMetres;
const double mouthDistanceMetres=std::max(0.0,std::min(alongMetres,
@@ -11488,16 +11532,16 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
floorShellDistance);
sample.shellSignedDistance=std::min(sample.shellSignedDistance,
localShellDistance);
if(!sample.valid||flatDistance<sample.signedDistance
||(flatDistance==sample.signedDistance
// Rank the tube body by round SDF. Its floor plane is selected
// independently above from the nearest centerline position.
if(!sample.valid||signedDistance<sample.roundSignedDistance
||(signedDistance==sample.roundSignedDistance
&&candidate.segmentIndex<sample.segmentIndex))
{
sample.signedDistance=flatDistance;
sample.roundSignedDistance=signedDistance;
sample.centerZSubvoxels=cz;
sample.floorCenterZSubvoxels=floorCenterZ;
sample.radiusSubvoxels=radius;
sample.floorDepthSubvoxels=floorDepth;
sample.t=t;
sample.segmentIndex=static_cast<std::uint32_t>(candidate.segmentIndex);
sample.valid=true;
@@ -11532,6 +11576,9 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
+static_cast<std::int64_t>(gy)*sweep->stepSubvoxels);
const double qz=static_cast<double>(sweep->gridMinimumSubvoxels[2]
+static_cast<std::int64_t>(gz)*sweep->stepSubvoxels);
sample.signedDistance=FStandaloneShapeWorld::PassageFlatBottomDistance(
static_cast<float>(sample.roundSignedDistance),
sample.floorCenterZSubvoxels,qz,sample.floorDepthSubvoxels,qPerMetre);
const double radius=sample.radiusSubvoxels;
const double centerZ=sample.centerZSubvoxels;
if(sample.signedDistance<=sweep->influenceSubvoxels)