diag: passage source-floor clamp rejected (L91); field has steep non-distance tails

Clamping the passage-composition source density at -c (c=2..6 voxels, diagnostic, default off)
changes the surface far beyond the bar: c=6 still 65 sign flips, up to 165 cm displacement, 120 deg
normal change (downstream composition consumes deep values). Source gradient at crossings is
distance-like at the median but has huge tails (FI p90 |grad| 512, max 894 vox/vox), so the
density-dependent passage reach is inflated by non-distance values. No world change.

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 05:50:11 +01:00
1 parent a7a03d42b4
commit 8805291d3e
9 files changed
+937 -11

No files matched your search

@@ -1809,6 +1809,10 @@ namespace VoxelForgeCore
bool profileMesherStages = false;
// Research-only: count passage-composer work per generated tile.
bool profilePassageComposer = false;
// Research-only field comparison. A nonnegative value clamps the source density
// entering passage composition to at least -N voxel units for this tile.
// A negative value leaves the process-level diagnostic override in control.
double diagnosticPassageSourceFloorVoxels = -1.0;
// Research-only: collect tile-drain kernel counters and floating-island cache metrics.
// Inactive on ordinary generation so the hot path only pays the option check.
bool instrumentTileDrain = false;
@@ -1907,6 +1911,8 @@ namespace VoxelForgeCore
std::string densityDispatchPathAt(Vec3d voxelPosition) const;
// Analytic source distance without the occupancy-preserving near-zero clamp or packed proxy.
float unclampedDensityAt(Vec3d voxelPosition) const;
// Research-only source field entering passage composition, with passage carving omitted.
float passageSourceDensityAt(Vec3d voxelPosition) const;
DetailFieldSample detailSampleAt(Vec3d voxelPosition) const;
float densityAtLattice(Vec3i voxelPosition) const;
bool isSolidAt(Vec3d voxelPosition) const;
+83 -7
View File
@@ -70,6 +70,20 @@ static bool VF_IsL90PassageCandidateCensusEnabled()
return bEnabled;
}
static double VF_L91PassageSourceFloorVoxels()
{
static const double Value=[]
{
const char* Raw=std::getenv("VOXELFORGE_L91_PASSAGE_SOURCE_FLOOR_VOXELS");
if(!Raw||!*Raw)return 0.0;
char* End=nullptr;
const double Parsed=std::strtod(Raw,&End);
return End!=Raw&&*End=='\0'&&std::isfinite(Parsed)&&Parsed>0.0
?Parsed:0.0;
}();
return Value;
}
// Standalone-only world compiler. It compiles the runtime room/tunnel/passages into
// axis-line intervals, composes rock/cave signs into packed Z-column words, then displaces
// only the conservative surface band. The copied Unreal generator remains the A/B reference.
@@ -226,12 +240,18 @@ public:
FScopedPassageTileQueries(const FStandaloneShapeWorld& shape,
const std::array<std::int64_t,3>& minimumSubvoxels,
const std::array<std::int64_t,3>& maximumSubvoxels,
VoxelForgeCore::TileGenerationStats* profileStats=nullptr,int32 profileLod=0)
VoxelForgeCore::TileGenerationStats* profileStats=nullptr,int32 profileLod=0,
double passageSourceFloorVoxels=-1.0)
:shape_(&shape),minimumSubvoxels_(minimumSubvoxels),
maximumSubvoxels_(maximumSubvoxels),previous_(ActivePassageTileQueries),
profileStats_(profileStats),profileLod_(profileLod),
candidateProfiled_(profileStats!=nullptr&&shape.L90PassageCandidateProgramEnabled)
candidateProfiled_(profileStats!=nullptr&&shape.L90PassageCandidateProgramEnabled),
passageSourceFloorVoxels_(std::isfinite(passageSourceFloorVoxels)
&&passageSourceFloorVoxels>=0.0?passageSourceFloorVoxels
:VF_L91PassageSourceFloorVoxels())
{
if(passageSourceFloorVoxels_>0.0)
clampCounters_=std::make_shared<FPassageSourceClampCounters>();
mayContainResolvedBoundaryBand_=shape.ResolvedBoundaryBandsIntersectSubvoxelRange(
minimumSubvoxels_[2],maximumSubvoxels_[2]);
const bool disablePassageComposition=VF_IsL88PassageCompositionDisabled();
@@ -338,11 +358,18 @@ public:
mayContainResolvedBoundaryBand_(source.mayContainResolvedBoundaryBand_),
mayContainTransitionPassageFade_(source.mayContainTransitionPassageFade_),
previous_(ActivePassageTileQueries),profileLod_(source.profileLod_),
candidateProfiled_(source.candidateProfiled_)
candidateProfiled_(source.candidateProfiled_),
passageSourceFloorVoxels_(source.passageSourceFloorVoxels_),
clampCounters_(source.clampCounters_),ownsClampCounters_(false)
{ ActivePassageTileQueries=this; }
~FScopedPassageTileQueries()
{
ActivePassageTileQueries=previous_;
if(ownsClampCounters_&&clampCounters_&&passageSourceFloorVoxels_>0.0)
std::printf("[L91PassageSourceClampTile] lod=%d floor_vox=%.3f source_clamped=%llu source_delta_sum=%.9g deepest_source_vox=%.9g\n",
profileLod_,passageSourceFloorVoxels_,
static_cast<unsigned long long>(clampCounters_->samples.load()),
clampCounters_->deltaSum.load(),clampCounters_->deepestSource.load());
if(!candidateProfiled_||l90Queries_==0)return;
std::array<std::array<char,360>,4> HistText{};
constexpr std::array<const char*,4> Names={"carve","tread","clearance","mouth_column"};
@@ -451,6 +478,20 @@ public:
VoxelForgeCore::TileGenerationStats* profileStats() const noexcept
{return profileStats_;}
bool candidateCensusProfiled() const noexcept{return candidateProfiled_;}
double passageSourceFloorVoxels() const noexcept{return passageSourceFloorVoxels_;}
void recordPassageSourceClamp(float sourceDensity) const noexcept
{
if(passageSourceFloorVoxels_<=0.0)return;
const double delta=-passageSourceFloorVoxels_-static_cast<double>(sourceDensity);
if(!(delta>0.0)||!std::isfinite(delta))return;
if(!clampCounters_)clampCounters_=std::make_shared<FPassageSourceClampCounters>();
clampCounters_->samples.fetch_add(1,std::memory_order_relaxed);
clampCounters_->deltaSum.fetch_add(delta,std::memory_order_relaxed);
double prior=clampCounters_->deepestSource.load(std::memory_order_relaxed);
while(static_cast<double>(sourceDensity)<prior
&&!clampCounters_->deepestSource.compare_exchange_weak(prior,sourceDensity,
std::memory_order_relaxed,std::memory_order_relaxed)){}
}
void recordL90CandidateHit(const std::array<std::size_t,4>& counts,bool haveBrick) const
{
if(!candidateProfiled_)return;
@@ -491,6 +532,12 @@ public:
{return cavernFeatureIndices_;}
private:
struct FPassageSourceClampCounters
{
std::atomic<std::uint64_t> samples{0};
std::atomic<double> deltaSum{0.0};
std::atomic<double> deepestSource{0.0};
};
const FStandaloneShapeWorld* shape_;
std::array<std::int64_t,3> minimumSubvoxels_,maximumSubvoxels_;
std::vector<std::uint32_t> featureIndices_;
@@ -508,6 +555,9 @@ public:
VoxelForgeCore::TileGenerationStats* profileStats_=nullptr;
int32 profileLod_=0;
bool candidateProfiled_=false;
double passageSourceFloorVoxels_=0.0;
mutable std::shared_ptr<FPassageSourceClampCounters> clampCounters_;
bool ownsClampCounters_=true;
mutable std::uint64_t l90Queries_=0,l90NoBrickQueries_=0;
mutable std::uint64_t l90FallbackIterations_=0,l90FallbackNanoseconds_=0,
l90QueryNanoseconds_=0,l90FallbackCarveVisits_=0,l90FallbackTreadVisits_=0,
@@ -1269,6 +1319,16 @@ public:
~FL90CandidateBrickScope()
{FStandaloneShapeWorld::ActivePassageCandidateBrick=previous;}
} l90CandidateBrickScope(l90CandidateBrick);
const double passageSourceFloorVoxels=passageTileScopeMatches
?passageTileQueries->passageSourceFloorVoxels()
:VF_L91PassageSourceFloorVoxels();
if(passageSourceFloorVoxels>0.0
&&static_cast<double>(density)<-passageSourceFloorVoxels)
{
if(passageTileScopeMatches)
passageTileQueries->recordPassageSourceClamp(density);
density=static_cast<float>(-passageSourceFloorVoxels);
}
if(passageTileScopeMatches&&density>=0.0f
&&!passageTileQueries->hasRouteFeatureOverlap()
&&!passageTileQueries->hasColumnZOverlap()
@@ -4002,6 +4062,9 @@ public:
return AnalyticDensityAt(X,Y,Z);
}
float PassageSourceDensityAt(float X,float Y,float Z) const
{return NativePassageDensityAt(X,Y,Z);}
std::vector<std::uint32_t> OreVeinTileCandidates(
const std::array<std::int64_t,3>& minimum,
const std::array<std::int64_t,3>& maximum) const
@@ -5900,12 +5963,24 @@ private:
L90PassageCandidateBricks.clear();
L90PassageCandidateProgramValid=false;
L90PassageCandidateBuildFailures=0;
L90PassageCandidateReachMetres=10.0;
const auto ReadPositiveEnv=[](const char* Name,double Default)
{
const char* Raw=std::getenv(Name);
if(!Raw||!*Raw)return Default;
char* End=nullptr;
const double Parsed=std::strtod(Raw,&End);
return End!=Raw&&*End=='\0'&&std::isfinite(Parsed)&&Parsed>0.0
?Parsed:Default;
};
L90PassageCandidateReachMetres=ReadPositiveEnv(
"VOXELFORGE_L90_PASSAGE_REACH_METRES",10.0);
const double brickMetres=ReadPositiveEnv(
"VOXELFORGE_L90_PASSAGE_BRICK_METRES",4.0);
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
const double qPerMetre=Q*1000000.0/std::max<std::uint32_t>(1,
ResolvedLayout->coreVoxelSizeMicrometres);
const double voxelsPerMetre=qPerMetre/Q;
L90PassageCandidateBrickEdgeSubvoxels=4.0*qPerMetre;
L90PassageCandidateBrickEdgeSubvoxels=brickMetres*qPerMetre;
const double reachSubvoxels=L90PassageCandidateReachMetres*qPerMetre;
const double cubicPadding=1.0;
std::array<std::uint64_t,4> emittedReferences{};
@@ -6241,8 +6316,9 @@ private:
L90PassageCandidateProgramValid=L90PassageCandidateBuildFailures==0;
const double buildMilliseconds=std::chrono::duration<double,std::milli>(
FClock::now()-buildStart).count();
std::printf("[L90PassageCandidateBuild] brick_m=4 reach_m=%.1f bricks=%zu emitted=(%llu,%llu,%llu,%llu) unique=(%llu,%llu,%llu,%llu) bytes_estimate=%zu build_ms=%.3f failures=%llu valid=%d\n",
L90PassageCandidateReachMetres,L90PassageCandidateBricks.size(),
std::printf("[L90PassageCandidateBuild] brick_m=%.3f reach_m=%.3f source_floor_vox=%.3f bricks=%zu emitted=(%llu,%llu,%llu,%llu) unique=(%llu,%llu,%llu,%llu) bytes_estimate=%zu build_ms=%.3f failures=%llu valid=%d\n",
brickMetres,L90PassageCandidateReachMetres,VF_L91PassageSourceFloorVoxels(),
L90PassageCandidateBricks.size(),
static_cast<unsigned long long>(emittedReferences[0]),
static_cast<unsigned long long>(emittedReferences[1]),
static_cast<unsigned long long>(emittedReferences[2]),
+4 -1
View File
@@ -1909,6 +1909,8 @@ namespace VoxelForgeCore
:"uncompiled"; }
float World::unclampedDensityAt(Vec3d position) const
{ return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape?impl_->shape->DensityAtUnclamped(static_cast<float>(position.x),static_cast<float>(position.y),static_cast<float>(position.z)):0.0f; }
float World::passageSourceDensityAt(Vec3d position) const
{ return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape?impl_->shape->PassageSourceDensityAt(static_cast<float>(position.x),static_cast<float>(position.y),static_cast<float>(position.z)):0.0f; }
DetailFieldSample World::detailSampleAt(Vec3d position) const
{ return impl_&&impl_->shapeReady.load(std::memory_order_acquire)&&impl_->shape?impl_->shape->DetailSampleAt(static_cast<float>(position.x),static_cast<float>(position.y),static_cast<float>(position.z)):DetailFieldSample{}; }
float World::densityAtLattice(Vec3i position) const
@@ -2794,7 +2796,8 @@ namespace VoxelForgeCore
// queryMinimum/queryMaximum ci-dessus couvrent exactement ce domaine inclusif.
const FStandaloneShapeWorld::FScopedPassageTileQueries passageFeatureScope(
tileShape,queryMinimum,queryMaximum,
options.profilePassageComposer?&out.diagnostics:nullptr,key.lod);
options.profilePassageComposer?&out.diagnostics:nullptr,key.lod,
options.diagnosticPassageSourceFloorVoxels);
if(options.profilePassageComposer)
{
out.diagnostics.passageComposerProfiled=true;