passages: contiguous BVH node ranges + child-bound reuse (L83); scaling and serial floor measured

Exact through LOD2 (all near tile hashes equal L82). W8 LOD0-2: SW 1.09->1.06, FI 2.47->2.34,
TN 2.39->2.43 (noise), VS 1.20->1.18 s. Fast tier PASS.
Scaling W4/W8/W12/W16 (LOD0-2, FI): 3.59 / 2.48 / 2.33 / 2.34 s - flattens past W8-W12.
Estimated infinite-worker floor ~1.0 s FI/TN = shape compile (0.35-0.41 s, not overlapped:
no shape-free tiles in these views) + slowest single LOD0 tile service (0.51-0.59 s).

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 00:24:49 +01:00
1 parent f572108dc4
commit a81b5b7d06
8 files changed
+800 -22

No files matched your search

+49 -22
View File
@@ -4055,6 +4055,7 @@ private:
std::array<double,3> minimum{},maximum{};
double maximumRadius=0.0;
std::size_t minimumSegment=0,maximumSegment=0;
bool segmentRangeContiguous=false;
std::vector<std::size_t> segments;
int left=-1,right=-1;
};
@@ -4873,6 +4874,8 @@ private:
node.maximumSegment=*std::max_element(segments.begin(),segments.end());
node.segments=segments;
std::sort(node.segments.begin(),node.segments.end());
node.segmentRangeContiguous=node.segments.size()
==node.maximumSegment-node.minimumSegment+1;
const int nodeIndex=static_cast<int>(PassageNearestNodes[passageIndex].size());
PassageNearestNodes[passageIndex].push_back(std::move(node));
if(segments.size()>4)
@@ -4918,6 +4921,10 @@ private:
bool hasCandidate=false;
if(node.left<0)
{
if(node.segmentRangeContiguous)
hasCandidate=static_cast<std::ptrdiff_t>(node.maximumSegment)>=first
&&static_cast<std::ptrdiff_t>(node.minimumSegment)<end;
else
for(const std::size_t segment:node.segments)
hasCandidate=hasCandidate
||(static_cast<std::ptrdiff_t>(segment)>=first
@@ -5510,8 +5517,8 @@ private:
template<typename FVisit>
void VisitNearestPassageSpatialNode(std::size_t passageIndex,int nodeIndex,
std::size_t first,std::size_t end,double qx,double qy,double qz,int priority,
const std::vector<std::uint8_t>* activeNodes,double& bestDistance,
FVisit& visit) const
const std::vector<std::uint8_t>* activeNodes,double knownLowerBound,
double& bestDistance,FVisit& visit) const
{
if(passageIndex>=PassageNearestNodes.size()||nodeIndex<0)return;
const auto& nodes=PassageNearestNodes[passageIndex];
@@ -5528,8 +5535,7 @@ private:
candidate=std::lower_bound(node.segments.begin(),node.segments.end(),first);
if(candidate==node.segments.end()||*candidate>=end)return;
}
const double lowerBound=PassageNearestNodeLowerBound(node,qx,qy,qz);
if(lowerBound>bestDistance)return;
if(knownLowerBound>bestDistance)return;
if(node.left<0)
{
for(auto it=candidate;it!=node.segments.end();++it)
@@ -5554,9 +5560,11 @@ private:
const int nearChild=leftBound<=rightBound?node.left:node.right;
const int farChild=leftBound<=rightBound?node.right:node.left;
VisitNearestPassageSpatialNode(passageIndex,nearChild,first,end,qx,qy,qz,
priority,activeNodes,bestDistance,visit);
priority,activeNodes,leftBound<=rightBound?leftBound:rightBound,
bestDistance,visit);
VisitNearestPassageSpatialNode(passageIndex,farChild,first,end,qx,qy,qz,
priority,activeNodes,bestDistance,visit);
priority,activeNodes,leftBound<=rightBound?rightBound:leftBound,
bestDistance,visit);
}
template<typename FVisit>
@@ -5570,9 +5578,18 @@ private:
const auto* tileQueries=ActivePassageTileQueries;
const auto* activeNodes=tileQueries&&tileQueries->matches(*this)
?tileQueries->segmentRangeNodeMask(passageIndex,first,last+1,priority):nullptr;
if(activeNodes&&(activeNodes->empty()||!(*activeNodes)[0]))return;
if(!activeNodes)
{
const auto& root=PassageNearestNodes[passageIndex][0];
if(root.maximumSegment<static_cast<std::size_t>(first)
||root.minimumSegment>=static_cast<std::size_t>(last+1))return;
}
const double rootLowerBound=PassageNearestNodeLowerBound(
PassageNearestNodes[passageIndex][0],qx,qy,qz);
VisitNearestPassageSpatialNode(passageIndex,0,static_cast<std::size_t>(first),
static_cast<std::size_t>(last+1),qx,qy,qz,priority,activeNodes,
bestDistance,callback);
rootLowerBound,bestDistance,callback);
}
bool PassagePotentialWithinNode(std::size_t passageIndex,int nodeIndex,
@@ -5581,13 +5598,18 @@ private:
{
if(passageIndex>=PassageNearestNodes.size()||nodeIndex<0)return false;
const auto& nodes=PassageNearestNodes[passageIndex];
const auto& node=nodes[static_cast<std::size_t>(nodeIndex)];
const std::size_t nodeOffset=static_cast<std::size_t>(nodeIndex);
if(nodeOffset>=nodes.size())return false;
const auto& node=nodes[nodeOffset];
if(node.maximumSegment<first||node.minimumSegment>=end)return false;
const bool allSegmentsInRange=first<=node.minimumSegment
&&node.maximumSegment<end;
const auto candidate=allSegmentsInRange?node.segments.begin()
:std::lower_bound(node.segments.begin(),node.segments.end(),first);
if(candidate==node.segments.end()||*candidate>=end)return false;
if(!node.segmentRangeContiguous)
{
const bool allSegmentsInRange=first<=node.minimumSegment
&&node.maximumSegment<end;
const auto candidate=allSegmentsInRange?node.segments.begin()
:std::lower_bound(node.segments.begin(),node.segments.end(),first);
if(candidate==node.segments.end()||*candidate>=end)return false;
}
if(PassageNearestNodeLowerBound(node,qx,qy,qz)>signedDistanceLimit)return false;
if(node.left<0)return true;
const double leftBound=PassageNearestNodeLowerBound(
@@ -5691,10 +5713,11 @@ private:
{
const auto possible=[&](std::ptrdiff_t first,std::ptrdiff_t last)
{
return first<=last&&passageIndex<PassageNearestNodes.size()
&&!PassageNearestNodes[passageIndex].empty()
&&PassagePotentialWithinNode(passageIndex,0,static_cast<std::size_t>(first),
static_cast<std::size_t>(last+1),qx,qy,qz,signedDistanceLimit);
if(first>last||passageIndex>=PassageNearestNodes.size()
||PassageNearestNodes[passageIndex].empty())return false;
return PassagePotentialWithinNode(passageIndex,0,
static_cast<std::size_t>(first),static_cast<std::size_t>(last+1),
qx,qy,qz,signedDistanceLimit);
};
return possible(carveBegin,carveEnd)
||possible(0,std::min<std::ptrdiff_t>(8,lowerMouthIndex)-1)
@@ -5710,11 +5733,15 @@ private:
const auto& nodes=PassageNearestNodes[passageIndex];
const auto& node=nodes[static_cast<std::size_t>(nodeIndex)];
if(node.maximumSegment<first||node.minimumSegment>=end)return false;
const bool allSegmentsInRange=first<=node.minimumSegment
&&node.maximumSegment<end;
auto candidate=allSegmentsInRange?node.segments.begin()
:std::lower_bound(node.segments.begin(),node.segments.end(),first);
if(candidate==node.segments.end()||*candidate>=end)return false;
auto candidate=node.segments.begin();
if(!node.segmentRangeContiguous)
{
const bool allSegmentsInRange=first<=node.minimumSegment
&&node.maximumSegment<end;
candidate=allSegmentsInRange?node.segments.begin()
:std::lower_bound(node.segments.begin(),node.segments.end(),first);
if(candidate==node.segments.end()||*candidate>=end)return false;
}
const double xyReach=0.39*qPerMetre;
if(qx+xyReach<node.minimum[0]||qx-xyReach>node.maximum[0]
||qy+xyReach<node.minimum[1]||qy-xyReach>node.maximum[1])return false;