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:
1 parent
dcf0763ec5
commit
811c4b7b17
23 files changed
+698
-17
No files matched your search
@@ -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
|
||||
|
||||
Reference in new issue
Block a user