core: one passage influence reach in metres, converted once (L130, evaluator v227)

Reach = 0.75 shell + 0.21 relief + 0.50/6 smooth-max support + 0.01 = 1.0533 m, used by proof, feature, fallback,
off-grid bounds and the sweep cutoff. Removes the dead 4 m term (v225 added metres to core-voxel coordinates).
Captures and mouth close-ups byte-identical; proof audit 0 misses over 25,728 shell/crest samples; floor 7.884 mm;
seams, walkability, fast tier, Clang/GCC W1/W8/W12 green; timing equal within noise.

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-31 00:43:44 +01:00
1 parent b96dd739b8
commit 044cd6d9c5
50 files changed
+2389 -29

No files matched your search

@@ -494,7 +494,10 @@ namespace VoxelForgeCore
// Version 223 projects the floor onto one continuous arc-length profile and groups
// dense passage samples into coarse tile candidates. Version 224 keeps the same
// continuous floor while relaxing the spline chord tolerance and bounding shell work.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 225;
// Version 226 unifies the passage influence reach in metres and converts it to core
// voxels for every broadphase and proof bound. Version 227 uses the exact smooth-max
// support width/6 when deriving that reach.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 227;
enum class FieldChannel : std::uint32_t
{
+145 -24
View File
@@ -72,11 +72,28 @@ static bool VF_IsL98PassagePrepareTraceEnabled()
return bEnabled;
}
static double VF_L93PassageCarveReachMetres()
static bool VF_IsL130PassageReachProofAuditEnabled()
{
// The generated world uses a fixed bounded tube influence. An explicit diagnostic
// option can still select the legacy point-evaluation path for comparisons.
return 4.0;
static const bool bEnabled=VF_IsL88DiagnosticSwitchEnabled(
"VOXELFORGE_L130_PASSAGE_REACH_PROOF_AUDIT");
return bEnabled;
}
static constexpr double VF_PassageShellThicknessMetres=0.75;
static constexpr double VF_PassageWallReliefMetres=0.21;
static constexpr double VF_PassageCornerBlendMetres=0.50;
static constexpr double VF_PassageReachMarginMetres=0.01;
// Radial support in metres: shell + maximum relief + the smooth-max support
// (corner-blend width / 6) + a 1 cm guard for float and bound rounding.
static constexpr double VF_PassageInfluenceReachMetres=
VF_PassageShellThicknessMetres+VF_PassageWallReliefMetres
+VF_PassageCornerBlendMetres/6.0+VF_PassageReachMarginMetres;
static double VF_PassageInfluenceReachCoreVoxels(
std::uint32_t coreVoxelSizeMicrometres)
{
return VF_PassageInfluenceReachMetres*1000000.0
/std::max<std::uint32_t>(1,coreVoxelSizeMicrometres);
}
enum class EPassageDensityQueryCaller : std::size_t
@@ -306,7 +323,7 @@ public:
profileStats_(profileStats),profileLod_(profileLod),
passageCarveReachMetres_(std::isfinite(passageCarveReachMetres)
&&passageCarveReachMetres>=0.0?passageCarveReachMetres
:VF_L93PassageCarveReachMetres())
:VF_PassageInfluenceReachMetres)
{
mayContainResolvedBoundaryBand_=shape.ResolvedBoundaryBandsIntersectSubvoxelRange(
minimumSubvoxels_[2],maximumSubvoxels_[2]);
@@ -1204,8 +1221,8 @@ public:
if(!ResolvedLayout||ResolvedLayout->passages.empty()||!std::isfinite(X)
||!std::isfinite(Y)||!std::isfinite(Z))return density;
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
constexpr double FloorShellThicknessMetres=0.75;
constexpr double WallReliefMetres=0.21;
constexpr double FloorShellThicknessMetres=VF_PassageShellThicknessMetres;
constexpr double WallReliefMetres=VF_PassageWallReliefMetres;
constexpr double OpenAirSideWallHeightMetres=1.0;
constexpr double MouthShellBlendMetres=5.0;
const double qPerMetre=Q*1000000.0/
@@ -1630,8 +1647,8 @@ public:
{
constexpr double Q=static_cast<double>(
VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
const double qPerMetre=Q*1000000.0/
std::max<std::uint32_t>(1,ResolvedLayout->coreVoxelSizeMicrometres);
const double reachCoreVoxels=VF_PassageInfluenceReachCoreVoxels(
ResolvedLayout->coreVoxelSizeMicrometres);
const auto overlaps=[&](const double low[3],const double high[3])
{
for(int axis=0;axis<3;++axis)
@@ -1648,7 +1665,8 @@ public:
const auto& p3=passage.controlPoints[
std::min(segment+2,passage.controlPoints.size()-1)];
const double radius=std::max(static_cast<double>(a.radiusSubvoxels),
static_cast<double>(b.radiusSubvoxels))/Q+1.0;
static_cast<double>(b.radiusSubvoxels))/Q
+reachCoreVoxels+0.01;
double low[3]{},high[3]{};
for(int axis=0;axis<3;++axis)
{
@@ -3499,7 +3517,7 @@ private:
double centerZSubvoxels,double queryZSubvoxels,double floorDepthSubvoxels,
double qPerMetre)
{
constexpr double CornerBlendMetres=0.50;
constexpr double CornerBlendMetres=VF_PassageCornerBlendMetres;
const float floorDistance=static_cast<float>(centerZSubvoxels
-floorDepthSubvoxels-queryZSubvoxels);
return SmoothMaxDistance(roundDistanceSubvoxels,floorDistance,
@@ -4811,13 +4829,9 @@ private:
PassageNearestNodes.resize(ResolvedLayout?ResolvedLayout->passages.size():0);
if(!ResolvedLayout||ResolvedLayout->passages.empty())return;
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
constexpr double PassageShellMetres=0.75;
constexpr double ReliefMetres=0.21;
constexpr double SweepReachMetres=4.0;
constexpr double CornerBlendMetres=0.50;
constexpr std::size_t CandidateFineSamplesPerSpan=5;
const double requiredReach=std::max(SweepReachMetres+ReliefMetres
+CornerBlendMetres*0.25,PassageShellMetres+ReliefMetres);
const double requiredReachCoreVoxels=VF_PassageInfluenceReachCoreVoxels(
ResolvedLayout->coreVoxelSizeMicrometres);
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();
++passageIndex)
{
@@ -4854,7 +4868,7 @@ private:
routeMinimum[axis]=std::min(routeMinimum[axis],localMinimum[axis]);
routeMaximum[axis]=std::max(routeMaximum[axis],localMaximum[axis]);
}
const double localExtent=requiredReach
const double localExtent=requiredReachCoreVoxels
+std::max(prepared.radiusA,prepared.radiusB)/Q+0.01;
FPassageProofBound proof;
for(std::size_t axis=0;axis<3;++axis)
@@ -4872,7 +4886,8 @@ private:
std::ceil((localMaximum[axis]+localExtent)*Q));
}
}
const double routeExtent=maximumRadiusSubvoxels/Q+requiredReach+0.01;
const double routeExtent=maximumRadiusSubvoxels/Q
+requiredReachCoreVoxels+0.01;
const double tileExtent=routeExtent;
std::array<std::int64_t,3> featureMinimum{},featureMaximum{};
for(std::size_t axis=0;axis<3;++axis)
@@ -4899,6 +4914,113 @@ private:
BuildPassageFeatureNode(0,PassageFeatureOrder.size());
if(!PassageProofBounds.empty())
BuildPassageProofNode(0,PassageProofBounds.size());
if(VF_IsL130PassageReachProofAuditEnabled())
{
constexpr double Q=static_cast<double>(
VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
constexpr std::array<std::array<double,2>,8> RadialDirections={{
{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}}};
constexpr std::array<double,2> CrestHeightsMetres={0.625,0.875};
const double qPerMetre=Q*1000000.0/
std::max<std::uint32_t>(1,ResolvedLayout->coreVoxelSizeMicrometres);
const std::array<double,6> shellOffsetsMetres={0.70,0.78,0.86,0.94,
VF_PassageInfluenceReachMetres-0.005,
VF_PassageInfluenceReachMetres+0.005};
std::uint64_t sampled=0,signRelevant=0,proofMisses=0,featureMisses=0;
for(std::size_t passageIndex=0;
passageIndex<PassageSegmentData.size();++passageIndex)
{
const auto& segments=PassageSegmentData[passageIndex];
if(segments.empty())continue;
const auto& constants=PassageComposerConstants[passageIndex];
const std::size_t stride=std::max<std::size_t>(1,
(segments.size()+127)/128);
for(std::size_t segmentIndex=0;segmentIndex<segments.size();
segmentIndex+=stride)
{
const auto& segment=segments[segmentIndex];
if(segment.lengthSq<=1.0e-12)continue;
constexpr double T=0.5;
const double centerX=segment.a[0]+T*segment.delta[0];
const double centerY=segment.a[1]+T*segment.delta[1];
const double centerZ=segment.a[2]+T*segment.delta[2];
const double radius=segment.radiusA+T*segment.radiusDelta;
const double floorDepth=PassageFlatFloorDepthSubvoxels(
constants,segmentIndex,T,radius,qPerMetre);
const double floorCenterZ=PassageFlatFloorCenterZSubvoxels(
constants,segments,segmentIndex,T,segment,centerX,centerY,
floorDepth,qPerMetre);
for(const double crestHeightMetres:CrestHeightsMetres)
{
const double sampleZ=floorCenterZ-floorDepth
+crestHeightMetres*qPerMetre;
const double verticalDelta=sampleZ-centerZ;
for(const double shellOffsetMetres:shellOffsetsMetres)
{
const double radialDistance=radius
+shellOffsetMetres*qPerMetre;
if(radialDistance*radialDistance
<=verticalDelta*verticalDelta)continue;
const double horizontalDistance=std::sqrt(
radialDistance*radialDistance
-verticalDelta*verticalDelta);
for(const auto& direction:RadialDirections)
{
const double sampleQ[3]={
centerX+direction[0]*horizontalDistance,
centerY+direction[1]*horizontalDistance,sampleZ};
const double sampleVoxel[3]={sampleQ[0]/Q,
sampleQ[1]/Q,sampleQ[2]/Q};
const float contribution=ApplyResolvedStratePassageCarves(
0.0f,static_cast<float>(sampleVoxel[0]),
static_cast<float>(sampleVoxel[1]),
static_cast<float>(sampleVoxel[2]));
++sampled;
if(std::abs(contribution)<=1.0e-6f)continue;
++signRelevant;
if(PassageProofNodes.empty()
||!PassageProofBoundsOverlapNode(0,sampleVoxel,
sampleVoxel))
++proofMisses;
std::array<std::int64_t,3> sampleMinimum{},sampleMaximum{};
for(std::size_t axis=0;axis<3;++axis)
{
sampleMinimum[axis]=static_cast<std::int64_t>(
std::floor(sampleQ[axis]));
sampleMaximum[axis]=static_cast<std::int64_t>(
std::ceil(sampleQ[axis]));
}
const auto candidates=BuildPassageFeatureTileList(
sampleMinimum,sampleMaximum);
const bool featureContainsSample=std::any_of(
candidates.begin(),candidates.end(),
[&](std::uint32_t featureIndex)
{
return featureIndex<PassageTileFeatures.size()
&&PassageTileFeatures[featureIndex].passageIndex
==passageIndex;
});
if(!featureContainsSample)++featureMisses;
}
}
}
}
}
const bool auditPassed=sampled>0&&signRelevant>0
&&proofMisses==0&&featureMisses==0;
std::printf("[L130PassageReachProofAudit] reach_m=%.3f sampled=%llu sign_relevant=%llu proof_misses=%llu feature_misses=%llu status=%s\n",
VF_PassageInfluenceReachMetres,
static_cast<unsigned long long>(sampled),
static_cast<unsigned long long>(signRelevant),
static_cast<unsigned long long>(proofMisses),
static_cast<unsigned long long>(featureMisses),
auditPassed?"PASS":"FAIL");
if(!auditPassed)std::abort();
}
}
bool PassageProofBoundsOverlapNode(int nodeIndex,const double minimum[3],
@@ -11442,10 +11564,9 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
const FIntVector& origin,std::int32_t step,std::int32_t cells,std::uint32_t seed)
{
constexpr std::int64_t Q=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
constexpr double InfluenceMetres=4.0;
constexpr double OpenAirSideWallHeightMetres=1.0;
if(!shape_||step<=0||cells<=0||!std::isfinite(passageCarveReachMetres_)
||std::abs(passageCarveReachMetres_-InfluenceMetres)>1.0e-9)return;
||std::abs(passageCarveReachMetres_-VF_PassageInfluenceReachMetres)>1.0e-9)return;
const bool profile=profileStats_!=nullptr;
const auto prepareStart=profile?std::chrono::steady_clock::now()
:std::chrono::steady_clock::time_point{};
@@ -11459,7 +11580,7 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
sweep->dimension=cells+3;
const std::size_t gridSampleCount=static_cast<std::size_t>(sweep->dimension)
*static_cast<std::size_t>(sweep->dimension)*static_cast<std::size_t>(sweep->dimension);
sweep->influenceSubvoxels=InfluenceMetres*static_cast<double>(Q)*1000000.0
sweep->influenceSubvoxels=passageCarveReachMetres_*static_cast<double>(Q)*1000000.0
/std::max<std::uint32_t>(1,shape_->ResolvedLayout
?shape_->ResolvedLayout->coreVoxelSizeMicrometres:250000);
sweep->passageToSweep.assign(passageRouteSegments_.size(),-1);
@@ -11473,7 +11594,7 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
const double qPerMetre=static_cast<double>(Q)*1000000.0/
std::max<std::uint32_t>(1,shape_->ResolvedLayout
?shape_->ResolvedLayout->coreVoxelSizeMicrometres:250000);
const double shellThickness=0.75*qPerMetre;
const double shellThickness=VF_PassageShellThicknessMetres*qPerMetre;
const double stampedOutsideDistance=sweep->influenceSubvoxels+1.0;
constexpr double MouthShellBlendMetres=5.0;
const double wallReliefShell=0.41*qPerMetre;
@@ -11633,7 +11754,7 @@ inline void FStandaloneShapeWorld::FScopedPassageTileQueries::prepareSweptTubeBa
// more than cornerWidth/6. Skip its work for pairs outside this exact
// support, with a small subvoxel guard for float rounding. The final
// shell union only consumes negative distances.
constexpr double CornerBlendMetres=0.50;
constexpr double CornerBlendMetres=VF_PassageCornerBlendMetres;
const float roundDistanceFloat=static_cast<float>(signedDistance);
const float floorDistanceFloat=static_cast<float>(floorCenterZ-floorDepth-qz);
const double flatDistanceLowerBound=std::max(