feat(opstack): EffectOverBox correct in ISOLATION -- the blocker is closed
COMPOSER-NOTES §6.1, titled THE BLOCKER, gated everything after it. A source writing only Sdf did not touch density, so it answered the box query ON BEHALF OF the converter that followed it -- fine when a human wrote and verified the pair, unsafe the moment the composer assembles a combination nobody checked. And the failure is the silent one: a tile wrongly proved uniform means no geometry, no collision, no error, and a player falls through the floor. FVoxelBoxHypotheses now carries FVoxelBoxSdfInterval. SDF writers publish their own [Min, Max]; replacement writers replace it, accumulating writers MinWith it; converters and detail ops consume the prior interval through a state-aware EffectOverBox. Each op answers only for itself and the fold composes them. Unknown, invalid, non-finite or unimplemented bounds force Mixed -- when in doubt the answer is Mixed, because a missed skip costs milliseconds and a false uniform costs a player. Bounds are SUPREMA of what Eval can produce, never the param named "max": FBM 1.5 (not 1.0), max(Min,Max) radius envelopes, warp sqrt(2), SmoothMin slack. [FLT_MAX, FLT_MAX] is the exact no-surface identity. ⭐ THE PROOF IS THE NOVEL STACK. Built a combination no shipping builder produces: ConstantVoid -> LatticeCorridorSource -> SdfRoughness -> SdfFill brute-forced 332,750 voxels across 256 boxes: 250 proved AllAir, 0 VIOLATIONS. If isolation is real an unverified stack must still be sound, and it is. That test -- not the refactor -- is the deliverable. Every archetype re-proved by brute force, 0 violations everywhere: Maze 112/256 · CrystalChamber 38/60 · Underwater 33/40 · FlatPlain 32/60 VerticalShafts 28/60 · FloatingIslands 15/60 · TunnelNetwork prod 9/40 TunnelNetwork dense 0/40 (correctly -- it really is all mixed) COST, reported not hidden: isolation gives up some skipping. TunnelNetwork production 12->9, VerticalShafts 32->28. Answering for yourself alone is strictly weaker than answering for a verified pair. The classifier stays materially useful and the trade buys safe composition, which is the point. Eval is untouched; equivalence tests bit-identical; no per-voxel box query. SurfaceWorld keeps its separate exact height/lattice classifier. Also: ⛔ WITHDREW the "corrective ops must be fused" claim from §3.2. FFloorBiasMod does NOT undo FCaveRoughnessMod -- it adds an independent NormZ^2 x FloorBias term to the ACCUMULATED density and never reads TotalRough. Not a correction, no fuse, no "corrects" dependency. The claim came from reading a name and a comment; one grep would have shown the ten Density-writing ops in between before the paragraph was written. Build clean, 22 succeeded / 0 failed, verified in VoxelM.log. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU
This commit is contained in:
1 parent
7b982ad5ae
commit
8e346a3054
11 files changed
+1193
-890
No files matched your search
@@ -233,7 +233,7 @@ bool FVoxelForgeOpStackIslandTest::RunTest(const FString& Parameters)
|
||||
// 3. LE VERDICT DE BOÎTE — et la première preuve « AllAir » du plugin
|
||||
//=========================================================================
|
||||
{
|
||||
int32 NumProvedSolid = 0, NumProvedAir = 0, NumMixed = 0, NumUnsound = 0;
|
||||
int32 NumProvedSolid = 0, NumProvedAir = 0, NumMixed = 0, NumUnsound = 0, NumBruteSamples = 0;
|
||||
FRandomStream Rng(24680);
|
||||
// Hors de la boucle : la ligne de rapport en a besoin. Une étendue d'échantillonnage qu'on
|
||||
// ne peut pas citer dans le rapport est une étendue que personne ne surveille.
|
||||
@@ -268,6 +268,7 @@ bool FVoxelForgeOpStackIslandTest::RunTest(const FString& Parameters)
|
||||
const float Y = (float)(Origin.Y + gy * Step);
|
||||
const float Z = (float)(Origin.Z + gz * Step);
|
||||
const float D = Stack.EvalMC(X, Y, Z);
|
||||
++NumBruteSamples;
|
||||
if (bClaimsSolid ? (D >= 0.0f) : (D < 0.0f))
|
||||
{
|
||||
if (NumUnsound == 0)
|
||||
@@ -275,7 +276,7 @@ bool FVoxelForgeOpStackIslandTest::RunTest(const FString& Parameters)
|
||||
AddError(FString::Printf(
|
||||
TEXT("HOLE: the island stack claimed %s for the box at (%d,%d,%d) but ")
|
||||
TEXT("EvalMC(%.0f, %.0f, %.0f) = %.6g is on the %s side. Suspects, in ")
|
||||
TEXT("order: the blob source's Pad (does it cover the WARP amplitude ")
|
||||
TEXT("order: the blob source's propagated SDF interval (does it cover the WARP amplitude ")
|
||||
TEXT("AND the roughness AND the fill blend AND the SmoothMin dip?), ")
|
||||
TEXT("then the Z bound -- note there is NO lower bound, a thin thread ")
|
||||
TEXT("of matter hangs below each island down the axis, so only the ")
|
||||
@@ -295,11 +296,11 @@ bool FVoxelForgeOpStackIslandTest::RunTest(const FString& Parameters)
|
||||
AddInfo(FString::Printf(
|
||||
TEXT("Box verdicts over 60 FloatingIslands tiles (XY sampled from +/- %d voxels = %.1f x ")
|
||||
TEXT("IslandSpacing %.0f): %d proved AllSolid, %d proved AllAir, ")
|
||||
TEXT("%d Mixed. Today's ClassifyTile proves ZERO of these. The AllAir count is the new ")
|
||||
TEXT("%d Mixed, %d voxels checked, %d violations. Today's ClassifyTile proves ZERO of these. The AllAir count is the new ")
|
||||
TEXT("thing: no cave archetype has ever been able to prove 'all air', and a floating-")
|
||||
TEXT("island strate is mostly exactly that (OPSTACK-DECOMPOSITION 7)."),
|
||||
SpanVoxels, (float)SpanVoxels / FMath::Max(P.IslandSpacing, 1.0f), P.IslandSpacing,
|
||||
NumProvedSolid, NumProvedAir, NumMixed));
|
||||
NumProvedSolid, NumProvedAir, NumMixed, NumBruteSamples, NumUnsound));
|
||||
|
||||
if (NumProvedAir == 0)
|
||||
{
|
||||
|
||||
@@ -87,6 +87,7 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
||||
namespace
|
||||
{
|
||||
constexpr int32 NumMazeSamples = 20000;
|
||||
constexpr int32 NumMazeBoxTests = 256;
|
||||
|
||||
/** Les params Maze de la strate Maze de la fixture, bornes Z de runtime comprises. */
|
||||
bool ResolveMazeParams(const VoxelForgeTest::FTestWorld& World, FMazeGenerationParams& Out,
|
||||
@@ -265,14 +266,14 @@ bool FVoxelForgeOpStackMazeTest::RunTest(const FString& Parameters)
|
||||
// VerticalShafts, FloatingIslands, FlatPlain, CrystalChamber et Underwater ne captent RIEN du
|
||||
// gain T1.d. Tout nombre > 0 ici est du saut de tuile que Maze n'a jamais eu.
|
||||
{
|
||||
int32 NumProved = 0, NumMixed = 0, NumUnsound = 0;
|
||||
int32 NumProved = 0, NumMixed = 0, NumUnsound = 0, NumBruteSamples = 0;
|
||||
FRandomStream Rng(24680);
|
||||
// Hors de la boucle : la ligne de rapport en a besoin. Une étendue d'échantillonnage qu'on
|
||||
// ne peut pas citer dans le rapport est une étendue que personne ne surveille.
|
||||
const int32 SpanCells = 40;
|
||||
const int32 SpanVoxels = SpanCells * 8; // Extent = Step * Cells = 1 * 8
|
||||
|
||||
for (int32 t = 0; t < 60; ++t)
|
||||
for (int32 t = 0; t < NumMazeBoxTests; ++t)
|
||||
{
|
||||
const int32 Step = 1, Cells = 8; // petites tuiles : force brute tenable
|
||||
const int32 Extent = Step * Cells;
|
||||
@@ -299,6 +300,7 @@ bool FVoxelForgeOpStackMazeTest::RunTest(const FString& Parameters)
|
||||
const float Y = (float)(Origin.Y + gy * Step);
|
||||
const float Z = (float)(Origin.Z + gz * Step);
|
||||
const float D = Stack.EvalMC(X, Y, Z);
|
||||
++NumBruteSamples;
|
||||
if (bClaimsSolid ? (D >= 0.0f) : (D < 0.0f))
|
||||
{
|
||||
if (NumUnsound == 0)
|
||||
@@ -307,8 +309,8 @@ bool FVoxelForgeOpStackMazeTest::RunTest(const FString& Parameters)
|
||||
TEXT("HOLE: the op stack claimed %s for the box at (%d,%d,%d) but ")
|
||||
TEXT("EvalMC(%.0f, %.0f, %.0f) = %.6g is on the %s side. One of the ops' ")
|
||||
TEXT("EffectOverBox/ClassifyBox is not conservative. Suspects, in order: ")
|
||||
TEXT("the lattice source's ExtraReach (does it cover the roughness ")
|
||||
TEXT("amplitude AND the carve blend?), then the seal's forcing verdict."),
|
||||
TEXT("the source interval, the SDF roughness interval, the converter's ")
|
||||
TEXT("threshold fold, then the seal's forcing verdict."),
|
||||
bClaimsSolid ? TEXT("AllSolid") : TEXT("AllAir"),
|
||||
Origin.X, Origin.Y, Origin.Z, X, Y, Z, D,
|
||||
(D >= 0.0f) ? TEXT("AIR") : TEXT("SOLID")));
|
||||
@@ -323,12 +325,12 @@ bool FVoxelForgeOpStackMazeTest::RunTest(const FString& Parameters)
|
||||
NumUnsound, 0);
|
||||
|
||||
AddInfo(FString::Printf(
|
||||
TEXT("Box verdicts over 60 Maze tiles (XY sampled from +/- %d voxels = %.1f x ")
|
||||
TEXT("CellSize %.0f): %d proved uniform, %d Mixed. Today's ClassifyTile ")
|
||||
TEXT("Box verdicts over %d Maze tiles (XY sampled from +/- %d voxels = %.1f x ")
|
||||
TEXT("CellSize %.0f): %d proved uniform, %d Mixed, %d voxels checked, %d violations. Today's ClassifyTile ")
|
||||
TEXT("proves ZERO of these -- every cave archetype falls through to \"pas prouvable en ")
|
||||
TEXT("v1\". Any number above zero here is tile-skipping Maze has never had."),
|
||||
SpanVoxels, (float)SpanVoxels / FMath::Max(MazeParams.CellSize, 1.0f), MazeParams.CellSize,
|
||||
NumProved, NumMixed));
|
||||
NumMazeBoxTests, SpanVoxels, (float)SpanVoxels / FMath::Max(MazeParams.CellSize, 1.0f), MazeParams.CellSize,
|
||||
NumProved, NumMixed, NumBruteSamples, NumUnsound));
|
||||
|
||||
if (NumProved == 0)
|
||||
{
|
||||
@@ -338,6 +340,86 @@ bool FVoxelForgeOpStackMazeTest::RunTest(const FString& Parameters)
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
// ISOLATION — a source with a converter it was never authored with
|
||||
//==========================================================================
|
||||
// Maze's hand-written stack uses ConstantRock -> Lattice -> SdfRoughness -> SdfCarve.
|
||||
// This stack deliberately uses a VOID root and SdfFill instead. The only way it may
|
||||
// claim AllAir is for the propagated lattice/roughness interval to prove that the fill
|
||||
// converter is inactive over the whole box. A source that still answered for its old
|
||||
// carve neighbour would not be a valid implementation of this test.
|
||||
{
|
||||
FMazeGenerationParams NovelParams = MazeParams;
|
||||
NovelParams.BranchProbability = 0.12f;
|
||||
NovelParams.Verticality = 0.08f;
|
||||
NovelParams.CorridorRadius = 1.0f;
|
||||
|
||||
FVoxelOpStack NovelStack;
|
||||
NovelStack.Add(VoxelDensityOps::MakeConstantVoidSource(NovelParams.BaseDensity));
|
||||
NovelStack.Add(VoxelDensityOps::MakeLatticeCorridorSource(NovelParams, World.Settings->Seed));
|
||||
NovelStack.Add(VoxelDensityOps::MakeSdfRoughnessMod(
|
||||
0.35f, 0.12f, 3, NovelParams.CorridorRadius + 2.0f));
|
||||
NovelStack.Add(VoxelDensityOps::MakeSdfFill(1.25f, NovelParams.BaseDensity));
|
||||
NovelStack.PrepareChunk(Ctx);
|
||||
|
||||
FString ChannelError;
|
||||
TestTrue(TEXT("the unverified source/converter stack has a valid channel order"),
|
||||
NovelStack.ValidateChannelOrder(&ChannelError));
|
||||
if (!ChannelError.IsEmpty()) { AddError(ChannelError); }
|
||||
|
||||
constexpr int32 NumNovelBoxTests = 256;
|
||||
const int32 NovelSpanCells = 160;
|
||||
const int32 NovelSpanVoxels = NovelSpanCells * 8;
|
||||
int32 NumNovelSolid = 0, NumNovelAir = 0, NumNovelMixed = 0;
|
||||
int32 NumNovelVoxels = 0, NumNovelViolations = 0;
|
||||
FRandomStream NovelRng(86420);
|
||||
|
||||
for (int32 t = 0; t < NumNovelBoxTests; ++t)
|
||||
{
|
||||
const int32 Step = 1, Cells = 8;
|
||||
const int32 Extent = Step * Cells;
|
||||
const FIntVector Origin(
|
||||
NovelRng.RandRange(-NovelSpanCells, NovelSpanCells) * Extent,
|
||||
NovelRng.RandRange(-NovelSpanCells, NovelSpanCells) * Extent,
|
||||
FMath::Clamp(NovelRng.RandRange(BottomVoxelZ / Extent, TopVoxelZ / Extent), -4096, 4096) * Extent);
|
||||
const int32 GridDim = Cells + 1;
|
||||
const FBox Box(
|
||||
FVector(Origin.X - Step, Origin.Y - Step, Origin.Z - Step),
|
||||
FVector(Origin.X + GridDim * Step, Origin.Y + GridDim * Step, Origin.Z + GridDim * Step));
|
||||
|
||||
const EVoxelTileClass Verdict = NovelStack.ClassifyBox(Box, Ctx);
|
||||
if (Verdict == EVoxelTileClass::Mixed)
|
||||
{
|
||||
++NumNovelMixed;
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool bClaimsSolid = (Verdict == EVoxelTileClass::AllSolid);
|
||||
if (bClaimsSolid) { ++NumNovelSolid; } else { ++NumNovelAir; }
|
||||
|
||||
// No sampled subset: every lattice point in every proved box is checked.
|
||||
for (int32 gz = -1; gz <= GridDim; ++gz)
|
||||
for (int32 gy = -1; gy <= GridDim; ++gy)
|
||||
for (int32 gx = -1; gx <= GridDim; ++gx)
|
||||
{
|
||||
const float X = (float)(Origin.X + gx * Step);
|
||||
const float Y = (float)(Origin.Y + gy * Step);
|
||||
const float Z = (float)(Origin.Z + gz * Step);
|
||||
const float D = NovelStack.EvalMC(X, Y, Z);
|
||||
++NumNovelVoxels;
|
||||
if (bClaimsSolid ? (D >= 0.0f) : (D < 0.0f)) { ++NumNovelViolations; }
|
||||
}
|
||||
}
|
||||
|
||||
TestEqual(TEXT("the unverified source/converter stack has zero box-verdict violations"),
|
||||
NumNovelViolations, 0);
|
||||
AddInfo(FString::Printf(
|
||||
TEXT("Novel lattice+roughness+FILL stack: %d boxes proved (%d AllSolid, %d AllAir), " )
|
||||
TEXT("%d Mixed; %d voxels checked, %d violations; XY sampled from +/- %d voxels."),
|
||||
NumNovelSolid + NumNovelAir, NumNovelSolid, NumNovelAir, NumNovelMixed,
|
||||
NumNovelVoxels, NumNovelViolations, NovelSpanVoxels));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ bool FVoxelForgeOpStackShaftTest::RunTest(const FString& Parameters)
|
||||
// 3. LE VERDICT DE BOÎTE
|
||||
//=========================================================================
|
||||
{
|
||||
int32 NumProved = 0, NumMixed = 0, NumUnsound = 0;
|
||||
int32 NumProved = 0, NumMixed = 0, NumUnsound = 0, NumBruteSamples = 0;
|
||||
FRandomStream Rng(13579);
|
||||
// Hors de la boucle : la ligne de rapport en a besoin. Une étendue d'échantillonnage qu'on
|
||||
// ne peut pas citer dans le rapport est une étendue que personne ne surveille.
|
||||
@@ -292,6 +292,7 @@ bool FVoxelForgeOpStackShaftTest::RunTest(const FString& Parameters)
|
||||
const float Y = (float)(Origin.Y + gy * Step);
|
||||
const float Z = (float)(Origin.Z + gz * Step);
|
||||
const float D = Stack.EvalMC(X, Y, Z);
|
||||
++NumBruteSamples;
|
||||
if (bClaimsSolid ? (D >= 0.0f) : (D < 0.0f))
|
||||
{
|
||||
if (NumUnsound == 0)
|
||||
@@ -299,8 +300,8 @@ bool FVoxelForgeOpStackShaftTest::RunTest(const FString& Parameters)
|
||||
AddError(FString::Printf(
|
||||
TEXT("HOLE: the shaft stack claimed %s for the box at (%d,%d,%d) but ")
|
||||
TEXT("EvalMC(%.0f, %.0f, %.0f) = %.6g is on the %s side. Suspects, in ")
|
||||
TEXT("order: the shaft source's ExtraReach (does it cover the roughness ")
|
||||
TEXT("amplitude AND the carve blend?), then the connector sweep (a ")
|
||||
TEXT("order: the shaft source's SDF interval (does it cover all shaft ")
|
||||
TEXT("and connector geometry?), then the connector sweep (a ")
|
||||
TEXT("connector can reach Spacing*1.6 beyond its cell), then the ledge ")
|
||||
TEXT("op's FillOnly."),
|
||||
bClaimsSolid ? TEXT("AllSolid") : TEXT("AllAir"),
|
||||
@@ -317,22 +318,22 @@ bool FVoxelForgeOpStackShaftTest::RunTest(const FString& Parameters)
|
||||
|
||||
AddInfo(FString::Printf(
|
||||
TEXT("Box verdicts over 60 VerticalShafts tiles (XY sampled from +/-%d voxels = %.1f x ")
|
||||
TEXT("ShaftSpacing %.0f): %d proved uniform, %d Mixed, brute-forced with %d violations. ")
|
||||
TEXT("ShaftSpacing %.0f): %d proved uniform, %d Mixed, %d voxels checked, %d violations. ")
|
||||
TEXT("This was 0 proved for as long as the connector branch bailed on mere shaft ")
|
||||
TEXT("EXISTENCE within Spacing*1.6 -- true almost everywhere at ShaftDensity 0.6, so it ")
|
||||
TEXT("was conservative AND sterile. It now tests the real connector capsules. Read the ")
|
||||
TEXT("proved count as a measurement; what is ASSERTED is that none of them is wrong, ")
|
||||
TEXT("because a false verdict here leaves no geometry and no collision."),
|
||||
SpanVoxels, (float)SpanVoxels / FMath::Max(P.ShaftSpacing, 1.0f), P.ShaftSpacing,
|
||||
NumProved, NumMixed, NumUnsound));
|
||||
NumProved, NumMixed, NumBruteSamples, NumUnsound));
|
||||
|
||||
if (NumProved == 0)
|
||||
{
|
||||
AddWarning(TEXT("No VerticalShafts tile was proved, so the brute force above verified ")
|
||||
TEXT("nothing. Before hypothesising: the shaft CIRCLE test and the connector ")
|
||||
TEXT("CAPSULE test are the only two things that can return CarveOnly here, ")
|
||||
TEXT("and ExtraReach inflates both -- check its value against ShaftMaxRadius ")
|
||||
TEXT("before touching either test."));
|
||||
TEXT("and the interval must cover both the shaft and connector capsules before ")
|
||||
TEXT("either test is relaxed."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ bool FVoxelForgeOpStackSlabTest::RunTest(const FString& Parameters)
|
||||
// 3. LE VERDICT DE BOÎTE — ce que §3.1 a acheté
|
||||
//=====================================================================
|
||||
{
|
||||
int32 NumProved = 0, NumMixed = 0, NumUnsound = 0;
|
||||
int32 NumProved = 0, NumMixed = 0, NumUnsound = 0, NumBruteSamples = 0;
|
||||
FRandomStream Rng(24680 + SlotIndex);
|
||||
// Hors de la boucle : la ligne de rapport en a besoin. Une étendue d'échantillonnage qu'on
|
||||
// ne peut pas citer dans le rapport est une étendue que personne ne surveille.
|
||||
@@ -312,6 +312,7 @@ bool FVoxelForgeOpStackSlabTest::RunTest(const FString& Parameters)
|
||||
const float Y = (float)(Origin.Y + gy * Step);
|
||||
const float Z = (float)(Origin.Z + gz * Step);
|
||||
const float D = Stack.EvalMC(X, Y, Z);
|
||||
++NumBruteSamples;
|
||||
if (bClaimsSolid ? (D >= 0.0f) : (D < 0.0f))
|
||||
{
|
||||
if (NumUnsound == 0)
|
||||
@@ -320,7 +321,7 @@ bool FVoxelForgeOpStackSlabTest::RunTest(const FString& Parameters)
|
||||
TEXT("HOLE: %s claimed %s for the box at (%d,%d,%d) but ")
|
||||
TEXT("EvalMC(%.0f, %.0f, %.0f) = %.6g is on the %s side. One of the ")
|
||||
TEXT("ops is not conservative. Suspects, in order: the slab source's ")
|
||||
TEXT("noise amplitude bounds (does FBM really honour [-1,1]?), the ")
|
||||
TEXT("noise amplitude bounds (the proved FBM supremum is 1.5, not 1.0), the ")
|
||||
TEXT("ceiling clamp raising CeilSurface above CeilZ, then the column ")
|
||||
TEXT("mod's reach (MaxRadius + blend)."),
|
||||
SlotName, bClaimsSolid ? TEXT("AllSolid") : TEXT("AllAir"),
|
||||
@@ -340,12 +341,12 @@ bool FVoxelForgeOpStackSlabTest::RunTest(const FString& Parameters)
|
||||
|
||||
AddInfo(FString::Printf(
|
||||
TEXT("%s box verdicts over %d tiles (XY sampled from +/- %d voxels = %.1f x ")
|
||||
TEXT("ColumnSpacing %.0f): %d proved uniform, %d Mixed. Today's ")
|
||||
TEXT("ColumnSpacing %.0f): %d proved uniform, %d Mixed, %d voxels checked, %d violations. Today's ")
|
||||
TEXT("ClassifyTile proves ZERO of these. This number is the whole point of making ")
|
||||
TEXT("the slab surfaces XY-pure (OPSTACK-DECOMPOSITION 3.1)."),
|
||||
SlotName, NumSlabTiles, SpanVoxels,
|
||||
(float)SpanVoxels / FMath::Max(SlabParams.ColumnSpacing, 1.0f), SlabParams.ColumnSpacing,
|
||||
NumProved, NumMixed));
|
||||
NumProved, NumMixed, NumBruteSamples, NumUnsound));
|
||||
|
||||
if (NumProved == 0)
|
||||
{
|
||||
|
||||
@@ -1086,8 +1086,8 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
|
||||
// 4. LE VERDICT DE BOÎTE — plus attendu nul, et CHAQUE VERDICT EST BRUTE-FORCÉ
|
||||
//=========================================================================
|
||||
// ⚠️ CE BLOC A CHANGÉ DE NATURE LE 2026-07-28, ET IL FAUT SAVOIR POURQUOI.
|
||||
// Il ASSERTAIT `NumProved == 0`. C'était juste tant que `FRoomGraphSource::EffectOverBox`
|
||||
// rendait `Both` inconditionnellement : « zéro » était alors une description honnête de l'état
|
||||
// Il ASSERTAIT `NumProved == 0`. C'était juste tant que la source de salles répondait
|
||||
// `Both` inconditionnellement : « zéro » était alors une description honnête de l'état
|
||||
// du portage. Depuis que la source répond SPATIALEMENT, asserter zéro reviendrait à interdire
|
||||
// le gain qu'on vient de construire — et pire, ça transformerait le test en gardien du bug.
|
||||
//
|
||||
@@ -1239,7 +1239,7 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
|
||||
AddInfo(FString::Printf(
|
||||
TEXT("[%s] Box verdicts over 40 TunnelNetwork tiles: %d proved (%d AllSolid, %d AllAir), ")
|
||||
TEXT("%d Mixed -- brute-forced over %d voxels, %d violations. This number was 0 proved / ")
|
||||
TEXT("40 Mixed until FRoomGraphSource::EffectOverBox learned to answer spatially, and it ")
|
||||
TEXT("40 Mixed until the SDF source interval and state-aware fold learned to answer spatially, and it ")
|
||||
TEXT("is the single largest perf item of the whole plan (OPSTACK-DECOMPOSITION 0.2): a ")
|
||||
TEXT("proved tile skips GenerateMesh entirely, so it trades one BuildChunkCache against ")
|
||||
TEXT("30000+ density evaluations. Read the PROVED count as a measurement, never as a ")
|
||||
@@ -1408,6 +1408,11 @@ bool FVoxelForgeOpStackTunnelTest::RunTest(const FString& Parameters)
|
||||
UWCtx.StrateBottomWorldZ = UP.StrateBottomWorldZ;
|
||||
UWStack.PrepareChunk(UWCtx);
|
||||
|
||||
// Underwater shares the tunnel builder, but it is a separate production archetype. Keep
|
||||
// its box proof in the report so a future change cannot silently make only this slot
|
||||
// unsound or sterile.
|
||||
RunTileScan(UWStack, UP, UWCtx, TEXT("Underwater"), /*bZeroProvedIsExpected*/ false);
|
||||
|
||||
TestEqual(TEXT("the Underwater stack is the tunnel stack: same 20 ops"), UWStack.Num(), 20);
|
||||
|
||||
// 8 → 24 chunks, comme le balayage principal. Le premier run vert a rapporté **0 de 2000
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user