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:
1 parent
2656d81ac9
commit
631dd57eb4
14 files changed
+552
-48
No files matched your search
@@ -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;
|
||||
|
||||
@@ -2366,6 +2366,7 @@ int main(int Argc,char** Argv)
|
||||
bool bStreamBenchmark=false;
|
||||
bool bStreamPipeline=false;
|
||||
bool bProfileDetailBand=false;
|
||||
bool bPassageDetailAuditOnly=false;
|
||||
bool bShardAudit=false;
|
||||
bool bFarSurvivalAudit=false;
|
||||
bool bFarAuditBadShell=false;
|
||||
@@ -2389,6 +2390,8 @@ int main(int Argc,char** Argv)
|
||||
else if(Arg=="--density-hash")App.bDensityHash=true;
|
||||
else if(Arg=="--shape-world")App.bShapeWorld=true;
|
||||
else if(Arg=="--shape-audit")App.bShapeWorld=true,App.bShapeAuditOnly=true;
|
||||
else if(Arg=="--passage-wall-detail-audit")
|
||||
{App.bShapeWorld=true;App.bShapeAuditOnly=true;bPassageDetailAuditOnly=true;}
|
||||
else if(Arg=="--shape-compare")App.bShapeWorld=true,App.bShapeCompare=true;
|
||||
else if(Arg.starts_with("--shape-compare-level="))
|
||||
ShapeCompareLevel=std::atoi(std::string(Arg.substr(std::string_view("--shape-compare-level=").size())).c_str());
|
||||
@@ -2496,6 +2499,8 @@ int main(int Argc,char** Argv)
|
||||
{std::fprintf(stderr,"Shape interval build failed: %s\n",Error.c_str());return 2;}
|
||||
if(App.bShapeAuditOnly)
|
||||
{
|
||||
if(bPassageDetailAuditOnly)
|
||||
return App.ShapeWorld->AuditSurfaceBandFamilies(true)?0:8;
|
||||
const bool bSurfacePassing=App.ShapeWorld->AuditViewSurface(App.Position.X,App.Position.Y,
|
||||
App.Position.Z,App.Yaw,App.Pitch);
|
||||
return App.ShapeWorld->IsDetailAuditPassing()&&bSurfacePassing?0:7;
|
||||
|
||||
Reference in new issue
Block a user