standalone: cheap chunk crossings -- exact-tile slab compile, nearest tiles first (~1.2 s -> 121 ms peak)

- Core compiles exact-tile analytic slabs for entering tiles; a Z-column sampler reuses the coherent
  noise context along each tile column; the viewer keeps residents and prioritises nearby tiles.
- 30-crossing straight flight: nearest tile ready 15.8 ms median / 27.6 ms max; full crossing wall
  121 ms peak; worker CPU per crossing 545 ms median, 834 ms max.
- W1/W8 hashes equal; routes 5642/5642; look, passage, stair, thin-sheet, coarse-panel and far
  audits pass; bad-shell control fails; path-hash audit kept.
Cold whole view, measured by me interleaved (busy machine): 1.242 s vs 1.255 s for 3b37d57, parity.
Still open from the owner (LOD0): fins along a strata seam, choppy stair facets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-05 20:12:51 +02:00
1 parent 3b37d5702e
commit 08ceed200d
7 files changed
+614 -86

No files matched your search

+115 -4
View File
@@ -271,12 +271,14 @@ public:
bool bIncludeFarWorld,
std::string& Error,
const VoxelForgeCore::JobScheduler* InScheduler=nullptr,
bool bInRoundTunnels=false,bool bInProfileDetailBand=false)
bool bInRoundTunnels=false,bool bInProfileDetailBand=false,
bool bValidatePassageRoutes=true)
{
using Clock=std::chrono::steady_clock;
const auto TotalStart=Clock::now();
Owner=&World;WorkerCount=std::clamp(Workers,1,8);DetailVariant=Variant;
Scheduler=InScheduler;RoundTunnelsEnabled=bInRoundTunnels;
bAnalyticOnly=false;
bProfileDetailBand=bInProfileDetailBand;
for(int32 A=0;A<3;++A)
{
@@ -321,7 +323,9 @@ public:
ApplyDetailBand(Stats.DetailBandLines);
Stats.SurfaceProxyNodes+=CompleteSignEdgeDistances();
Stats.SurfaceSeconds=std::chrono::duration<double>(Clock::now()-Stage).count();
ValidatePassageRoutes();
// Route validation is world-wide. Detail regions reuse the same authored route data and
// do not need to repeat the 5,642-point world audit for every entering tile group.
if(bValidatePassageRoutes)ValidatePassageRoutes();
Built=true;
if(bIncludeFarWorld)BuildFarWorld();
const uint64 WordBytes=static_cast<uint64>(RockWords.size()+CandidateWords.size())*sizeof(uint64);
@@ -403,6 +407,35 @@ public:
return true;
}
bool BuildAnalyticRegion(FStandaloneOwnerWorld& World,const FIntVector& MinVoxels,
const FIntVector& MaxVoxels,const FIntVector& ClipMinVoxels,
const FIntVector& ClipMaxVoxels,EDetailVariant Variant,
bool bInRoundTunnels,std::string& Error)
{
using Clock=std::chrono::steady_clock;
Owner=&World;WorkerCount=1;DetailVariant=Variant;Scheduler=nullptr;
RoundTunnelsEnabled=bInRoundTunnels;bAnalyticOnly=true;bProfileDetailBand=false;
for(int32 A=0;A<3;++A)
{
Min[A]=(&MinVoxels.X)[A]-2;Max[A]=(&MaxVoxels.X)[A]+2;
ClipMin[A]=(&ClipMinVoxels.X)[A];ClipMax[A]=(&ClipMaxVoxels.X)[A];
Size[A]=Max[A]-Min[A]+1;
if(Size[A]<=0||Size[A]>4096||ClipMax[A]<ClipMin[A])
{Error="analytic tile region is invalid or outside the bounded 4096-node compiler envelope";return false;}
}
Stats={};
const auto Stage=Clock::now();
BuildLayerBounds();BuildOwnerPrimitives();
if(RoundTunnelsEnabled)BuildRoundTunnelPrimitives();
BuildSpatialBins(LineBinSize);
Stats.ShapeSeconds=std::chrono::duration<double>(Clock::now()-Stage).count();
Stats.PrimitiveCount=Primitives.size();
if(Primitives.empty())
{Error="owner shape extraction produced no rooms, tunnels, or passages";return false;}
Built=true;
return true;
}
const FBuildStats& GetStats() const { return Stats; }
bool IsBuilt() const { return Built; }
bool HasFarWorld() const { return FarBuilt; }
@@ -490,7 +523,7 @@ public:
{
int32 IX=0,IY=0,IZ=0;
const bool bInteger=NearInteger(X,IX)&&NearInteger(Y,IY)&&NearInteger(Z,IZ);
const bool bPacked=bInteger&&Contains(IX,IY,IZ);
const bool bPacked=!bAnalyticOnly&&bInteger&&Contains(IX,IY,IZ);
if(bPacked)
return PackedDensityAt(IX,IY,IZ,IsRock(IX,IY,IZ),X,Y,Z);
return AnalyticDensityAt(X,Y,Z);
@@ -498,7 +531,7 @@ public:
float DensityAtLattice(int32 X,int32 Y,int32 Z) const
{
const bool bPacked=Contains(X,Y,Z);
const bool bPacked=!bAnalyticOnly&&Contains(X,Y,Z);
if(bPacked)
return PackedDensityAt(X,Y,Z,IsRock(X,Y,Z),static_cast<float>(X),
static_cast<float>(Y),static_cast<float>(Z));
@@ -506,11 +539,19 @@ public:
static_cast<float>(Z));
}
bool IsAnalyticOnly() const { return bAnalyticOnly; }
void DensityAtLatticeX8(int32 XStart,int32 XStep,int32 Y,int32 Z,
int32 Count,float OutDensity[8]) const
{
Count=std::clamp(Count,0,8);
if(Count==0)return;
if(bAnalyticOnly)
{
for(int32 Lane=0;Lane<Count;++Lane)
OutDensity[Lane]=DensityAtLattice(XStart+Lane*XStep,Y,Z);
return;
}
bool bFast=EditBrushes.empty()&&Y>=Min[1]&&Y<=Max[1]
&&Z>=Min[2]&&Z<=Max[2]
&&XStart>=Min[0]
@@ -3430,6 +3471,75 @@ private:
}
}
public:
void DensityAtLatticeZRun(int32 X,int32 Y,int32 ZStart,int32 ZStep,
int32 Count,float* OutDensity) const
{
if(Count<=0||OutDensity==nullptr)return;
if(!bAnalyticOnly)
{
for(int32 Lane=0;Lane<Count;++Lane)
OutDensity[Lane]=DensityAtLattice(X,Y,ZStart+Lane*ZStep);
return;
}
FDetailNoiseLineContext DetailNoiseLine(
static_cast<float>(X),static_cast<float>(Y),static_cast<uint32>(Owner->Seed));
for(int32 Offset=0;Offset<Count;)
{
int32 Z[8];
const int32 Remaining=std::min(8,Count-Offset);
for(int32 Lane=0;Lane<Remaining;++Lane)
Z[Lane]=ZStart+(Offset+Lane)*ZStep;
const int32 BinZ=FloorDiv(Z[0],ActiveSpatialBinSize);
const auto Found=SpatialBins.find({FloorDiv(X,ActiveSpatialBinSize),
FloorDiv(Y,ActiveSpatialBinSize),BinZ});
const FBinItems* BinItems=Found==SpatialBins.end()?nullptr:&Found->second;
int32 BatchCount=1;
while(BatchCount<Remaining
&&FloorDiv(Z[BatchCount],ActiveSpatialBinSize)==BinZ)++BatchCount;
FEffectiveRockSample Samples[8]{};
EffectiveRockDistanceZ8(X,Y,Z,BatchCount,BinItems,Samples);
for(int32 Lane=0;Lane<BatchCount;++Lane)
{
const int32 SampleZ=Z[Lane];
const bool bInsideFine=X>=Min[0]&&X<=Max[0]
&&Y>=Min[1]&&Y<=Max[1]&&SampleZ>=Min[2]&&SampleZ<=Max[2];
float RockDistance=Samples[Lane].Distance;
if(bInsideFine&&DetailVariant!=EDetailVariant::Smooth
&&std::abs(RockDistance)<=DetailSupremum+0.125f)
{
const float Fade=DetailBandFadeAt(static_cast<float>(X),
static_cast<float>(Y),static_cast<float>(SampleZ),RockDistance,
Samples[Lane].SurfaceSDF,Samples[Lane].CaveInfluence,
Samples[Lane].FloorInfluence);
if(Fade>0.0f)RockDistance+=DetailNoiseOnLine(static_cast<float>(X),
static_cast<float>(Y),static_cast<float>(SampleZ),
Samples[Lane].SurfaceSDF,Samples[Lane].CaveInfluence,
Samples[Lane].FloorInfluence,Samples[Lane].PassageInfluence,
DetailNoiseLine)*Fade;
}
if(Samples[Lane].bCriticalAir)
RockDistance=std::min(RockDistance,-1.0f/16.0f);
const bool bRock=RockDistance>=0.0f;
float Density=-RockDistance;
if((Density<0.0f)!=bRock||std::abs(Density)<0.05f)
Density=(bRock?-1.0f:1.0f)*std::max(std::abs(Density),0.05f);
OutDensity[Offset+Lane]=ApplyEditBrushes(Density,X,Y,SampleZ);
}
Offset+=BatchCount;
}
}
void DensityAtLatticeZ8(int32 X,int32 Y,int32 ZStart,int32 ZStep,
int32 Count,float OutDensity[8]) const
{
DensityAtLatticeZRun(X,Y,ZStart,ZStep,std::clamp(Count,0,8),OutDensity);
}
private:
float CoarseRockDistance(double X,double Y,double Z,bool* OutCriticalAir) const
{
const float Base=StrataDistance(Z);
@@ -3906,4 +4016,5 @@ private:
std::array<std::vector<uint64>,3> CandidateAxisWords;
std::vector<uint64> CandidateWords;
FBuildStats Stats;
bool bAnalyticOnly=false;
};