wip(assembler): round S3 -- far ground from the native heightfield; LOD7/8 tiles 36-66% cheaper
Far-shell repair (81-96% of S2's LOD7/8 tile time) is skipped for certified SurfaceWorld tiles; ground and cap come from the shared planar heightfield. Near LOD0-3 hashes equal S2; far recipe version 1 salts LOD5+ identities. Cold first view 6.6 -> 3.4 s (aim 1.57 s). Not a visual sign-off: distant cap shows floating pieces, sprint streaming arrives late. 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
6ddb834b1c
commit
d0f97bf79a
26 files changed
+976
-30
No files matched your search
@@ -311,7 +311,10 @@ inline void AppendFarConnectorShells(const FStandaloneShapeWorld& Shape,const FV
|
||||
if(TMin>TMax){bIntersects=false;break;}
|
||||
}
|
||||
if(!bIntersects||TMax-TMin<1.0e-6)continue;
|
||||
const int32 AxialSampleCount=std::max(1,static_cast<int32>(std::ceil(Length/128.0)));
|
||||
// LOD7 and LOD8 share a 256-voxel connector station grid; near LOD keeps 128-voxel checks.
|
||||
// LOD7 et LOD8 partagent des stations aux 256 voxels; pres du joueur, garder les pas de 128.
|
||||
const double ConnectorStationStep=Key.Level>=7?std::max(256.0,static_cast<double>(Step)):128.0;
|
||||
const int32 AxialSampleCount=std::max(1,static_cast<int32>(std::ceil(Length/ConnectorStationStep)));
|
||||
std::vector<uint8> MissingMasks(static_cast<size_t>(AxialSampleCount),0);
|
||||
std::vector<std::array<double,4>> SourceRadii(static_cast<size_t>(AxialSampleCount));
|
||||
for(auto& Radii:SourceRadii)Radii.fill(0.0);
|
||||
@@ -429,7 +432,7 @@ inline void AppendFarConnectorShells(const FStandaloneShapeWorld& Shape,const FV
|
||||
}
|
||||
}
|
||||
std::vector<FRing> Rings;
|
||||
const double MaxRingStep=128.0;
|
||||
const double MaxRingStep=Key.Level>=7?std::max(256.0,static_cast<double>(Step)):128.0;
|
||||
double CurrentT=RunMin;
|
||||
Rings.push_back(MakeRing(CurrentT,RunStart,RunEnd,RunRadiusMask));
|
||||
while(CurrentT<RunMax-1.0e-7)
|
||||
@@ -901,6 +904,67 @@ inline std::vector<double> FindFarStratumCrossings(const FStandaloneShapeWorld&
|
||||
return Crossings;
|
||||
}
|
||||
|
||||
inline bool FindNearestFarStratumCrossing(const FStandaloneShapeWorld& Shape,
|
||||
double X,double Y,double ZMin,double ZMax,double Prediction,double& OutCrossing)
|
||||
{
|
||||
if(ZMax<=ZMin||!std::isfinite(Prediction))return false;
|
||||
const int32 Center=std::clamp(static_cast<int32>(std::floor(Prediction)),
|
||||
static_cast<int32>(std::ceil(ZMin)),static_cast<int32>(std::floor(ZMax)));
|
||||
double PreviousLeft=Center,PreviousRight=Center;
|
||||
bool PreviousLeftSolid=Shape.DensityAt(static_cast<float>(X),static_cast<float>(Y),
|
||||
static_cast<float>(PreviousLeft))<0.0f;
|
||||
bool PreviousRightSolid=PreviousLeftSolid;
|
||||
const int32 MaximumRadius=std::max(Center-static_cast<int32>(std::floor(ZMin)),
|
||||
static_cast<int32>(std::ceil(ZMax))-Center)+1;
|
||||
for(int32 Radius=1;Radius<=MaximumRadius;++Radius)
|
||||
{
|
||||
bool bFound=false;
|
||||
double Best=0.0,BestDistance=std::numeric_limits<double>::infinity();
|
||||
const auto CheckBracket=[&](double A,double B,bool ASolid)
|
||||
{
|
||||
double Lo=std::min(A,B),Hi=std::max(A,B);
|
||||
for(int32 I=0;I<6;++I)
|
||||
{
|
||||
const double Mid=(Lo+Hi)*0.5;
|
||||
if((Shape.DensityAt(static_cast<float>(X),static_cast<float>(Y),
|
||||
static_cast<float>(Mid))<0.0f)==ASolid)
|
||||
{
|
||||
if(A<B)Lo=Mid;else Hi=Mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(A<B)Hi=Mid;else Lo=Mid;
|
||||
}
|
||||
}
|
||||
const double Crossing=(Lo+Hi)*0.5;
|
||||
const double Difference=std::abs(Crossing-Prediction);
|
||||
if(Difference<BestDistance)
|
||||
{Best=Crossing;BestDistance=Difference;bFound=true;}
|
||||
};
|
||||
|
||||
const double Left=std::max(ZMin,static_cast<double>(Center-Radius));
|
||||
if(Left<PreviousLeft-1.0e-9)
|
||||
{
|
||||
const bool LeftSolid=Shape.DensityAt(static_cast<float>(X),static_cast<float>(Y),
|
||||
static_cast<float>(Left))<0.0f;
|
||||
if(LeftSolid!=PreviousLeftSolid)CheckBracket(Left,PreviousLeft,LeftSolid);
|
||||
PreviousLeft=Left;PreviousLeftSolid=LeftSolid;
|
||||
}
|
||||
const double Right=std::min(ZMax,static_cast<double>(Center+Radius));
|
||||
if(Right>PreviousRight+1.0e-9)
|
||||
{
|
||||
const bool RightSolid=Shape.DensityAt(static_cast<float>(X),static_cast<float>(Y),
|
||||
static_cast<float>(Right))<0.0f;
|
||||
if(RightSolid!=PreviousRightSolid)CheckBracket(PreviousRight,Right,PreviousRightSolid);
|
||||
PreviousRight=Right;PreviousRightSolid=RightSolid;
|
||||
}
|
||||
if(bFound)
|
||||
{OutCrossing=Best;return true;}
|
||||
if(Left<=ZMin+1.0e-9&&Right>=ZMax-1.0e-9)break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void AppendFarStratumShells(const FStandaloneOwnerWorld& World,const FStandaloneShapeWorld& Shape,
|
||||
const FVoxelTileKey& Key,int32 Step,FVoxelMeshData& Mesh)
|
||||
{
|
||||
@@ -992,12 +1056,9 @@ inline void AppendFarStratumShells(const FStandaloneOwnerWorld& World,const FSta
|
||||
Vertex.X=X0+(X1-X0)*static_cast<double>(PX)/PatchDivisions;
|
||||
Vertex.Y=Y0+(Y1-Y0)*static_cast<double>(PY)/PatchDivisions;
|
||||
const double PredictedZ=SurfaceZ(Vertex.X,Vertex.Y);
|
||||
const std::vector<double> Crossings=FindFarStratumCrossings(
|
||||
Shape,Vertex.X,Vertex.Y,ZMin,ZMax);
|
||||
if(Crossings.empty()){bValidPatch=false;break;}
|
||||
Vertex.Z=*std::min_element(Crossings.begin(),Crossings.end(),
|
||||
[PredictedZ](double A,double B)
|
||||
{return std::abs(A-PredictedZ)<std::abs(B-PredictedZ);});
|
||||
if(!FindNearestFarStratumCrossing(Shape,Vertex.X,Vertex.Y,
|
||||
ZMin,ZMax,PredictedZ,Vertex.Z))
|
||||
{bValidPatch=false;break;}
|
||||
const float VertexGX=Density(Vertex.X+2,Vertex.Y,Vertex.Z)
|
||||
-Density(Vertex.X-2,Vertex.Y,Vertex.Z);
|
||||
const float VertexGY=Density(Vertex.X,Vertex.Y+2,Vertex.Z)
|
||||
|
||||
Reference in new issue
Block a user