passages: swept tube evaluates the exact route on in-bound cache misses (L100, v216)

L99 treated a missing exact-grid sweep sample as "no route here", so off-grid queries exposed the
FI/TN boundary band inside passage 1-2 (flat ceiling/floor). In-bound misses now evaluate the
exact route; a conservative route-feature bound still skips out-of-extent misses. Composition
order unchanged (graph -> bands -> passage -> stamps -> floor caps).
Comparison now counts added/removed crossings and triangles: 0/0 crossings on all four strates
(FI +56 triangles). 1-2 mid-tunnel: L98->L100 changes 32k px (L99 changed 1.14M).
Near-ready @W12 (L98/L99/L100): FI 2.62/1.78/2.05, TN 2.36/1.55/1.80, SW 1.17/0.95/1.04,
VS 1.16/1.03/1.08 s. All walk audits pass; 24/24 Clang/GCC W1/W8/W12 determinism; fast tier PASS.

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-28 16:49:46 +01:00
1 parent fa6363b31a
commit 2d5822cdf7
47 files changed
+1433 -22

No files matched your search

@@ -476,7 +476,7 @@ namespace VoxelForgeCore
// Version 210 keeps bulk native-cave sampling on the scalar field path at strata edges.
// Version 211 makes coordinate biasing in the shared cell hash unsigned, removing signed-overflow UB.
// Version 212 balances generated entry routes against existing walk lanes and preserves their shared treads.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 215;
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 216;
enum class FieldChannel : std::uint32_t
{
+96 -12
View File
@@ -279,6 +279,7 @@ public:
double signedDistance=std::numeric_limits<double>::infinity();
double t=0.0;
std::uint32_t segmentIndex=std::numeric_limits<std::uint32_t>::max();
std::uint8_t scanPhase=std::numeric_limits<std::uint8_t>::max();
float wallRelief=0.0f,mouthSurfaceRelief=0.0f,mouthTreadFieldRelief=0.0f;
bool valid=false,hasWallRelief=false,hasMouthSurfaceRelief=false,
hasMouthTreadFieldRelief=false;
@@ -634,6 +635,28 @@ public:
const auto& candidates=columnFeature?passageColumns_:passageRoutes_;
return passageIndex<candidates.size()&&candidates[passageIndex]!=0;
}
bool hasUpperMouthSupport(std::size_t passageIndex) const
{
return std::find(upperMouthSupportPassages_.begin(),
upperMouthSupportPassages_.end(),passageIndex)
!=upperMouthSupportPassages_.end();
}
bool routeFeatureMayAffect(std::size_t passageIndex,double qx,double qy,
double qz) const
{
if(passageIndex>=passageRouteSegments_.size())return false;
for(const FCandidateSegment& candidate:passageRouteSegments_[passageIndex])
{
if(qx<candidate.minimumSubvoxels[0]
||qx>candidate.maximumSubvoxels[0]
||qy<candidate.minimumSubvoxels[1]
||qy>candidate.maximumSubvoxels[1]
||qz<candidate.minimumSubvoxels[2]
||qz>candidate.maximumSubvoxels[2])continue;
return true;
}
return false;
}
const std::vector<FCandidateSegment>& mouthSupportSegments(std::size_t passageIndex) const
{
static const std::vector<FCandidateSegment> Empty;
@@ -1910,14 +1933,28 @@ public:
if(l90CandidateProfiled)recordColumnProof(columnDistance,composed);
composed=std::min(composed,static_cast<float>(columnDistance/Q));
}
const bool usePreparedPassageSweep=passageTileScopeMatches
&&passageCarveReachEnabled&&passageTileQueries->hasSweptTubeBase();
const auto* preparedSweepSample=usePreparedPassageSweep
const bool preparedPassageSweepRequested=passageTileScopeMatches
&&passageCarveReachEnabled
&&passageTileQueries->hasSweptTubeBase();
const auto* preparedSweepSample=preparedPassageSweepRequested
?passageTileQueries->sweptSample(passageIndex,qx,qy,qz):nullptr;
// The tile sweep has already visited every segment whose bounded route or
// support envelope reaches this lattice point. No route query can affect it.
if(usePreparedPassageSweep&&(!preparedSweepSample
||preparedSweepSample->signedDistance>passageCarveReachQ))continue;
// The sweep is indexed at the tile's exact lattice points. Mesher and seam
// queries can also arrive at interpolated off-grid positions; a cache miss
// at those points says nothing about route influence, so use the exact direct
// route search instead of dropping the carve.
const bool usePreparedPassageSweep=preparedSweepSample!=nullptr;
// Candidate route bounds include the carve reach, tread/clearance extents,
// and conservative padding. A missing lattice sample outside every route
// bound cannot affect this query; keep direct evaluation for all in-bound
// misses and for the separate column and mouth-support paths.
if(preparedPassageSweepRequested&&!preparedSweepSample
&&!passageTileQueries->hasFeature(passageIndex,true)
&&!passageTileQueries->hasMouthSupport(passageIndex)
&&!passageTileQueries->hasUpperMouthSupport(passageIndex)
&&!passageTileQueries->routeFeatureMayAffect(passageIndex,qx,qy,qz))
continue;
if(usePreparedPassageSweep
&&preparedSweepSample->signedDistance>passageCarveReachQ)continue;
const bool tilePassageFree=passageTileScopeMatches
&&!ActivePassageTileQueries->hasFeature(passageIndex,false);
if(composed>=0.0f&&tilePassageFree)
@@ -2111,7 +2148,7 @@ public:
bestSignedDistance=preparedSweepSample->signedDistance;
bestT=preparedSweepSample->t;
bestIndex=static_cast<std::ptrdiff_t>(preparedSweepSample->segmentIndex);
bestScanPhase=0;
bestScanPhase=preparedSweepSample->scanPhase;
bestScanIndex=bestIndex;
}
else if(passageTileScopeMatches)
@@ -14092,6 +14129,46 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
auto& passageSamples=sweep->passages.emplace_back();
passageSamples.passageIndex=passageIndex;
passageSamples.samples.resize(gridSampleCount);
const auto& constants=shape_->PassageComposerConstants[passageIndex];
struct FCarveWindow
{
std::ptrdiff_t begin=1,end=0;
};
std::vector<FCarveWindow> carveWindows(static_cast<std::size_t>(sweep->dimension));
const auto& floorProfileQ=constants.controlFloorProfileQ;
const std::ptrdiff_t lowerMouthIndex=constants.lowerMouthIndex;
if(lowerMouthIndex>=0
&&static_cast<std::size_t>(lowerMouthIndex)<floorProfileQ.size())
{
const auto compareFloorProfile=[](double floorProfile,double value)
{return floorProfile>value;};
const auto profileBegin=floorProfileQ.begin();
const auto profileEnd=profileBegin+lowerMouthIndex+1;
for(std::int32_t gz=0;gz<sweep->dimension;++gz)
{
const double qz=static_cast<double>(sweep->gridMinimumSubvoxels[2]
+static_cast<std::int64_t>(gz)*sweep->stepSubvoxels);
const auto carveHigh=std::lower_bound(profileBegin,profileEnd,
qz+constants.carveSearchMargin,compareFloorProfile);
const auto carveLow=std::lower_bound(profileBegin,profileEnd,
qz-constants.carveSearchMargin,compareFloorProfile);
auto& window=carveWindows[static_cast<std::size_t>(gz)];
window.begin=std::max<std::ptrdiff_t>(0,
(carveHigh-profileBegin)-1);
window.end=std::min<std::ptrdiff_t>(lowerMouthIndex-1,
(carveLow-profileBegin)+1);
}
}
const auto scanPhaseForSegment=[&](std::ptrdiff_t segmentIndex,
const FCarveWindow& window)
{
if(segmentIndex>=window.begin&&segmentIndex<=window.end)return 0;
if(segmentIndex<std::min<std::ptrdiff_t>(8,lowerMouthIndex))return 1;
if(segmentIndex>=constants.mouthSearchBegin
&&segmentIndex<constants.mouthSearchEnd)return 2;
if(segmentIndex>=lowerMouthIndex&&segmentIndex<constants.lastIndex)return 3;
return -1;
};
for(const auto& candidate:candidates)
{
if(candidate.segmentIndex>=shape_->PassageSegmentData[passageIndex].size())continue;
@@ -14101,7 +14178,6 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
candidate.sweepMaximumSubvoxels[axis],first[axis],last[axis]);
if(first[0]>last[0]||first[1]>last[1]||first[2]>last[2])continue;
const auto& constants=shape_->PassageComposerConstants[passageIndex];
const auto& segment=shape_->PassageSegmentData[passageIndex][candidate.segmentIndex];
if(segment.lengthSq<=0.0)continue;
const std::ptrdiff_t segmentIndex=static_cast<std::ptrdiff_t>(candidate.segmentIndex);
@@ -14112,9 +14188,13 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
&&!shape_->IsPassageShortSpanSegment(passageIndex,candidate.segmentIndex)
&&!shape_->IsPassageShortSpanSegment(passageIndex,candidate.segmentIndex+1);
for(std::int32_t gz=first[2];gz<=last[2];++gz)
for(std::int32_t gy=first[1];gy<=last[1];++gy)
for(std::int32_t gx=first[0];gx<=last[0];++gx)
{
const int scanPhase=scanPhaseForSegment(segmentIndex,
carveWindows[static_cast<std::size_t>(gz)]);
if(scanPhase<0)continue;
for(std::int32_t gy=first[1];gy<=last[1];++gy)
for(std::int32_t gx=first[0];gx<=last[0];++gx)
{
const double qx=static_cast<double>(sweep->gridMinimumSubvoxels[0]
+static_cast<std::int64_t>(gx)*sweep->stepSubvoxels);
const double qy=static_cast<double>(sweep->gridMinimumSubvoxels[1]
@@ -14162,17 +14242,21 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
auto& sample=passageSamples.samples[sampleIndex];
if(!sample.valid||signedDistance<sample.signedDistance
||(signedDistance==sample.signedDistance
&&candidate.segmentIndex<sample.segmentIndex))
&&(scanPhase<sample.scanPhase
||(scanPhase==sample.scanPhase
&&candidate.segmentIndex<sample.segmentIndex))))
{
sample.signedDistance=signedDistance;
sample.t=t;
sample.segmentIndex=static_cast<std::uint32_t>(candidate.segmentIndex);
sample.scanPhase=static_cast<std::uint8_t>(scanPhase);
sample.valid=true;
sample.hasWallRelief=false;
sample.hasMouthSurfaceRelief=false;
sample.hasMouthTreadFieldRelief=false;
if(profile)++profileStats_->passageSweepMinimumUpdates;
}
}
}
}
}