test(gate): stress repro judges terrain penetration -- gate on 10/10 clear, gate off 3/3 falls through

The old criteria (travel distance) could not tell a working gate from a broken one: every run,
gate on or off, ended at (455.7, 0, -58.1). That spot is measured air ~1.2 m above a real floor
(density zero-crossing at world Z ~ -275.7 cm), so it is a terrain trap, not a fall-through.

The stress test now drops the pawn fast onto an unready support tile (0,0,-1) and samples the
density at the capsule feet every frame, sweeping at <= half a voxel between positions. PASS =
no measured clearance below -5 cm.

Owner config (radius 3, max level 6, distance 768, sheets off):
- gate on: 10/10 PASS, min clearance +120.5..+120.9 cm, one hold of 0.43-0.47 s each,
  support submitted in ~0.7 ms, collision ready in 0.43-0.47 s
- gate off: 3/3 FAIL terrain_penetration, clearance -5.7..-8.1 cm
Edit-ghost, clipmap no-overlap sweep: pass. Test-harness code only; no production path changed.
This validates a49725d.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-09-25 06:11:08 +02:00
1 parent a49725d365
commit 6ee433efa5
4 files changed
+657 -68

No files matched your search

+21 -1
View File
@@ -548,6 +548,10 @@ private:
void AdvanceHeadlessCollisionGateStressTest(FVector& InOutPlayerPosition,
FVector& InOutPlayerHeading, APawn* PlayerPawn);
void ObserveHeadlessCollisionGateStressTest(const FVector& PlayerPosition, APawn* PlayerPawn);
bool MeasureHeadlessCollisionGateStressTerrain(
const FVector& WorldPosition, float CapsuleHalfHeightCm,
float& OutFeetDensity, float& OutCenterDensity,
float& OutSurfaceLocalVoxelZ, float& OutClearanceCm) const;
void AdvanceHeadlessSurfaceFallTest(FVector& InOutPlayerPosition,
FVector& InOutPlayerHeading, APawn* PlayerPawn);
void InitializeHeadlessStrateCrossingTest();
@@ -1109,12 +1113,17 @@ public:
bool bHeadlessCollisionGateStressTestExitRequested = false;
bool bHeadlessCollisionGateStressTestGateWasEngaged = false;
bool bHeadlessCollisionGateStressTestFullStop = false;
bool bHeadlessCollisionGateStressTestStartHeightCrossed = false;
bool bHeadlessCollisionGateStressTestTerrainViolation = false;
bool bHeadlessCollisionGateStressTestTerrainMeasurementMissing = false;
bool bHeadlessCollisionGateStressTestLanded = false;
bool bHeadlessCollisionGateStressTestLaunchSupportTimingCaptured = false;
float HeadlessCollisionGateStressTestSpeedCmPerSecond = 6000.0f;
float HeadlessCollisionGateStressTestStartDelaySeconds = 0.1f;
float HeadlessCollisionGateStressTestDurationSeconds = 2.0f;
float HeadlessCollisionGateStressTestTimeoutSeconds = 15.0f;
double HeadlessCollisionGateStressTestBeginSeconds = 0.0;
double HeadlessCollisionGateStressTestStartSeconds = 0.0;
double HeadlessCollisionGateStressTestLandedSeconds = 0.0;
double HeadlessCollisionGateStressTestGateStartSeconds = 0.0;
double HeadlessCollisionGateStressTestFullStopStartSeconds = 0.0;
double HeadlessCollisionGateStressTestDistanceCm = 0.0;
@@ -1122,10 +1131,21 @@ public:
double HeadlessCollisionGateStressTestTotalGateDurationSeconds = 0.0;
double HeadlessCollisionGateStressTestMaxGateDurationSeconds = 0.0;
double HeadlessCollisionGateStressTestFullStopDurationSeconds = 0.0;
double HeadlessCollisionGateStressTestLaunchSupportCheckSeconds = 0.0;
double HeadlessCollisionGateStressTestLaunchSupportSubmittedSeconds = 0.0;
double HeadlessCollisionGateStressTestLaunchSupportReadySeconds = 0.0;
double HeadlessCollisionGateStressTestMinClearanceCm = 1.0e30;
float HeadlessCollisionGateStressTestMinFeetDensity = 0.0f;
float HeadlessCollisionGateStressTestMinSurfaceLocalVoxelZ = 0.0f;
int32 HeadlessCollisionGateStressTestTerrainSampleCount = 0;
int32 HeadlessCollisionGateStressTestTraceFrame = 0;
int32 HeadlessCollisionGateStressTestGateHoldCount = 0;
int32 HeadlessCollisionGateStressTestFullStopCount = 0;
FVector HeadlessCollisionGateStressTestDirection = FVector::XAxisVector;
FVector HeadlessCollisionGateStressTestLastActualPosition = FVector::ZeroVector;
FVector HeadlessCollisionGateStressTestStartPosition = FVector::ZeroVector;
FVector HeadlessCollisionGateStressTestMinClearancePosition = FVector::ZeroVector;
FVoxelTileKey HeadlessCollisionGateStressTestLaunchSupportTile;
FString HeadlessCollisionGateStressTestFailureReason;
// Explicit owner-layout collision-gate repro. This is a command-line-only harness path: it