fix(N.5b T7): tighten conformance sample upper bound to 191.975f

Code review identified a latent false-positive flake risk: physics
path clamps fx = localX/24 to (CellsPerSide - 0.001f) = 7.999, which
corresponds to localX <= 191.976. With samples up to 191.999f,
physics computes Z at the clamped position while the mesh sampler
uses the actual position — a difference of up to 23 mm at the upper
edge, which on a steep slope would falsely trip the 1 mm sentinel.

Tighten upper bound to 191.975f (strictly below the clamp boundary)
so both oracles compute Z at the same (cellX, tx). Also restored the
"worst-case from SplitFormulaDivergenceTest" inline comment for
landblock 0x4D96 per code review suggestion #3.

Test still passes: 10/10 landblocks, 1000 samples, max |delta|
= 0.0153 mm (previously 0.0305 mm — confirms the prior worst-case
was indeed at the boundary).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-09 08:59:01 +02:00
parent e54d5ca2cf
commit 4ed79207a6

View file

@ -41,7 +41,7 @@ public class TerrainModernConformanceTests
("Mid-map 0x7F7F", 0x7F, 0x7F),
("MapCorner 0xFEFE", 0xFE, 0xFE),
("Subway outdoor 0x0185", 0x01, 0x85),
("North continent 0x4D96", 0x4D, 0x96),
("North continent 0x4D96", 0x4D, 0x96), // worst-case landblock from SplitFormulaDivergenceTest
};
[Fact]
@ -102,14 +102,19 @@ public class TerrainModernConformanceTests
var surfaceCache = new Dictionary<uint, SurfaceInfo>();
var meshData = LandblockMesh.Build(landblock, lbX, lbY, heightTable, ctx, surfaceCache);
// Sample 100 (localX, localY) points uniformly in [0, 192).
// We avoid the exact upper bound (192) because that maps to
// cell index 8 which the physics path clamps; the pure mesh
// sampler doesn't have triangles past 192 anyway.
// Sample 100 (localX, localY) points uniformly in [0, 191.975].
// The physics path clamps fx = localX/24 to (CellsPerSide - 0.001f)
// = 7.999, which corresponds to localX <= 7.999 * 24 = 191.976.
// Sampling beyond that boundary makes physics compute Z at the
// clamped position while the mesh sampler uses the actual
// position — a difference of up to 23 mm at the upper edge,
// which on a steep slope would falsely trip the 1 mm sentinel.
// Stay strictly below the clamp boundary so both oracles
// compute Z at the same (cellX, tx).
for (int s = 0; s < 100; s++)
{
float lx = (float)rng.NextDouble() * 191.999f;
float ly = (float)rng.NextDouble() * 191.999f;
float lx = (float)rng.NextDouble() * 191.975f;
float ly = (float)rng.NextDouble() * 191.975f;
float meshZ = SampleMeshZ(meshData, lx, ly);
float physicsZ = TerrainSurface.SampleZFromHeightmap(