wip(L6, side branch): screen-space far gate; no-op cutoff removed; cost within noise vs L4

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ED33VnqepD4YY6gDAAA832
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-19 21:10:08 +02:00
1 parent b21a19d561
commit aa67bd31f5
13 files changed
+474 -615

No files matched your search

+272 -63
View File
@@ -22,6 +22,12 @@ namespace StandaloneScreenSpaceGate
int Lod=0;
std::uint64_t Samples=0,Missing=0,Floating=0;
double P50=0.0,P99=0.0,Maximum=0.0;
double VerticalP50=0.0,VerticalP99=0.0,VerticalMaximum=0.0;
double MaximumNormalDistanceMeters=0.0,MaximumX=0.0,MaximumY=0.0;
double MaximumReferenceZ=0.0,MaximumDisplayedZ=0.0;
double MaximumSlopeDegrees=0.0;
std::array<std::uint64_t,4> SlopeSamples{};
std::array<double,4> SlopeP99{},SlopeMaximum{};
bool Valid=false;
};
@@ -30,9 +36,128 @@ namespace StandaloneScreenSpaceGate
int CoarseLod=0;
std::uint64_t Samples=0,Cracks=0,Floating=0;
double P50=0.0,P99=0.0,Maximum=0.0;
double VerticalP50=0.0,VerticalP99=0.0,VerticalMaximum=0.0;
double MaximumNormalDistanceMeters=0.0,MaximumX=0.0,MaximumY=0.0;
double MaximumReferenceZ=0.0,MaximumDisplayedZ=0.0;
double MaximumSlopeDegrees=0.0;
std::array<std::uint64_t,4> SlopeSamples{};
std::array<double,4> SlopeP99{},SlopeMaximum{};
bool Valid=false;
};
struct FSurfaceRoot
{
double ZMeters=0.0;
double SlopeX=0.0;
double SlopeY=0.0;
};
struct FViewBasis
{
std::array<double,3> Right{};
std::array<double,3> Up{};
};
struct FErrorAccumulator
{
std::vector<double> Pixels,VerticalPixels;
std::array<std::vector<double>,4> BySlope;
double Maximum=-1.0,MaximumVertical=0.0,MaximumNormalDistanceMeters=0.0;
double MaximumX=0.0,MaximumY=0.0,MaximumSlopeDegrees=0.0;
double MaximumReferenceZ=0.0,MaximumDisplayedZ=0.0;
std::array<std::uint64_t,4> SlopeSamples{};
};
inline double Percentile(std::vector<double>& Values,double P);
inline FViewBasis MakeViewBasis(double YawDegrees,double PitchDegrees)
{
constexpr double Pi=3.14159265358979323846;
const double Yaw=YawDegrees*Pi/180.0,Pitch=PitchDegrees*Pi/180.0;
const std::array<double,3> Forward={std::sin(Yaw)*std::cos(Pitch),
std::cos(Yaw)*std::cos(Pitch),std::sin(Pitch)};
FViewBasis Basis;
Basis.Right={std::cos(Yaw),-std::sin(Yaw),0.0};
Basis.Up={Basis.Right[1]*Forward[2]-Basis.Right[2]*Forward[1],
Basis.Right[2]*Forward[0]-Basis.Right[0]*Forward[2],
Basis.Right[0]*Forward[1]-Basis.Right[1]*Forward[0]};
return Basis;
}
inline std::size_t SlopeBin(double Degrees)
{
if(Degrees<30.0)return 0;
if(Degrees<45.0)return 1;
if(Degrees<60.0)return 2;
return 3;
}
inline void AddError(FErrorAccumulator& Accumulator,double DeltaZMeters,
const FSurfaceRoot& Root,double PixelBudgetMeters,const FViewBasis& View,
double X,double Y)
{
constexpr double Pi=3.14159265358979323846;
const double GradientSquared=Root.SlopeX*Root.SlopeX+Root.SlopeY*Root.SlopeY;
const double NormalLength=std::sqrt(1.0+GradientSquared);
const double NormalX=-Root.SlopeX/NormalLength;
const double NormalY=-Root.SlopeY/NormalLength;
const double NormalZ=1.0/NormalLength;
const double NormalDistance=std::abs(DeltaZMeters)/NormalLength;
const double ProjectedNormal=std::hypot(
NormalX*View.Right[0]+NormalY*View.Right[1]+NormalZ*View.Right[2],
NormalX*View.Up[0]+NormalY*View.Up[1]+NormalZ*View.Up[2]);
const double ProjectedVertical=std::hypot(View.Right[2],View.Up[2]);
const double NormalPixels=NormalDistance*ProjectedNormal/PixelBudgetMeters;
const double VerticalPixels=std::abs(DeltaZMeters)*ProjectedVertical/PixelBudgetMeters;
const double SlopeDegrees=std::atan(std::sqrt(GradientSquared))*180.0/Pi;
Accumulator.Pixels.push_back(NormalPixels);
Accumulator.VerticalPixels.push_back(VerticalPixels);
const std::size_t Bin=SlopeBin(SlopeDegrees);
Accumulator.BySlope[Bin].push_back(NormalPixels);
++Accumulator.SlopeSamples[Bin];
if(NormalPixels>Accumulator.Maximum)
{
Accumulator.Maximum=NormalPixels;
Accumulator.MaximumVertical=VerticalPixels;
Accumulator.MaximumNormalDistanceMeters=NormalDistance;
Accumulator.MaximumX=X;Accumulator.MaximumY=Y;
Accumulator.MaximumSlopeDegrees=SlopeDegrees;
Accumulator.MaximumReferenceZ=Root.ZMeters;
Accumulator.MaximumDisplayedZ=Root.ZMeters+DeltaZMeters;
}
}
inline void AddMissing(FErrorAccumulator& Accumulator)
{
Accumulator.Pixels.push_back(2.0);
Accumulator.VerticalPixels.push_back(2.0);
}
inline void FinalizeError(FErrorRow& Row,FErrorAccumulator& Accumulator)
{
Row.Samples=Accumulator.Pixels.size();
Row.P50=Percentile(Accumulator.Pixels,0.50);
Row.P99=Percentile(Accumulator.Pixels,0.99);
Row.Maximum=Accumulator.Pixels.empty()?0.0
:*std::max_element(Accumulator.Pixels.begin(),Accumulator.Pixels.end());
Row.VerticalP50=Percentile(Accumulator.VerticalPixels,0.50);
Row.VerticalP99=Percentile(Accumulator.VerticalPixels,0.99);
Row.VerticalMaximum=Accumulator.VerticalPixels.empty()?0.0
:*std::max_element(Accumulator.VerticalPixels.begin(),Accumulator.VerticalPixels.end());
Row.MaximumNormalDistanceMeters=Accumulator.MaximumNormalDistanceMeters;
Row.MaximumX=Accumulator.MaximumX;Row.MaximumY=Accumulator.MaximumY;
Row.MaximumReferenceZ=Accumulator.MaximumReferenceZ;
Row.MaximumDisplayedZ=Accumulator.MaximumDisplayedZ;
Row.MaximumSlopeDegrees=Accumulator.MaximumSlopeDegrees;
Row.SlopeSamples=Accumulator.SlopeSamples;
for(std::size_t Bin=0;Bin<Accumulator.BySlope.size();++Bin)
{
Row.SlopeP99[Bin]=Percentile(Accumulator.BySlope[Bin],0.99);
Row.SlopeMaximum[Bin]=Accumulator.BySlope[Bin].empty()?0.0
:*std::max_element(Accumulator.BySlope[Bin].begin(),Accumulator.BySlope[Bin].end());
}
}
struct FHeightGrid
{
int Side=65;
@@ -162,38 +287,51 @@ namespace StandaloneScreenSpaceGate
return Grid;
}
inline std::vector<double> ExactHeightRoots(const FHeightGrid& Grid,int Ix,int Iy,
inline std::vector<FSurfaceRoot> ExactHeightRoots(const FHeightGrid& Grid,int Ix,int Iy,
const FVoxelTileKey& Patch,double VoxelMeters,
const VoxelForgeCore::WorldAssemblyManifest& Assembly)
{
std::vector<double> Roots;
std::vector<FSurfaceRoot> Roots;
const double XSubvoxels=Grid.X(Ix)/VoxelMeters*256.0;
const double YSubvoxels=Grid.Y(Iy)/VoxelMeters*256.0;
const auto X=static_cast<std::int64_t>(std::llround(XSubvoxels));
const auto Y=static_cast<std::int64_t>(std::llround(YSubvoxels));
const double MinZ=static_cast<double>(Patch.OriginVoxels().Z);
const double MaxZ=MinZ+Patch.ExtentVoxels();
constexpr std::int64_t NormalProbeSubvoxels=256;
for(const auto& Plan:Assembly.plan.strates)
{
VoxelForgeCore::Heightfield2D Field(Assembly.recipe,Plan);
if(!Field.isValid())continue;
const auto Column=Field.point(static_cast<std::int64_t>(std::llround(XSubvoxels)),
static_cast<std::int64_t>(std::llround(YSubvoxels)),0);
const auto Column=Field.point(X,Y,0);
if(Column.groundHeightSubvoxels>=Column.capHeightSubvoxels)continue;
const double Ground=static_cast<double>(Column.groundHeightSubvoxels)/(256.0)*VoxelMeters;
const double Cap=static_cast<double>(Column.capHeightSubvoxels)/(256.0)*VoxelMeters;
const auto XMinus=Field.point(X-NormalProbeSubvoxels,Y,0);
const auto XPlus=Field.point(X+NormalProbeSubvoxels,Y,0);
const auto YMinus=Field.point(X,Y-NormalProbeSubvoxels,0);
const auto YPlus=Field.point(X,Y+NormalProbeSubvoxels,0);
const auto Slope=[&](std::int64_t Minus,std::int64_t Plus)
{return static_cast<double>(Plus-Minus)/(2.0*NormalProbeSubvoxels);};
const double Ground=static_cast<double>(Column.groundHeightSubvoxels)/256.0*VoxelMeters;
const double Cap=static_cast<double>(Column.capHeightSubvoxels)/256.0*VoxelMeters;
const double PlanMinZ=static_cast<double>(Plan.bottomChunkZ)*32.0*VoxelMeters;
const double PlanMaxZ=static_cast<double>(Plan.topChunkZ+1)*32.0*VoxelMeters;
if(Ground>=MinZ*VoxelMeters-0.25*VoxelMeters
&&Ground<=MaxZ*VoxelMeters+0.25*VoxelMeters
&&Ground>=PlanMinZ-0.25*VoxelMeters&&Ground<=PlanMaxZ+0.25*VoxelMeters)
Roots.push_back(Ground);
Roots.push_back({Ground,Slope(XMinus.groundHeightSubvoxels,
XPlus.groundHeightSubvoxels),Slope(YMinus.groundHeightSubvoxels,
YPlus.groundHeightSubvoxels)});
if(Cap>=MinZ*VoxelMeters-0.25*VoxelMeters
&&Cap<=MaxZ*VoxelMeters+0.25*VoxelMeters
&&Cap>=PlanMinZ-0.25*VoxelMeters&&Cap<=PlanMaxZ+0.25*VoxelMeters)
Roots.push_back(Cap);
Roots.push_back({Cap,Slope(XMinus.capHeightSubvoxels,
XPlus.capHeightSubvoxels),Slope(YMinus.capHeightSubvoxels,
YPlus.capHeightSubvoxels)});
}
std::sort(Roots.begin(),Roots.end());
Roots.erase(std::unique(Roots.begin(),Roots.end(),[](double A,double B)
{return std::abs(A-B)<0.01;}),Roots.end());
std::sort(Roots.begin(),Roots.end(),[](const FSurfaceRoot& A,const FSurfaceRoot& B)
{return A.ZMeters<B.ZMeters;});
Roots.erase(std::unique(Roots.begin(),Roots.end(),[](const FSurfaceRoot& A,
const FSurfaceRoot& B){return std::abs(A.ZMeters-B.ZMeters)<0.01;}),Roots.end());
return Roots;
}
@@ -213,75 +351,87 @@ namespace StandaloneScreenSpaceGate
inline FErrorRow CompareToExact(const FHeightGrid& MeshGrid,const FVoxelTileKey& Patch,
double VoxelMeters,double PixelBudgetMeters,
const VoxelForgeCore::WorldAssemblyManifest& Assembly)
const VoxelForgeCore::WorldAssemblyManifest& Assembly,const FViewBasis& View)
{
FErrorRow Row;Row.Lod=Patch.Level;Row.Valid=true;
std::vector<double> Errors;
FErrorAccumulator Accumulator;
for(int Iy=0;Iy<MeshGrid.Side;++Iy)
for(int Ix=0;Ix<MeshGrid.Side;++Ix)
{
const auto Roots=ExactHeightRoots(MeshGrid,Ix,Iy,Patch,VoxelMeters,Assembly);
if(Roots.empty()&&MeshGrid.At(Ix,Iy).empty())continue;
std::vector<bool> Used(MeshGrid.At(Ix,Iy).size(),false);
for(double Root:Roots)
for(const FSurfaceRoot& Root:Roots)
{
std::size_t HitIndex=0;double ErrorMeters=0.0;
if(!MatchNearest(MeshGrid.At(Ix,Iy),Used,Root,HitIndex,ErrorMeters))
if(!MatchNearest(MeshGrid.At(Ix,Iy),Used,Root.ZMeters,HitIndex,ErrorMeters))
{
++Row.Missing;
Errors.push_back(2.0);
AddMissing(Accumulator);
continue;
}
Used[HitIndex]=true;
Errors.push_back(ErrorMeters/PixelBudgetMeters);
AddError(Accumulator,MeshGrid.At(Ix,Iy)[HitIndex]-Root.ZMeters,
Root,PixelBudgetMeters,View,MeshGrid.X(Ix),MeshGrid.Y(Iy));
++Row.Samples;
}
// Heightfield2D declares ground and cap roots only. Other mesh intersections may
// be valid tunnel geometry; the exact-mesh comparison checks extra pieces.
}
Row.P50=Percentile(Errors,0.50);Row.P99=Percentile(Errors,0.99);
Row.Maximum=Errors.empty()?0.0:*std::max_element(Errors.begin(),Errors.end());
Row.Samples=Errors.size();
FinalizeError(Row,Accumulator);
return Row;
}
inline FErrorRow CompareToReference(const FHeightGrid& MeshGrid,
const FHeightGrid& ReferenceGrid,int Lod,double PixelBudgetMeters)
const FHeightGrid& ReferenceGrid,const FVoxelTileKey& Patch,double VoxelMeters,
double PixelBudgetMeters,const VoxelForgeCore::WorldAssemblyManifest& Assembly,
const FViewBasis& View)
{
FErrorRow Row;Row.Lod=Lod;Row.Valid=true;
std::vector<double> Errors;
FErrorRow Row;Row.Lod=Patch.Level;Row.Valid=true;
FErrorAccumulator Accumulator;
for(int Iy=0;Iy<ReferenceGrid.Side;++Iy)
for(int Ix=0;Ix<ReferenceGrid.Side;++Ix)
{
const auto& Reference=ReferenceGrid.At(Ix,Iy);
const auto& Mesh=MeshGrid.At(Ix,Iy);
if(Reference.empty()&&Mesh.empty())continue;
std::vector<bool> Used(Mesh.size(),false);
for(double ReferenceZ:Reference)
const auto Roots=ExactHeightRoots(ReferenceGrid,Ix,Iy,Patch,VoxelMeters,Assembly);
std::vector<bool> UsedReference(Reference.size(),false),UsedMesh(Mesh.size(),false);
for(std::size_t ReferenceIndex=0;ReferenceIndex<Reference.size();++ReferenceIndex)
{
std::size_t HitIndex=0;double ErrorMeters=0.0;
if(!MatchNearest(Mesh,Used,ReferenceZ,HitIndex,ErrorMeters))
const double ReferenceZ=Reference[ReferenceIndex];
UsedReference[ReferenceIndex]=true;
std::size_t MeshIndex=0;double MeshError=0.0;
if(!MatchNearest(Mesh,UsedMesh,ReferenceZ,MeshIndex,MeshError))
{
++Row.Missing;Errors.push_back(2.0);continue;
++Row.Missing;AddMissing(Accumulator);continue;
}
Used[HitIndex]=true;
Errors.push_back(ErrorMeters/PixelBudgetMeters);
UsedMesh[MeshIndex]=true;
FSurfaceRoot Root{ReferenceZ,0.0,0.0};
if(!Roots.empty())
{
const auto BestRoot=std::min_element(Roots.begin(),Roots.end(),
[ReferenceZ](const FSurfaceRoot& A,const FSurfaceRoot& B)
{return std::abs(A.ZMeters-ReferenceZ)<std::abs(B.ZMeters-ReferenceZ);});
if(BestRoot!=Roots.end()&&std::abs(BestRoot->ZMeters-ReferenceZ)<1.0)
Root=*BestRoot;
}
AddError(Accumulator,Mesh[MeshIndex]-Reference[ReferenceIndex],
Root,PixelBudgetMeters,View,ReferenceGrid.X(Ix),ReferenceGrid.Y(Iy));
}
for(std::size_t I=0;I<Mesh.size();++I)
if(!Used[I]){++Row.Floating;Errors.push_back(2.0);}
if(!UsedMesh[I]){++Row.Floating;AddMissing(Accumulator);}
}
Row.P50=Percentile(Errors,0.50);Row.P99=Percentile(Errors,0.99);
Row.Maximum=Errors.empty()?0.0:*std::max_element(Errors.begin(),Errors.end());
Row.Samples=Errors.size();
FinalizeError(Row,Accumulator);
return Row;
}
inline FPopRow ComparePop(const FHeightGrid& Coarse,const FHeightGrid& Fine,
const FVoxelTileKey& Patch,double VoxelMeters,double PixelBudgetMeters,
const VoxelForgeCore::WorldAssemblyManifest& Assembly)
const VoxelForgeCore::WorldAssemblyManifest& Assembly,const FViewBasis& View)
{
FPopRow Row;Row.CoarseLod=Patch.Level;Row.Valid=true;
std::vector<double> Errors;
FErrorAccumulator Accumulator;
for(int Iy=0;Iy<Coarse.Side;++Iy)
for(int Ix=0;Ix<Coarse.Side;++Ix)
{
@@ -291,25 +441,34 @@ namespace StandaloneScreenSpaceGate
if(Roots.empty()&&CoarseHits.empty()&&FineHits.empty())continue;
std::vector<bool> CoarseUsed(CoarseHits.size(),false);
std::vector<bool> FineUsed(FineHits.size(),false);
for(double Root:Roots)
for(const FSurfaceRoot& Root:Roots)
{
std::size_t CoarseIndex=0,FineIndex=0;
double CoarseError=0.0,FineError=0.0;
if(!MatchNearest(CoarseHits,CoarseUsed,Root,CoarseIndex,CoarseError)
||!MatchNearest(FineHits,FineUsed,Root,FineIndex,FineError))
if(!MatchNearest(CoarseHits,CoarseUsed,Root.ZMeters,CoarseIndex,CoarseError)
||!MatchNearest(FineHits,FineUsed,Root.ZMeters,FineIndex,FineError))
{
++Row.Cracks;Errors.push_back(2.0);continue;
++Row.Cracks;AddMissing(Accumulator);continue;
}
CoarseUsed[CoarseIndex]=true;
FineUsed[FineIndex]=true;
Errors.push_back(std::abs(CoarseHits[CoarseIndex]-FineHits[FineIndex])
/PixelBudgetMeters);
AddError(Accumulator,CoarseHits[CoarseIndex]-FineHits[FineIndex],
Root,PixelBudgetMeters,View,Coarse.X(Ix),Coarse.Y(Iy));
++Row.Samples;
}
}
Row.P50=Percentile(Errors,0.50);Row.P99=Percentile(Errors,0.99);
Row.Maximum=Errors.empty()?0.0:*std::max_element(Errors.begin(),Errors.end());
Row.Samples=Errors.size();
FErrorRow Stats;Stats.Lod=Patch.Level;Stats.Valid=true;
FinalizeError(Stats,Accumulator);
Row.Samples=Stats.Samples;Row.P50=Stats.P50;Row.P99=Stats.P99;Row.Maximum=Stats.Maximum;
Row.VerticalP50=Stats.VerticalP50;Row.VerticalP99=Stats.VerticalP99;
Row.VerticalMaximum=Stats.VerticalMaximum;
Row.MaximumNormalDistanceMeters=Stats.MaximumNormalDistanceMeters;
Row.MaximumX=Stats.MaximumX;Row.MaximumY=Stats.MaximumY;
Row.MaximumReferenceZ=Stats.MaximumReferenceZ;
Row.MaximumDisplayedZ=Stats.MaximumDisplayedZ;
Row.MaximumSlopeDegrees=Stats.MaximumSlopeDegrees;
Row.SlopeSamples=Stats.SlopeSamples;Row.SlopeP99=Stats.SlopeP99;
Row.SlopeMaximum=Stats.SlopeMaximum;
return Row;
}
@@ -352,19 +511,52 @@ namespace StandaloneScreenSpaceGate
return Distances;
}
inline void PrintSlopeTail(const char* Kind,int Lod,const std::array<std::uint64_t,4>& Counts,
const std::array<double,4>& P99,const std::array<double,4>& Maximum)
{
constexpr const char* Labels[4]={"lt30","30to45","45to60","ge60"};
for(std::size_t Bin=0;Bin<Counts.size();++Bin)
std::printf("[ScreenSpaceSlopeTail] kind=%s lod=%d slope_deg=%s samples=%llu p99_px=%.4f max_px=%.4f\n",
Kind,Lod,Labels[Bin],static_cast<unsigned long long>(Counts[Bin]),P99[Bin],Maximum[Bin]);
}
inline void PrintKnownFailureControl(double CellMeters,double DisplayDistanceMeters,
const FViewBasis& View)
{
constexpr double Slope=100.0;
const double LateralMeters=CellMeters/200.0;
const double VerticalMeters=Slope*LateralMeters;
const double NormalLength=std::sqrt(1.0+Slope*Slope);
const double NormalDistance=VerticalMeters/NormalLength;
const std::array<double,3> Normal={-Slope/NormalLength,0.0,1.0/NormalLength};
const double ProjectedNormal=std::hypot(
Normal[0]*View.Right[0]+Normal[1]*View.Right[1]+Normal[2]*View.Right[2],
Normal[0]*View.Up[0]+Normal[1]*View.Up[1]+Normal[2]*View.Up[2]);
const double PixelBudgetMeters=DisplayDistanceMeters*OnePixelRadians;
const double VerticalPixels=VerticalMeters/PixelBudgetMeters;
const double NormalPixels=NormalDistance*ProjectedNormal/PixelBudgetMeters;
const bool Passed=VerticalPixels>4.0&&NormalPixels<1.0;
std::printf("[ScreenSpaceKnownFailureControl] case=steep-plane-lateral-offset slope_deg=%.4f cell_m=%.6f lateral_m=%.6f cell_fraction=%.6f vertical_error_m=%.6f vertical_height_px=%.4f closest_normal_m=%.6f projected_normal_px=%.4f status=%s\n",
std::atan(Slope)*180.0/3.14159265358979323846,CellMeters,LateralMeters,
LateralMeters/CellMeters,VerticalMeters,VerticalPixels,NormalDistance,NormalPixels,
Passed?"EXPECTED_VERTICAL_FALSE_POSITIVE":"CONTROL_FAILED");
}
inline bool Run(const std::array<std::optional<FStandaloneCpuTile>,9>& SampleTiles,
FStandaloneStreamingGenerator& Streamer,
const VoxelForgeCore::WorldAssemblyManifest& Assembly,
const std::array<double,9>& Distances,std::uint32_t VoxelSizeMicrons,int MaxLod,
const std::array<std::int64_t,9>& PixelBudgetsSubvoxels)
const std::array<std::int64_t,9>& PixelBudgetsSubvoxels,
double CameraYawDegrees,double CameraPitchDegrees)
{
const double VoxelMeters=static_cast<double>(VoxelSizeMicrons)/1000000.0;
const FViewBasis View=MakeViewBasis(CameraYawDegrees,CameraPitchDegrees);
std::array<double,9> Budgets{};
std::array<FErrorRow,9> ErrorRows{};
std::array<FPopRow,9> PopRows{};
bool GatePass=true;
std::printf("[ScreenSpaceGate] angular_pixel=%.9f rad (90deg/2560) lod>=3_limit=1.0px sampling=65x65 skirts=excluded metric=vertical_height_error field_reference=direct-Heightfield2D-roots\n",
OnePixelRadians);
std::printf("[ScreenSpaceGate] angular_pixel=%.9f rad (horizontal_fov=90deg,width=2560) lod>=3_limit=1.0px sampling=65x65 skirts=excluded metric=local_surface_normal_projected field_reference=direct-Heightfield2D-roots normal_probe_vox=1 view_yaw_deg=%.3f view_pitch_deg=%.3f\n",
OnePixelRadians,CameraYawDegrees,CameraPitchDegrees);
for(int Lod=0;Lod<=MaxLod&&Lod<9;++Lod)
{
Budgets[Lod]=Distances[Lod]*OnePixelRadians;
@@ -372,6 +564,8 @@ namespace StandaloneScreenSpaceGate
Lod,Distances[Lod],Budgets[Lod],Budgets[Lod]*100.0,
static_cast<long long>(PixelBudgetsSubvoxels[Lod]),Lod<3?"exact-2cm":"1px");
}
const double LOD3CellMeters=static_cast<double>(CHUNK_SIZE*(1<<3))*VoxelMeters/64.0;
PrintKnownFailureControl(LOD3CellMeters,Distances[3],View);
VoxelForgeCore::Heightfield2D::resetThreadColumnCacheStats(false,true,0);
for(int Lod=3;Lod<=MaxLod&&Lod<9;++Lod)
{
@@ -389,32 +583,43 @@ namespace StandaloneScreenSpaceGate
const FStandaloneCpuTile* ExactPointer=&ExactTile;
const std::span<const FStandaloneCpuTile* const> ExactSpan(&ExactPointer,1);
const FHeightGrid ExactGrid=Rasterize(ExactSpan,ExactTile.Key,VoxelMeters);
ErrorRows[Lod]=CompareToReference(CoarseGrid,ExactGrid,Lod,Budgets[Lod]);
ErrorRows[Lod]=CompareToReference(CoarseGrid,ExactGrid,CoarseTile.Key,VoxelMeters,
Budgets[Lod],Assembly,View);
const FErrorRow& Error=ErrorRows[Lod];
const bool LodPass=Error.Valid&&Error.Missing==0&&Error.Floating==0
&&Error.Samples>=16&&Error.Maximum<=1.0;
GatePass=GatePass&&LodPass;
std::printf("[ScreenSpaceGateLOD] lod=%d key=(%d,%d,%d) samples=%llu p50_px=%.4f p99_px=%.4f max_px=%.4f missing=%llu floating=%llu status=%s\n",
std::printf("[ScreenSpaceGateLOD] lod=%d key=(%d,%d,%d) samples=%llu normal_px_p50=%.4f p99=%.4f max=%.4f vertical_px_p50=%.4f p99=%.4f max=%.4f max_normal_m=%.6f max_xy_m=(%.3f,%.3f) max_slope_deg=%.2f missing=%llu floating=%llu status=%s\n",
Lod,CoarseTile.Key.Coord.X,CoarseTile.Key.Coord.Y,CoarseTile.Key.Coord.Z,
static_cast<unsigned long long>(Error.Samples),Error.P50,Error.P99,Error.Maximum,
Error.VerticalP50,Error.VerticalP99,Error.VerticalMaximum,
Error.MaximumNormalDistanceMeters,Error.MaximumX,Error.MaximumY,
Error.MaximumSlopeDegrees,
static_cast<unsigned long long>(Error.Missing),static_cast<unsigned long long>(Error.Floating),
LodPass?"PASS":"REJECT");
PrintSlopeTail("same_lod",Lod,Error.SlopeSamples,Error.SlopeP99,Error.SlopeMaximum);
const FErrorRow FieldError=CompareToExact(CoarseGrid,CoarseTile.Key,VoxelMeters,
Budgets[Lod],Assembly);
Budgets[Lod],Assembly,View);
const bool FieldPass=FieldError.Valid&&FieldError.Missing==0&&FieldError.Floating==0
&&FieldError.Samples>=16&&FieldError.Maximum<=1.0;
GatePass=GatePass&&FieldPass;
std::printf("[ScreenSpaceGateFieldLOD] lod=%d samples=%llu p50_px=%.4f p99_px=%.4f max_px=%.4f missing=%llu floating=%llu status=%s\n",
std::printf("[ScreenSpaceGateFieldLOD] lod=%d samples=%llu normal_px_p50=%.4f p99=%.4f max=%.4f vertical_px_p50=%.4f p99=%.4f max=%.4f max_normal_m=%.6f max_xyz_m=(%.3f,%.3f,%.3f) max_slope_deg=%.2f missing=%llu floating=%llu status=%s\n",
Lod,static_cast<unsigned long long>(FieldError.Samples),FieldError.P50,
FieldError.P99,FieldError.Maximum,static_cast<unsigned long long>(FieldError.Missing),
FieldError.P99,FieldError.Maximum,FieldError.VerticalP50,FieldError.VerticalP99,
FieldError.VerticalMaximum,FieldError.MaximumNormalDistanceMeters,
FieldError.MaximumX,FieldError.MaximumY,FieldError.MaximumDisplayedZ,
FieldError.MaximumSlopeDegrees,
static_cast<unsigned long long>(FieldError.Missing),
static_cast<unsigned long long>(FieldError.Floating),FieldPass?"PASS":"REJECT");
PrintSlopeTail("field",Lod,FieldError.SlopeSamples,FieldError.SlopeP99,
FieldError.SlopeMaximum);
bool FaultControlsPass=true;
const FHeightGrid MissingGrid(ExactGrid.Side,ExactGrid.MinimumX,ExactGrid.MaximumX,
ExactGrid.MinimumY,ExactGrid.MaximumY);
const FErrorRow MissingError=CompareToReference(MissingGrid,ExactGrid,Lod,
Budgets[Lod]);
const FErrorRow MissingError=CompareToReference(MissingGrid,ExactGrid,
CoarseTile.Key,VoxelMeters,Budgets[Lod],Assembly,View);
const bool MissingRejected=MissingError.Missing>0&&MissingError.Maximum>1.0;
FaultControlsPass=FaultControlsPass&&MissingRejected;
std::printf("[ScreenSpaceFaultInjection] lod=%d case=missing-displayed-surface missing=%llu status=%s\n",
@@ -435,8 +640,8 @@ namespace StandaloneScreenSpaceGate
const FStandaloneCpuTile* FloatingPointer=&FloatingTile;
const std::span<const FStandaloneCpuTile* const> FloatingSpan(&FloatingPointer,1);
const FHeightGrid FloatingGrid=Rasterize(FloatingSpan,CoarseTile.Key,VoxelMeters);
const FErrorRow FloatingError=CompareToReference(FloatingGrid,ExactGrid,Lod,
Budgets[Lod]);
const FErrorRow FloatingError=CompareToReference(FloatingGrid,ExactGrid,
CoarseTile.Key,VoxelMeters,Budgets[Lod],Assembly,View);
const bool FloatingRejected=FloatingError.Floating>0||FloatingError.Maximum>1.0;
FaultControlsPass=FaultControlsPass&&FloatingRejected;
std::printf("[ScreenSpaceFaultInjection] lod=%d case=2m-floating-surface floating=%llu max_px=%.4f status=%s\n",
@@ -461,20 +666,24 @@ namespace StandaloneScreenSpaceGate
FinePointers.data(),FinePointers.size());
const FHeightGrid FineGrid=Rasterize(FineSpan,CoarseTile.Key,VoxelMeters);
PopRows[Lod]=ComparePop(CoarseGrid,FineGrid,CoarseTile.Key,VoxelMeters,
Budgets[Lod],Assembly);
Budgets[Lod],Assembly,View);
const FPopRow& Pop=PopRows[Lod];
const bool PopPass=Pop.Valid&&Pop.Cracks==0&&Pop.Floating==0&&Pop.Maximum<=1.0;
GatePass=GatePass&&PopPass;
std::printf("[ScreenSpaceSwap] lod=%d_to_%d samples=%llu p50_px=%.4f p99_px=%.4f max_px=%.4f cracks=%llu floating=%llu status=%s\n",
std::printf("[ScreenSpaceSwap] lod=%d_to_%d samples=%llu normal_px_p50=%.4f p99=%.4f max=%.4f vertical_px_p50=%.4f p99=%.4f max=%.4f max_normal_m=%.6f max_xyz_m=(%.3f,%.3f,%.3f) max_slope_deg=%.2f cracks=%llu floating=%llu status=%s\n",
Lod,Lod-1,static_cast<unsigned long long>(Pop.Samples),
Pop.P50,Pop.P99,Pop.Maximum,static_cast<unsigned long long>(Pop.Cracks),
Pop.P50,Pop.P99,Pop.Maximum,Pop.VerticalP50,Pop.VerticalP99,Pop.VerticalMaximum,
Pop.MaximumNormalDistanceMeters,Pop.MaximumX,Pop.MaximumY,
Pop.MaximumDisplayedZ,
Pop.MaximumSlopeDegrees,static_cast<unsigned long long>(Pop.Cracks),
static_cast<unsigned long long>(Pop.Floating),
PopPass?"PASS":"REJECT");
PrintSlopeTail("swap",Lod,Pop.SlopeSamples,Pop.SlopeP99,Pop.SlopeMaximum);
const FHeightGrid MissingFineGrid(CoarseGrid.Side,CoarseGrid.MinimumX,
CoarseGrid.MaximumX,CoarseGrid.MinimumY,CoarseGrid.MaximumY);
const FPopRow MissingFineError=ComparePop(CoarseGrid,MissingFineGrid,
CoarseTile.Key,VoxelMeters,Budgets[Lod],Assembly);
CoarseTile.Key,VoxelMeters,Budgets[Lod],Assembly,View);
const bool CrackRejected=MissingFineError.Cracks>0&&MissingFineError.Maximum>1.0;
FaultControlsPass=FaultControlsPass&&CrackRejected;
GatePass=GatePass&&FaultControlsPass;
@@ -490,8 +699,8 @@ namespace StandaloneScreenSpaceGate
const FStandaloneCpuTile* BadPointer=&Bad;
const std::span<const FStandaloneCpuTile* const> BadSpan(&BadPointer,1);
const FHeightGrid BadGrid=Rasterize(BadSpan,Bad.Key,VoxelMeters);
const FErrorRow BadError=CompareToReference(BadGrid,ExactGrid,Lod,
Budgets[Lod]);
const FErrorRow BadError=CompareToReference(BadGrid,ExactGrid,
CoarseTile.Key,VoxelMeters,Budgets[Lod],Assembly,View);
const bool Rejected=BadError.Missing>0||BadError.Floating>0
||BadError.Samples<16||BadError.Maximum>1.0;
NegativeControlsPass=NegativeControlsPass&&Rejected;