standalone: landing plate removed; passage shaft rings reduced with the rock detail kept

- AddLanding no longer adds a shallow positive ellipsoid (floor plate check 71.3% -> 0%).
- Round 10 had removed all relief on passage walls to pass the ring check (smooth tube; rejected).
  Cause found instead: the owner roughness's 8-voxel Z anchors with linear interpolation. Passage-
  controlled walls now use 2-voxel anchors, blended smoothly into the 8-voxel ones.
- Ring gate (lag-20 correlation) 0.376 -> 0.038 AND shaft relief RMS 1.294 (smooth-tube control
  0.276 fails); passage/cave relief ratio 1.152. Faint rings remain deep in the shaft.
- Whole view 0.984 s cold @8w (interleaved, full payload); W1/W8 44/44 hash fields equal; routes
  5642/5642; look and far-survival audits pass; bad-shell control fails.

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 09:56:11 +02:00
1 parent 2656d81ac9
commit 631dd57eb4
14 files changed
+552 -48

No files matched your search

+140 -45
View File
@@ -138,6 +138,7 @@ public:
double FloorBlendRadius = 0.0;
bool bCarve = true;
bool bCritical = false;
bool bPassageSurface = false;
bool bCapsule = false;
bool bSmoothCapsuleRadius = false;
bool bRoundedBox = false;
@@ -612,14 +613,17 @@ private:
}
ESurfaceFamily SurfaceFamily=ESurfaceFamily::Strata;float SurfaceSDF=100000.0f;
bool bFloorSurface=false,bCriticalAir=false;float CaveInfluence=0.0f,FloorInfluence=0.0f;
float PassageInfluence=0.0f;
float RockDistance=EffectiveRockDistance(X,Y,Z,&SurfaceFamily,&SurfaceSDF,
&bFloorSurface,&CaveInfluence,&FloorInfluence,&bCriticalAir);
&bFloorSurface,&CaveInfluence,&FloorInfluence,&bCriticalAir,nullptr,false,
&PassageInfluence);
if(bInsideFine&&DetailVariant!=EDetailVariant::Smooth
&&std::abs(RockDistance)<=DetailSupremum+0.125f)
{
const float Fade=DetailBandFadeAt(X,Y,Z,RockDistance,SurfaceSDF,
CaveInfluence,FloorInfluence);
if(Fade>0.0f)RockDistance+=DetailNoise(X,Y,Z,SurfaceSDF,CaveInfluence,FloorInfluence)*Fade;
if(Fade>0.0f)RockDistance+=DetailNoise(X,Y,Z,SurfaceSDF,CaveInfluence,
FloorInfluence,PassageInfluence)*Fade;
}
if(bCriticalAir)RockDistance=std::min(RockDistance,-1.0f/16.0f);
const bool bRock=RockDistance>=0.0f;
@@ -683,7 +687,7 @@ public:
return bFlips&&bCoherent&&bFamilies;
}
bool AuditSurfaceBandFamilies() const
bool AuditSurfaceBandFamilies(bool bPassageOnly=false) const
{
struct FPatchKey
{
@@ -706,6 +710,7 @@ public:
struct FFamilyStats {uint64 Count=0,NearZero=0;double Sum=0.0,SumSq=0.0;};
std::unordered_map<FPatchKey,FPatchStats,FPatchHash> Patches;
std::array<FFamilyStats,3> Families{};
FFamilyStats PassageWalls,OrdinaryCaveWalls;
for(size_t Line=0;Line<static_cast<size_t>(Size[0])*Size[1];++Line)
{
const int32 X=Min[0]+static_cast<int32>(Line%Size[0]);
@@ -721,16 +726,23 @@ public:
const int32 Z=Min[2]+static_cast<int32>(Zi);
ESurfaceFamily Family=ESurfaceFamily::Strata;float SurfaceSDF=100000.0f;
bool bFloorSurface=false;float CaveInfluence=0.0f,FloorInfluence=0.0f;
float PassageInfluence=0.0f;
const float Raw=EffectiveRockDistance(X,Y,Z,&Family,&SurfaceSDF,
&bFloorSurface,&CaveInfluence,&FloorInfluence);
&bFloorSurface,&CaveInfluence,&FloorInfluence,nullptr,nullptr,false,
&PassageInfluence);
if(std::abs(Raw)>=0.5f)continue;
const float Fade=DetailBandFadeAt(X,Y,Z,Raw,SurfaceSDF,
CaveInfluence,FloorInfluence);
const float Detail=Fade>0.0f
?DetailNoise(X,Y,Z,SurfaceSDF,CaveInfluence,FloorInfluence)*Fade:0.0f;
?DetailNoise(X,Y,Z,SurfaceSDF,CaveInfluence,FloorInfluence,
PassageInfluence)*Fade:0.0f;
const size_t FamilyIndex=static_cast<size_t>(Family);
FFamilyStats& F=Families[FamilyIndex];++F.Count;F.Sum+=Detail;F.SumSq+=Detail*Detail;
if(std::abs(Detail)<0.05f)++F.NearZero;
if(PassageInfluence>=0.5f)
{++PassageWalls.Count;PassageWalls.Sum+=Detail;PassageWalls.SumSq+=Detail*Detail;}
else if(Family==ESurfaceFamily::Cave&&PassageInfluence<0.1f)
{++OrdinaryCaveWalls.Count;OrdinaryCaveWalls.Sum+=Detail;OrdinaryCaveWalls.SumSq+=Detail*Detail;}
const FPatchKey Key{FloorDiv(X,16),FloorDiv(Y,16),FloorDiv(Z,16),
static_cast<uint8>(FamilyIndex)};
FPatchStats& P=Patches[Key];++P.Count;P.Sum+=Detail;P.SumSq+=Detail*Detail;
@@ -769,7 +781,23 @@ public:
std::printf("[FlatPatchAudit] patch_width=16 vox min_patch_samples=16 flat_stddev_lt=0.10 flat_share=%.1f%% largest_flat_patch=%llu status=%s\n",
FlatShare,static_cast<unsigned long long>(LargestFlatPatch),
Tested>0&&FlatShare<20.0?"PASS":"FAIL");
return Tested>0&&FlatShare<20.0&&bPass;
const double PassageRms=PassageWalls.Count
?std::sqrt(PassageWalls.SumSq/PassageWalls.Count):0.0;
const double OrdinaryCaveRms=OrdinaryCaveWalls.Count
?std::sqrt(OrdinaryCaveWalls.SumSq/OrdinaryCaveWalls.Count):0.0;
const double PassageRmsRatio=OrdinaryCaveRms>1.0e-9
?PassageRms/OrdinaryCaveRms:0.0;
const bool bHasPassageSamples=PassageWalls.Count>0;
const bool bRatioPass=PassageWalls.Count>=32&&OrdinaryCaveWalls.Count>=32
&&PassageRmsRatio>=0.75&&PassageRmsRatio<=1.25;
const bool bPassageDetail=bPassageOnly?bRatioPass:(!bHasPassageSamples||bRatioPass);
const char* PassageStatus=!bHasPassageSamples
?(bPassageOnly?"FAIL":"SKIP"):(bPassageDetail?"PASS":"FAIL");
std::printf("[PassageWallDetailAudit] passage_samples=%llu passage_rms=%.4f cave_samples=%llu cave_rms=%.4f ratio=%.3f range=(0.750,1.250) status=%s\n",
static_cast<unsigned long long>(PassageWalls.Count),PassageRms,
static_cast<unsigned long long>(OrdinaryCaveWalls.Count),OrdinaryCaveRms,
PassageRmsRatio,PassageStatus);
return bPassageOnly?bPassageDetail:(Tested>0&&FlatShare<20.0&&bPass&&bPassageDetail);
}
bool AuditViewSurface(double CameraX,double CameraY,double CameraZ,
@@ -788,12 +816,14 @@ public:
const double OX=CameraX*4.0,OY=CameraY*4.0,OZ=CameraZ*4.0;
auto Distance=[&](double X,double Y,double Z,ESurfaceFamily* OutFamily=nullptr,
float* OutRaw=nullptr,float* OutDetail=nullptr,
bool* OutFloorSurface=nullptr)
bool* OutFloorSurface=nullptr,float* OutPassageInfluence=nullptr)
{
ESurfaceFamily Family=ESurfaceFamily::Strata;float SurfaceSDF=100000.0f;
bool bFloorSurface=false;float CaveInfluence=0.0f,FloorInfluence=0.0f;
float PassageInfluence=0.0f;
float D=EffectiveRockDistance(X,Y,Z,&Family,&SurfaceSDF,
&bFloorSurface,&CaveInfluence,&FloorInfluence);
&bFloorSurface,&CaveInfluence,&FloorInfluence,nullptr,nullptr,false,
&PassageInfluence);
float Detail=0.0f;
const bool bInside=X>=Min[0]&&X<=Max[0]&&Y>=Min[1]&&Y<=Max[1]
&&Z>=Min[2]&&Z<=Max[2];
@@ -802,13 +832,15 @@ public:
{
const float Fade=DetailBandFadeAt(X,Y,Z,D,SurfaceSDF,CaveInfluence,FloorInfluence);
if(Fade>0.0f)
{Detail=DetailNoise(X,Y,Z,SurfaceSDF,CaveInfluence,FloorInfluence)*Fade;D+=Detail;}
{Detail=DetailNoise(X,Y,Z,SurfaceSDF,CaveInfluence,FloorInfluence,
PassageInfluence)*Fade;D+=Detail;}
}
if(bCriticalAir)D=std::min(D,-1.0f/16.0f);
if(OutFamily)*OutFamily=Family;
if(OutRaw)*OutRaw=D-Detail;
if(OutDetail)*OutDetail=Detail;
if(OutFloorSurface)*OutFloorSurface=bFloorSurface;
if(OutPassageInfluence)*OutPassageInfluence=PassageInfluence;
return D;
};
uint64 TotalHits=0,TotalAxisLocked=0,TotalNearZero=0,FloorTaggedHits=0,FloorAxisLocked=0;
@@ -842,8 +874,8 @@ public:
PrimaryHitT=HitT;
const double XH=OX+DX*HitT,YH=OY+DY*HitT,ZH=OZ+DZ*HitT;
ESurfaceFamily Family=ESurfaceFamily::Strata;float Raw=0.0f,Detail=0.0f;
bool bFloorSurface=false;
Distance(XH,YH,ZH,&Family,&Raw,&Detail,&bFloorSurface);
bool bFloorSurface=false;float PassageInfluence=0.0f;
Distance(XH,YH,ZH,&Family,&Raw,&Detail,&bFloorSurface,&PassageInfluence);
const double GX=Distance(XH+0.5,YH,ZH)-Distance(XH-0.5,YH,ZH);
const double GY=Distance(XH,YH+0.5,ZH)-Distance(XH,YH-0.5,ZH);
const double GZ=Distance(XH,YH,ZH+0.5)-Distance(XH,YH,ZH-0.5);
@@ -897,8 +929,8 @@ public:
{
const char* Name=Family==ESurfaceFamily::Strata?"strata":
Family==ESurfaceFamily::Cave?"cave":"solid_overlay";
std::printf("[SurfaceRay] t=%.2f vox hit=(%.2f,%.2f,%.2f) family=%s floor_surface=%s raw_sdf=%.4f detail=%.4f axis_dot=%.4f\n",
HitT,XH,YH,ZH,Name,bFloorSurface?"yes":"no",Raw,Detail,AxisDot);
std::printf("[SurfaceRay] t=%.2f vox hit=(%.2f,%.2f,%.2f) family=%s floor_surface=%s passage_influence=%.3f raw_sdf=%.4f detail=%.4f axis_dot=%.4f\n",
HitT,XH,YH,ZH,Name,bFloorSurface?"yes":"no",PassageInfluence,Raw,Detail,AxisDot);
}
bFound=true;break;
}
@@ -1872,6 +1904,7 @@ private:
const double CoreExtendStart=I>0?CoreExtension:0.0,CoreExtendEnd=I+2<Points.Num()?CoreExtension:0.0;
AddTaperedCapsule(Points[I],Points[I+1],RadiusA,RadiusB,true,false,true,ZA,ZB,
ExtendStart,ExtendEnd);
Primitives.back().bPassageSurface=true;
SetCurvedFloorClip(Primitives.back(),Points[I],Points[I+1],ZA,ZB,
FloorTangents[static_cast<size_t>(I)],FloorTangents[static_cast<size_t>(I+1)]);
++Stats.CurvedFloorSegments;
@@ -1929,7 +1962,11 @@ private:
}
}
}
else AddCapsule(P.UpperPoint,P.LowerPoint,std::max(6.0f,P.Radius),true,true);
else
{
AddCapsule(P.UpperPoint,P.LowerPoint,std::max(6.0f,P.Radius),true,true);
Primitives.back().bPassageSurface=true;
}
AddLanding(P.UpperLanding,true);
AddLanding(P.LowerLanding,true);
}
@@ -1955,8 +1992,8 @@ private:
AddEllipsoid(Center,{2.5,2.5,HalfZ},{1,0,0},{0,1,0},{0,0,1},true);
for(size_t I=Before;I<Primitives.size();++I)Primitives[I].bCritical=true;
}
const FVector Floor(Center.X,Center.Y,L.FloorZ-1.25);
AddEllipsoid(Floor,{Width,Width,1.25},{1,0,0},{0,1,0},{0,0,1},false);
// The rounded landing carve and native floor already provide support.
// A shallow positive ellipsoid under this floor creates a broad shaft/floor plate.
}
void BuildRoundTunnelPrimitives()
@@ -2637,6 +2674,7 @@ private:
const float SurfaceSDF=Sample.SurfaceSDF;
const float CaveInfluence=Sample.CaveInfluence;
const float FloorInfluence=Sample.FloorInfluence;
const float PassageInfluence=Sample.PassageInfluence;
const bool bCriticalAir=Sample.bCriticalAir;
float DetailFade=DetailBandFade(SDF);
float MacroValue=0.0f;
@@ -2662,7 +2700,7 @@ private:
{
if(bProfile)++Profile.DetailEvaluations;
Displaced+=DetailNoiseOnLine(X,Y,Z,Sample.SurfaceSDF,
CaveInfluence,FloorInfluence,NoiseLine,bTimeDetail?&Profile:nullptr,
CaveInfluence,FloorInfluence,PassageInfluence,NoiseLine,bTimeDetail?&Profile:nullptr,
DetailField,bDetailFieldKnown,bMacroKnown,MacroValue)*DetailFade;
}
if(bTimeDetail)
@@ -2906,12 +2944,14 @@ private:
float* OutFloorInfluence=nullptr,
bool* OutCriticalAir=nullptr,
const FBinItems* KnownBinItems=nullptr,
bool bKnownBin=false) const
bool bKnownBin=false,
float* OutPassageInfluence=nullptr) const
{
const float Base=StrataDistance(Z);
float Cave=100000.0f;
float Overlay=-100000.0f;
float CaveFloorInfluence=0.0f;
float CavePassageInfluence=0.0f;
bool bCriticalAir=false;
const FBinItems* BinItems=KnownBinItems;
if(!bKnownBin)
@@ -2949,6 +2989,9 @@ private:
const float PrimitiveWeight=SmoothUnit(0.5f+(Cave-Distance)/(2.0f*MetadataWidth));
const float Combined=SmoothMinDistance(Cave,Distance,static_cast<float>(P.BlendRadius));
CaveFloorInfluence=std::lerp(CaveFloorInfluence,PrimitiveFloorInfluence,PrimitiveWeight);
if(OutPassageInfluence&&(CavePassageInfluence>0.0f||P.bPassageSurface))
CavePassageInfluence=std::lerp(CavePassageInfluence,
P.bPassageSurface?1.0f:0.0f,PrimitiveWeight);
Cave=Combined;
}
else if(X>=P.Min[0]&&X<=P.Max[0]&&Y>=P.Min[1]&&Y<=P.Max[1]
@@ -2965,6 +3008,7 @@ private:
const float CarveInfluence=SmoothUnit(0.5f+(Base-CarveOrOverlay)/(2.0f*FamilyBlendWidth));
const float CaveInfluence=CarveInfluence*CaveVsOverlay;
const float FloorInfluence=CaveInfluence*CaveFloorInfluence;
const float PassageInfluence=CaveInfluence*CavePassageInfluence;
const float RockDistance=SmoothMinDistance(Base,CarveOrOverlay,StrataCaveBlendRadius);
if(OutFamily)
*OutFamily=Family;
@@ -2973,6 +3017,7 @@ private:
(Family==ESurfaceFamily::Cave?Cave:Overlay);
if(OutCaveInfluence)*OutCaveInfluence=CaveInfluence;
if(OutFloorInfluence)*OutFloorInfluence=FloorInfluence;
if(OutPassageInfluence)*OutPassageInfluence=PassageInfluence;
if(OutFloorSurface)*OutFloorSurface=FloorInfluence>=0.5f;
return RockDistance;
}
@@ -2983,6 +3028,7 @@ private:
float SurfaceSDF=0.0f;
float CaveInfluence=0.0f;
float FloorInfluence=0.0f;
float PassageInfluence=0.0f;
ESurfaceFamily Family=ESurfaceFamily::Strata;
bool bFloorSurface=false;
bool bCriticalAir=false;
@@ -3085,7 +3131,7 @@ private:
void EffectiveRockDistanceZ8(int32 X,int32 Y,const int32 Z[8],int32 Count,
const FBinItems* BinItems,FEffectiveRockSample Out[8]) const
{
float Base[8],Cave[8],Overlay[8],CaveFloorInfluence[8];
float Base[8],Cave[8],Overlay[8],CaveFloorInfluence[8],CavePassageInfluence[8];
bool CriticalAir[8]{};
for(int32 Lane=0;Lane<Count;++Lane)
{
@@ -3093,6 +3139,7 @@ private:
Cave[Lane]=100000.0f;
Overlay[Lane]=-100000.0f;
CaveFloorInfluence[Lane]=0.0f;
CavePassageInfluence[Lane]=0.0f;
}
if(BinItems)
{
@@ -3158,6 +3205,9 @@ private:
static_cast<float>(P.BlendRadius));
CaveFloorInfluence[Lane]=std::lerp(CaveFloorInfluence[Lane],
PrimitiveFloorInfluence,PrimitiveWeight);
if(CavePassageInfluence[Lane]>0.0f||P.bPassageSurface)
CavePassageInfluence[Lane]=std::lerp(CavePassageInfluence[Lane],
P.bPassageSurface?1.0f:0.0f,PrimitiveWeight);
Cave[Lane]=Combined;
}
}
@@ -3180,12 +3230,14 @@ private:
+(Base[Lane]-CarveOrOverlay)/(2.0f*FamilyBlendWidth));
const float CaveInfluence=CarveInfluence*CaveVsOverlay;
const float FloorInfluence=CaveInfluence*CaveFloorInfluence[Lane];
const float PassageInfluence=CaveInfluence*CavePassageInfluence[Lane];
Out[Lane].Distance=SmoothMinDistance(Base[Lane],CarveOrOverlay,StrataCaveBlendRadius);
Out[Lane].Family=Family;
Out[Lane].SurfaceSDF=Family==ESurfaceFamily::Strata?Base[Lane]:
(Family==ESurfaceFamily::Cave?Cave[Lane]:Overlay[Lane]);
Out[Lane].CaveInfluence=CaveInfluence;
Out[Lane].FloorInfluence=FloorInfluence;
Out[Lane].PassageInfluence=PassageInfluence;
Out[Lane].bFloorSurface=FloorInfluence>=0.5f;
Out[Lane].bCriticalAir=CriticalAir[Lane];
}
@@ -3257,27 +3309,29 @@ private:
{
const uint32 Seed=static_cast<uint32>(Owner->Seed);
const float RF=Params.RoughnessFrequency;
const float NoiseX=static_cast<float>(X);
const float NoiseY=static_cast<float>(Y);
const float EffectiveZ=(Params.VerticalScale>0.0f&&Params.VerticalScale!=1.0f)
?static_cast<float>(Z)/Params.VerticalScale:static_cast<float>(Z);
FVector3f Main(static_cast<float>(X)*RF+VoxelHash::SeedOffset(Seed,11.3f),
static_cast<float>(Y)*RF+VoxelHash::SeedOffset(Seed,13.7f),
FVector3f Main(NoiseX*RF+VoxelHash::SeedOffset(Seed,11.3f),
NoiseY*RF+VoxelHash::SeedOffset(Seed,13.7f),
EffectiveZ*RF+VoxelHash::SeedOffset(Seed,17.1f));
FVector3f Fine(static_cast<float>(X)*RF*3.0f+VoxelHash::SeedOffset(Seed,19.1f)+2000.0f,
static_cast<float>(Y)*RF*3.0f+VoxelHash::SeedOffset(Seed,23.7f)+2500.0f,
FVector3f Fine(NoiseX*RF*3.0f+VoxelHash::SeedOffset(Seed,19.1f)+2000.0f,
NoiseY*RF*3.0f+VoxelHash::SeedOffset(Seed,23.7f)+2500.0f,
EffectiveZ*RF*3.0f+VoxelHash::SeedOffset(Seed,29.3f)+3000.0f);
if(Params.DomainWarpStrength>0.0f)
{
const float WF=Params.DomainWarpFrequency,WS=Params.DomainWarpStrength;
float WX=0.0f,WY=0.0f,WZ=0.0f;
VoxelNoise::Perlin3D_x3(
static_cast<float>(X)*WF+VoxelHash::SeedOffset(Seed,5.2f),
static_cast<float>(Y)*WF+VoxelHash::SeedOffset(Seed,1.3f),
NoiseX*WF+VoxelHash::SeedOffset(Seed,5.2f),
NoiseY*WF+VoxelHash::SeedOffset(Seed,1.3f),
EffectiveZ*WF+VoxelHash::SeedOffset(Seed,9.7f),
static_cast<float>(X)*WF+100.0f+VoxelHash::SeedOffset(Seed,7.7f),
static_cast<float>(Y)*WF+200.0f+VoxelHash::SeedOffset(Seed,3.1f),
NoiseX*WF+100.0f+VoxelHash::SeedOffset(Seed,7.7f),
NoiseY*WF+200.0f+VoxelHash::SeedOffset(Seed,3.1f),
EffectiveZ*WF+300.0f,
static_cast<float>(X)*WF+400.0f,
static_cast<float>(Y)*WF+500.0f+VoxelHash::SeedOffset(Seed,11.9f),
NoiseX*WF+400.0f,
NoiseY*WF+500.0f+VoxelHash::SeedOffset(Seed,11.9f),
EffectiveZ*WF+600.0f+VoxelHash::SeedOffset(Seed,13.3f),WX,WY,WZ);
WX*=VOXEL_NOISE_SCALE*WS;WY*=VOXEL_NOISE_SCALE*WS;WZ*=VOXEL_NOISE_SCALE*WS;
Main+=FVector3f(WX,WY,WZ);Fine+=FVector3f(WX,WY,WZ);
@@ -3320,18 +3374,21 @@ private:
float OwnerCaveRoughness(double X,double Y,double Z,float SurfaceSDF,
const FLayerField& Field,float CaveInfluence,
FOwnerNoiseLineContext& LineContext,
FDetailWorkerProfile* Profile=nullptr) const
FDetailWorkerProfile* Profile=nullptr,
int32 AnchorStep=8) const
{
const FStrateGenerationParams& Params=Field.Params;
const float Depth=Params.SurfaceRoughness*2.0f;
if(!(Depth>0.0f)||std::abs(SurfaceSDF)>=Depth||!(Params.RoughnessFrequency>0.0f))return 0.0f;
if(Profile)++Profile->OwnerRoughnessActiveCalls;
constexpr int32 ZStep=8;
const int32 ZStep=std::max(1,AnchorStep);
const int32 GridZ0=static_cast<int32>(std::floor(Z/static_cast<double>(ZStep)))*ZStep;
const int32 SampleZ0=std::max(GridZ0,Field.Lo);
const int32 SampleZ1=std::min(GridZ0+ZStep,Field.Hi);
float Total=0.0f;
if(SampleZ1>SampleZ0)
if(ZStep==1)
Total=OwnerCaveRoughnessCore(X,Y,Z,Params);
else if(SampleZ1>SampleZ0)
{
const bool bCacheHit=LineContext.Field==&Field&&LineContext.GridZ0==GridZ0;
if(Profile)
@@ -3357,6 +3414,33 @@ private:
return Total*Fade*Fade;
}
float OwnerCaveRoughnessForDetail(double X,double Y,double Z,float SurfaceSDF,
const FLayerField& Field,float CaveInfluence,
float PassageInfluence,
FOwnerNoiseLineContext& LineContext,
FDetailWorkerProfile* Profile=nullptr) const
{
constexpr float DirectStart=0.40f,DirectEnd=0.60f;
constexpr int32 PassageAnchorStep=2;
const float PassageWeight=std::clamp(PassageInfluence,0.0f,1.0f);
if(PassageWeight>=DirectEnd)
return OwnerCaveRoughness(X,Y,Z,SurfaceSDF,Field,CaveInfluence,
LineContext,Profile,PassageAnchorStep);
const float Anchored=OwnerCaveRoughness(X,Y,Z,SurfaceSDF,Field,
CaveInfluence,LineContext,Profile);
if(PassageWeight<=DirectStart)return Anchored;
const float Direct=OwnerCaveRoughness(X,Y,Z,SurfaceSDF,Field,
CaveInfluence,LineContext,Profile,PassageAnchorStep);
const float DirectWeight=SmoothUnit((PassageWeight-DirectStart)
/(DirectEnd-DirectStart));
const float AnchoredWeight=1.0f-DirectWeight;
const float Normalization=1.0f/std::sqrt(
AnchoredWeight*AnchoredWeight+DirectWeight*DirectWeight);
return (AnchoredWeight*Anchored+DirectWeight*Direct)*Normalization;
}
static float SurfaceRelief(float X,float Y,float Z,uint32 Seed)
{
// The low band carries the broad rock shapes and also gently varies mid-band
@@ -3442,27 +3526,31 @@ private:
};
float DetailNoise(double X,double Y,double Z,float SurfaceSDF,
float CaveInfluence,float FloorInfluence) const
float CaveInfluence,float FloorInfluence,float PassageInfluence) const
{
if(DetailVariant==EDetailVariant::Smooth)return 0.0f;
if(DetailVariant==EDetailVariant::PerVoxel)
{
const int32 IX=static_cast<int32>(std::floor(X)),IY=static_cast<int32>(std::floor(Y)),IZ=static_cast<int32>(std::floor(Z));
return FStandaloneResearchTunnels::NoiseValue(IX,IY,IZ,static_cast<uint32>(Owner->Seed))*DetailSupremum;
return FStandaloneResearchTunnels::NoiseValue(IX,IY,IZ,static_cast<uint32>(Owner->Seed))
*DetailSupremum;
}
const float Relief=SurfaceRelief(static_cast<float>(X),
static_cast<float>(Y),static_cast<float>(Z),static_cast<uint32>(Owner->Seed));
const float Relief=SurfaceRelief(static_cast<float>(X),static_cast<float>(Y),
static_cast<float>(Z),static_cast<uint32>(Owner->Seed));
const float PassageWeight=std::clamp(PassageInfluence,0.0f,1.0f);
const FLayerField* Field=FindLayerField(Z);
FOwnerNoiseLineContext OwnerNoise;
const float OwnerRelief=Field?OwnerCaveRoughness(X,Y,Z,SurfaceSDF,*Field,
CaveInfluence,OwnerNoise):0.0f;
float OwnerRelief=0.0f;
if(Field)
OwnerRelief=OwnerCaveRoughnessForDetail(X,Y,Z,SurfaceSDF,*Field,
CaveInfluence,PassageWeight,OwnerNoise);
const float Contrast=1.35f-0.80f*std::clamp(CaveInfluence,0.0f,1.0f)
+1.85f*std::clamp(FloorInfluence,0.0f,1.0f);
return std::clamp((Relief+OwnerRelief*0.5f)*Contrast,-3.9f,3.9f);
}
float DetailNoiseOnLine(double X,double Y,double Z,float SurfaceSDF,
float CaveInfluence,float FloorInfluence,
float CaveInfluence,float FloorInfluence,float PassageInfluence,
FDetailNoiseLineContext& NoiseLine,
FDetailWorkerProfile* Profile=nullptr,
const FLayerField* KnownField=nullptr,
@@ -3470,10 +3558,11 @@ private:
float KnownMacro=0.0f) const
{
if(DetailVariant!=EDetailVariant::Coherent)
return DetailNoise(X,Y,Z,SurfaceSDF,CaveInfluence,FloorInfluence);
return DetailNoise(X,Y,Z,SurfaceSDF,CaveInfluence,FloorInfluence,PassageInfluence);
using Clock=std::chrono::steady_clock;
const auto ReliefStart=Profile?Clock::now():Clock::time_point{};
const float Relief=NoiseLine.SurfaceReliefAt(static_cast<float>(Z),bMacroKnown,KnownMacro);
const float Relief=NoiseLine.SurfaceReliefAt(static_cast<float>(Z),
bMacroKnown,KnownMacro);
if(Profile)
Profile->ReliefSampleNanoseconds+=static_cast<uint64>(
std::chrono::duration_cast<std::chrono::nanoseconds>(Clock::now()-ReliefStart).count());
@@ -3484,8 +3573,11 @@ private:
std::chrono::duration_cast<std::chrono::nanoseconds>(Clock::now()-LookupStart).count());
const auto OwnerStart=Profile?Clock::now():Clock::time_point{};
if(Profile&&Field)++Profile->OwnerRoughnessFieldCalls;
const float OwnerRelief=Field?OwnerCaveRoughness(X,Y,Z,SurfaceSDF,*Field,
CaveInfluence,NoiseLine.OwnerNoise,Profile):0.0f;
const float PassageWeight=std::clamp(PassageInfluence,0.0f,1.0f);
float OwnerRelief=0.0f;
if(Field)
OwnerRelief=OwnerCaveRoughnessForDetail(X,Y,Z,SurfaceSDF,*Field,
CaveInfluence,PassageWeight,NoiseLine.OwnerNoise,Profile);
if(Profile)
Profile->OwnerRoughnessSampleNanoseconds+=static_cast<uint64>(
std::chrono::duration_cast<std::chrono::nanoseconds>(Clock::now()-OwnerStart).count());
@@ -3498,15 +3590,18 @@ private:
{
ESurfaceFamily SurfaceFamily=ESurfaceFamily::Strata;float SurfaceSDF=100000.0f;
bool bFloorSurface=false,bCriticalAir=false;float CaveInfluence=0.0f,FloorInfluence=0.0f;
float PassageInfluence=0.0f;
float RockDistance=EffectiveRockDistance(X,Y,Z,&SurfaceFamily,&SurfaceSDF,
&bFloorSurface,&CaveInfluence,&FloorInfluence,&bCriticalAir);
&bFloorSurface,&CaveInfluence,&FloorInfluence,&bCriticalAir,nullptr,false,
&PassageInfluence);
const bool bInsideFine=X>=Min[0]&&X<=Max[0]&&Y>=Min[1]&&Y<=Max[1]&&Z>=Min[2]&&Z<=Max[2];
if(bInsideFine&&DetailVariant!=EDetailVariant::Smooth
&&std::abs(RockDistance)<=DetailSupremum+0.125f)
{
const float Fade=DetailBandFadeAt(X,Y,Z,RockDistance,SurfaceSDF,
CaveInfluence,FloorInfluence);
if(Fade>0.0f)RockDistance+=DetailNoise(X,Y,Z,SurfaceSDF,CaveInfluence,FloorInfluence)*Fade;
if(Fade>0.0f)RockDistance+=DetailNoise(X,Y,Z,SurfaceSDF,CaveInfluence,
FloorInfluence,PassageInfluence)*Fade;
}
if(bCriticalAir)RockDistance=std::min(RockDistance,-1.0f/16.0f);
return RockDistance>=0.0f;