wip(assembler): round L19 -- strate ceilings closed at every LOD; ledges diagnosed

The shared boundary-cap path now emits a cap wherever the field is solid just below a strate's
configured top (it previously required a solid-to-air crossing there) and checks a 5x5 perimeter
grid before suppressing a fallback cap. Strict audit: 0 misses / 0 edge gaps, LOD0-8.
farHorizonVersion 3 -> 4. SurfaceWorld LOD0-2, full detail and exact queries unchanged; 28/28
matrix plus 14/14 crossing; route parity and proofs pass.
Ledges: the lower stratum's terrain at the FI/SW interface, seen through the FI void, sampled at
0.5/1/2 m at LOD1-3 (up to 1.5 m / 7.7 m ring steps). Fix deferred to the units/layers round.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-20 08:46:29 +02:00
1 parent dcf0763ec5
commit 811c4b7b17
23 files changed
+698 -17

No files matched your search

@@ -1096,11 +1096,11 @@ namespace VoxelForgeCore
// LOD8-only planar horizon interior grid; zero follows the MC step, 128 restores S9.
// Grille interieure LOD8 seulement; zero suit la maille MC, 128 restaure S9.
std::int32_t lod8HorizonInteriorStepVoxels = 0;
// Bump when the distant cap representation changes. LOD4-8 mesh hashes are salted;
// density and LOD0-3 hashes remain unchanged.
// Incremente quand le plafond lointain change. Les hashes LOD4-8 incluent cette version;
// densite et hashes LOD0-3 restent inchanges.
std::uint32_t farHorizonVersion = 3;
// Bump when shared stratum-boundary caps or the distant horizon representation changes.
// LOD4-8 mesh hashes are salted; density and LOD0-3 keep their direct identities.
// Incremente quand les plafonds partages ou l'horizon lointain changent.
// Les hashes de maillage LOD4-8 incluent cette version; LOD0-3 gardent leur identite directe.
std::uint32_t farHorizonVersion = 4;
// Linux research controls for reproducing L5 negative controls. Defaults preserve output.
std::uint32_t diagnosticGlobalOctaveDrop = 0;
std::uint32_t diagnosticCellStride = 1;
+17 -12
View File
@@ -894,7 +894,11 @@ struct FFarMeshColumnIndex
bool HasDownwardCellCoverage(double X0,double Y0,double X1,double Y1,
double Z,double Tolerance) const
{
constexpr double Samples[3]={0.125,0.5,0.875};
// Probe the perimeter as well as the interior: sparse interior-only probes can
// incorrectly hide a missing ceiling quad at an MC grid vertex.
// Sonder le perimetre et l'interieur: des sondes seulement interieures peuvent
// masquer un carre de plafond manquant sur un sommet de la grille MC.
constexpr double Samples[5]={0.0,0.25,0.5,0.75,1.0};
for(const double V:Samples)for(const double U:Samples)
{
const double X=X0+(X1-X0)*U;
@@ -1185,7 +1189,7 @@ inline void AppendStratumBoundaryCeilings(const FStandaloneOwnerWorld& World,
struct FCandidate
{
FStandaloneShapeWorld::FResolvedStratumBounds Bounds;
std::vector<uint8> Crossing;
std::vector<uint8> SolidBelow;
};
std::vector<FCandidate> Candidates;
for(const FStrateSlot& Slot:World.Manager->GetLayout())
@@ -1197,21 +1201,22 @@ inline void AppendStratumBoundaryCeilings(const FStandaloneOwnerWorld& World,
||Candidate.Bounds.TopZ>Origin.Z+Extent+1.0e-6)continue;
const double Epsilon=std::min(0.5,Candidate.Bounds.SealThickness*0.25);
if(Epsilon<=0.0)continue;
Candidate.Crossing.resize(static_cast<std::size_t>(GridSide)*GridSide,0);
bool AnyCrossing=false;
Candidate.SolidBelow.resize(static_cast<std::size_t>(GridSide)*GridSide,0);
bool AnySolidBelow=false;
for(int32 Y=0;Y<GridSide;++Y)for(int32 X=0;X<GridSide;++X)
{
const double WorldX=Origin.X+X*GridStep;
const double WorldY=Origin.Y+Y*GridStep;
const float Below=Shape.DensityAt(static_cast<float>(WorldX),static_cast<float>(WorldY),
static_cast<float>(Candidate.Bounds.TopZ-Epsilon));
const float Above=Shape.DensityAt(static_cast<float>(WorldX),static_cast<float>(WorldY),
static_cast<float>(Candidate.Bounds.TopZ+Epsilon));
const bool bCrosses=std::isfinite(Below)&&std::isfinite(Above)&&Below<0.0f&&Above>0.0f;
Candidate.Crossing[static_cast<std::size_t>(Y*GridSide+X)]=bCrosses?1:0;
AnyCrossing=AnyCrossing||bCrosses;
// The shared upper boundary closes the stratum even where its raw field stays
// solid above the configured top. A zero-crossing test leaves holes there.
// Le plafond partage ferme la strate meme si le champ reste solide au-dessus.
const bool bSolidBelow=std::isfinite(Below)&&Below<0.0f;
Candidate.SolidBelow[static_cast<std::size_t>(Y*GridSide+X)]=bSolidBelow?1:0;
AnySolidBelow=AnySolidBelow||bSolidBelow;
}
if(AnyCrossing)Candidates.push_back(std::move(Candidate));
if(AnySolidBelow)Candidates.push_back(std::move(Candidate));
}
if(Candidates.empty())return;
@@ -1248,8 +1253,8 @@ inline void AppendStratumBoundaryCeilings(const FStandaloneOwnerWorld& World,
{
const std::size_t I00=static_cast<std::size_t>(Y*GridSide+X);
const std::size_t I10=I00+1,I01=I00+GridSide,I11=I01+1;
if(!Candidate.Crossing[I00]||!Candidate.Crossing[I10]
||!Candidate.Crossing[I01]||!Candidate.Crossing[I11])continue;
if(!Candidate.SolidBelow[I00]||!Candidate.SolidBelow[I10]
||!Candidate.SolidBelow[I01]||!Candidate.SolidBelow[I11])continue;
const double CellX0=Origin.X+X*GridStep,CellY0=Origin.Y+Y*GridStep;
const double CellX1=CellX0+GridStep,CellY1=CellY0+GridStep;
// Suppress a coincident plane only when it covers the full cell. A hit at just the