perf(gen): interval propagation -- blocks can finally be PROVEN empty. 1.55s -> 1.21s

Task 4 ran 11 hours and was killed by system memory pressure before it could file a
report. The work survived, builds clean (0 errors), and is verified faster with
byte-identical output. This commit is my verification, not its summary -- it never
got to write one.

THE STRUCTURAL FIX
0e9df9e established why no block could ever be skipped: OriginSpineOp,
PassageCarveOp and the active seals Lerp/Min/Max against the CURRENT density, so
with an unknown incoming density their supremum is genuinely unbounded. Not a
missing bound -- the operator semantics.

The answer is to propagate a density INTERVAL through the stack, and that is what
landed: FVoxelBoxSdfInterval + PropagateSdfOverBox on the operator interface, an
interval fold through every converter and modifier, interval arithmetic down into
the noise primitives themselves (gradient corners, warp, worm frequencies), and a
BlockSkip lattice the mesher consults per 8^3 block.

Its own guiding comment, which is the right default:
  "no finite interval is a proof. Unknown costs the skip and protects the geometry."

  128^3 TunnelNetwork seed 1337 slot 1, freshly built binary, 3 runs each:
    before  1.515 / 1.554 / 1.569 s
    after   1.213 / 1.258 / 1.171 s     -22.5%, 1.28x -- clears the 17% floor

  Geometry SHA-256 98eaad61..d3c4f IDENTICAL to 0e9df9e. 153,740 triangles either
  way. It skips only provably-empty work; nothing about the world changed.

It also fixed one cause of the 5.6 s empty tiles found in 0e9df9e: an LOD4 tile
legitimately spans 19^3 = 6,859 chunk keys and was rebuilding per-chunk state
thousands of times within a single tile. A shared cache removed that failure mode;
remaining slow empties were LOD0 and are a separate fast-classifier bail, still open.

Partially landed, unfinished when killed: RequestStartCycles on FChunkResult, to
report request-to-ready latency rather than worker generation time. Harmless as is.

⚠️ WHAT KILLED IT, AND IT IS OURS
A single UnrealEditor-Cmd commandlet grew to 19.5 GB, leaving 1.3 GB free on a
32 GB machine, and the OS killed the agent. Freeing it restored 21.6 GB. The owner
said twice that his machine should not be under memory pressure and he was right
both times: first the 411 MiB worker caches, now a 19.5 GB commandlet. A generation
run must not need 19.5 GB. Next task.

Cumulative on this region: 342.2 -> 16.2 -> 2.62 -> 1.49 -> 1.21 s  (~283x).
3,374 insertions / 342 deletions across 12 files. Build 0 errors. Nothing outside
Plugins/VoxelForge; RealtimeMeshComponent untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aheo2crrZmHuYtPpdY2Cb
This commit is contained in:
Fr0zkaandClaude Opus 5 committed 2026-09-09 21:11:13 +02:00
1 parent 0e9df9e5a7
commit d38d4cabef
12 files changed
+3375 -343

No files matched your search

@@ -433,6 +433,73 @@ namespace VoxelPassageGeometry
return MaxA >= MinB && MinA <= MaxB;
}
/** True when the exact MC lattice has at least one sample in a closed interval. */
FORCEINLINE bool LatticeAxisHasSampleInInterval(
float Min, float Max, float Origin, int32 Step)
{
if (Step <= 0 || !FMath::IsFinite(Min) || !FMath::IsFinite(Max)
|| !FMath::IsFinite(Origin) || Min > Max)
{
return false;
}
const float InvStep = 1.0f / static_cast<float>(Step);
const int32 First = FMath::CeilToInt(
(Min - Origin) * InvStep - 1.0e-4f);
const int32 Last = FMath::FloorToInt(
(Max - Origin) * InvStep + 1.0e-4f);
return First <= Last;
}
FORCEINLINE bool OriginLandingRoomTouchesLattice(
const FBox& VoxelBox, const FIntVector& LatticeOrigin, int32 Step,
float StrateTopZ, float StrateBottomZ, float SealThickness, float OriginRadius)
{
if (!VoxelBox.IsValid) return false;
const FOriginLandingGeometry Geometry = BuildOriginLandingGeometry(
StrateTopZ, StrateBottomZ, SealThickness, OriginRadius);
if (!Geometry.bValid) return false;
const float Pad = LandingCarveBlendVoxels;
return LatticeAxisHasSampleInInterval(
FMath::Max((float)VoxelBox.Min.X, -Geometry.HalfWidth - Pad),
FMath::Min((float)VoxelBox.Max.X, Geometry.HalfWidth + Pad),
(float)LatticeOrigin.X, Step)
&& LatticeAxisHasSampleInInterval(
FMath::Max((float)VoxelBox.Min.Y, -Geometry.HalfWidth - Pad),
FMath::Min((float)VoxelBox.Max.Y, Geometry.HalfWidth + Pad),
(float)LatticeOrigin.Y, Step)
&& LatticeAxisHasSampleInInterval(
FMath::Max((float)VoxelBox.Min.Z, Geometry.FloorZ - Pad),
FMath::Min((float)VoxelBox.Max.Z, Geometry.CeilingZ + Pad),
(float)LatticeOrigin.Z, Step);
}
FORCEINLINE bool OriginLandingFloorTouchesLattice(
const FBox& VoxelBox, const FIntVector& LatticeOrigin, int32 Step,
float StrateTopZ, float StrateBottomZ, float SealThickness, float OriginRadius)
{
if (!VoxelBox.IsValid) return false;
const FOriginLandingGeometry Geometry = BuildOriginLandingGeometry(
StrateTopZ, StrateBottomZ, SealThickness, OriginRadius);
if (!Geometry.bValid) return false;
constexpr float ProofPad = 1.0f;
const float FloorHalfWidth = FMath::Max(
Geometry.HalfWidth - 1.0f, 0.0f);
return LatticeAxisHasSampleInInterval(
FMath::Max((float)VoxelBox.Min.X, -FloorHalfWidth - ProofPad),
FMath::Min((float)VoxelBox.Max.X, FloorHalfWidth + ProofPad),
(float)LatticeOrigin.X, Step)
&& LatticeAxisHasSampleInInterval(
FMath::Max((float)VoxelBox.Min.Y, -FloorHalfWidth - ProofPad),
FMath::Min((float)VoxelBox.Max.Y, FloorHalfWidth + ProofPad),
(float)LatticeOrigin.Y, Step)
&& LatticeAxisHasSampleInInterval(
FMath::Max((float)VoxelBox.Min.Z,
Geometry.FloorZ - Geometry.FloorThickness - ProofPad),
FMath::Min((float)VoxelBox.Max.Z, Geometry.FloorZ + ProofPad),
(float)LatticeOrigin.Z, Step);
}
/** Conservative influence box for the origin room's air carve. */
FORCEINLINE bool OriginLandingRoomTouchesBox(
const FBox& VoxelBox,