standalone: owner LOD0 defects -- relief blended as partition of unity (stairs gone), exposed skirts 0

- Stairs: cave, floor, strata and passage relief were effectively summed in overlaps (owner ray
  ~0.94 voxel of displacement); now partition-of-unity weights: -0.288 voxel there, max detail
  gradient 0.323 voxel/voxel. High-detail patch scan 133 -> 0; exact midpoint edge roots kept
  (removing them: 7,993 bad roots, 46 patches).
- Fins: exposed skirt triangle scan 1,776 -> 0; thin sheets 0; coarse off-surface panels 0.
- Path hash both directions equal; W1/W8 equal; routes 5642/5642; passage detail ratio 0.850;
  far survival passes, bad-shell fails; 30-crossing flight: nearest tile 15.1 ms median, 124 ms max.
Caveats seen in the captures: the owner-ray wall has visibly less relief than before; the fin
before/after captures do not show the fins (evidence is the scan only). Cold StreamFullClipmap
0.758 s vs 0.741 s (+17 ms, Luna's interleaved run). Owner to judge: bin\VoxelForgeLookCheck4.exe.

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-06 02:42:56 +02:00
1 parent b3af0e589e
commit de14f0042d
6 files changed
+213 -26

No files matched your search

@@ -25,6 +25,18 @@ namespace
GVoxelForgeUseOperatorBlock,
TEXT("Use the operator-major density block path for non-shared mesher grids."));
bool GVoxelForgeBlockSwitchParsed = false;
int32 GVoxelForgeRawSkirtsForAudit = 0;
bool GVoxelForgeRawSkirtsSwitchParsed = false;
void VF_ParseRawSkirtsAuditSwitch()
{
if(GVoxelForgeRawSkirtsSwitchParsed)return;
GVoxelForgeRawSkirtsSwitchParsed=true;
GVoxelForgeRawSkirtsForAudit=FString(FCommandLine::Get()).Contains(
TEXT("--audit-raw-skirts"))?1:0;
if(GVoxelForgeRawSkirtsForAudit)
std::printf("[SkirtAuditControl] raw skirt curtains enabled for negative-control scan\n");
}
int32 GVoxelForgeTilePostReachDebug = 0;
FAutoConsoleVariableRef CVarVoxelForgeTilePostReachDebug(
@@ -93,6 +105,7 @@ void UVoxelMarchingCubesMesher::InitializeConsoleSwitches()
{
VF_ParseOperatorBlockSwitch();
VF_ParseTilePostReachSwitches();
VF_ParseRawSkirtsAuditSwitch();
}
//=============================================================================
@@ -562,7 +575,7 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
VoxelDensityProfile::RecordClassifierCall(bSampleClassifier);
}
EVoxelTileClass Verdict;
if(ShapeWorldContext)
if(ShapeWorldContext&&Step<=2)
{
const auto ShapeVerdict=ShapeWorldContext->ClassifyBox(
BlockOrigin,Step,BlockCells);
@@ -1631,6 +1644,23 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
return Idx;
};
std::vector<float> SurfaceVertexDensitySamples;
if(ShapeWorldContext)
SurfaceVertexDensitySamples.assign(static_cast<size_t>(MeshData.Vertices.Num()),
std::numeric_limits<float>::quiet_NaN());
const auto SampleSurfaceVertexDensity=[&](int32 OriginalIndex,const FVector& Position)
{
if(!ShapeWorldContext)return 0.0f;
if(OriginalIndex<0||static_cast<size_t>(OriginalIndex)>=SurfaceVertexDensitySamples.size())
return ShapeWorldContext->DensityAt(Position.X/VOXEL_SIZE,
Position.Y/VOXEL_SIZE,Position.Z/VOXEL_SIZE);
float& Density=SurfaceVertexDensitySamples[static_cast<size_t>(OriginalIndex)];
if(std::isnan(Density))
Density=ShapeWorldContext->DensityAt(Position.X/VOXEL_SIZE,
Position.Y/VOXEL_SIZE,Position.Z/VOXEL_SIZE);
return Density;
};
// F17 — jupes émises PAR SEAU : chaque jupe hérite la classe (donc le polygroup /
// matériau) de son triangle source ; ajouter les jupes après coup casserait les runs
// d'indices contigus par groupe qu'exige RMC.
@@ -1655,7 +1685,7 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
Position.Y/VOXEL_SIZE,Position.Z/VOXEL_SIZE);
return Vertex;
};
const auto InterpolateVertex=[](const FSkirtVertex& A,const FSkirtVertex& B,float T)
const auto InterpolateVertex=[&](const FSkirtVertex& A,const FSkirtVertex& B,float T)
{
if(T<=1.0e-6f)return A;
if(T>=1.0f-1.0e-6f)return B;
@@ -1667,13 +1697,31 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
static_cast<uint8>(FMath::Clamp(FMath::RoundToInt(FMath::Lerp(static_cast<float>(A.Color.G),static_cast<float>(B.Color.G),T)),0,255)),
static_cast<uint8>(FMath::Clamp(FMath::RoundToInt(FMath::Lerp(static_cast<float>(A.Color.B),static_cast<float>(B.Color.B),T)),0,255)),
static_cast<uint8>(FMath::Clamp(FMath::RoundToInt(FMath::Lerp(static_cast<float>(A.Color.A),static_cast<float>(B.Color.A),T)),0,255)));
Out.Density=FMath::Lerp(A.Density,B.Density,T);
Out.Density=ShapeWorldContext
?ShapeWorldContext->DensityAt(Out.Position.X/VOXEL_SIZE,
Out.Position.Y/VOXEL_SIZE,Out.Position.Z/VOXEL_SIZE)
:FMath::Lerp(A.Density,B.Density,T);
Out.OriginalIndex=INDEX_NONE;
return Out;
};
const auto EmitClippedTriangle=[&](const FSkirtVertex& A,const FSkirtVertex& B,
const FSkirtVertex& C,uint8 FaceMask)
const auto EmitClippedTriangle=[&](auto&& Self,const FSkirtVertex& A,
const FSkirtVertex& B,const FSkirtVertex& C,uint8 FaceMask,
int32 RefinementDepth)->void
{
if(GVoxelForgeRawSkirtsForAudit)
{
const FSkirtVertex Input[3]={A,B,C};
int32 Indices[3];
for(int32 Vertex=0;Vertex<3;++Vertex)
Indices[Vertex]=Input[Vertex].OriginalIndex>=0
?Input[Vertex].OriginalIndex
:AddSkirtVert(Input[Vertex].Position,Input[Vertex].Normal,
Input[Vertex].Color);
Tris.Add(Indices[0]);Tris.Add(Indices[1]);Tris.Add(Indices[2]);
Tris.Add(Indices[0]);Tris.Add(Indices[2]);Tris.Add(Indices[1]);
FaceMasks.Add(FaceMask);FaceMasks.Add(FaceMask);
return;
}
FSkirtVertex Input[3]={A,B,C};
FSkirtVertex Polygon[5];
int32 PolygonCount=0;
@@ -1704,7 +1752,56 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
const FSkirtVertex& P0=Polygon[0];
const FSkirtVertex& P1=Polygon[Fan];
const FSkirtVertex& P2=Polygon[Fan+1];
if(ShapeWorldContext)
if(ShapeWorldContext&&Step<=2)
{
const auto ProbeDensity=[&](double WA,double WB,double WC)
{
const FVector Position=P0.Position*static_cast<float>(WA)
+P1.Position*static_cast<float>(WB)
+P2.Position*static_cast<float>(WC);
return ShapeWorldContext->DensityAt(Position.X/VOXEL_SIZE,
Position.Y/VOXEL_SIZE,Position.Z/VOXEL_SIZE);
};
const auto VertexProbeDensity=[&](const FSkirtVertex& Vertex)
{
return Vertex.OriginalIndex>=0
?SampleSurfaceVertexDensity(Vertex.OriginalIndex,Vertex.Position)
:Vertex.Density;
};
float MaximumProbeDensity=FMath::Max(VertexProbeDensity(P0),
FMath::Max(VertexProbeDensity(P1),VertexProbeDensity(P2)));
const double ProbeWeights[4][3]={
{1.0/3.0,1.0/3.0,1.0/3.0},
{0.5,0.5,0.0},{0.0,0.5,0.5},{0.5,0.0,0.5}};
const int32 ProbeCount=RefinementDepth==0?4:1;
for(int32 Probe=0;Probe<ProbeCount;++Probe)
{
MaximumProbeDensity=FMath::Max(MaximumProbeDensity,
ProbeDensity(ProbeWeights[Probe][0],
ProbeWeights[Probe][1],ProbeWeights[Probe][2]));
if(MaximumProbeDensity>0.25f)break;
}
if(MaximumProbeDensity>0.25f)
{
if(RefinementDepth>=1)continue;
const auto MakeMidpoint=[&](const FSkirtVertex& X,
const FSkirtVertex& Y)
{
FSkirtVertex Mid=InterpolateVertex(X,Y,0.5f);
Mid.OriginalIndex=INDEX_NONE;
return Mid;
};
const FSkirtVertex M01=MakeMidpoint(P0,P1);
const FSkirtVertex M12=MakeMidpoint(P1,P2);
const FSkirtVertex M20=MakeMidpoint(P2,P0);
Self(Self,P0,M01,M20,FaceMask,RefinementDepth+1);
Self(Self,M01,P1,M12,FaceMask,RefinementDepth+1);
Self(Self,M20,M12,P2,FaceMask,RefinementDepth+1);
Self(Self,M01,M12,M20,FaceMask,RefinementDepth+1);
continue;
}
}
else if(ShapeWorldContext)
{
const FVector Center=(P0.Position+P1.Position+P2.Position)
/(3.0f*VOXEL_SIZE);
@@ -1739,8 +1836,8 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
// Clip both source triangles against the solid half-space before emitting
// each orientation. A curtain that points into tunnel air must not become
// visible geometry beyond the sampled isosurface.
EmitClippedTriangle(A,B,B2,FaceMask);
EmitClippedTriangle(A,B2,A2,FaceMask);
EmitClippedTriangle(EmitClippedTriangle,A,B,B2,FaceMask,0);
EmitClippedTriangle(EmitClippedTriangle,A,B2,A2,FaceMask,0);
}
}
MeshData.NumSkirtTriangles += (Tris.Num() - BaseTriNum) / 3;