diag(phys): [bsp-test] probe + grounded apparatus test + handoff
Visual verification of Task 7 ship: doors block at dead-center (the small Cylinder catches) but the BSP slab doesn't catch off-center or inside-walking-out approaches. Probe-instrumented live capture proves multi-part registration is correct — every door spawns with shapes=cyl1+bsp1, and the BSP part is visited 135 times for a single door at player approaches as close as 0.42 m, with cacheHit=True. But zero [resolve-bldg] attributions for the BSP shape. Three artifacts added: 1. TransitionTypes.cs — new [bsp-test] probe in the BSP collision dispatch, fires BEFORE the cache lookup. Mirrors [cyl-test] on the Cylinder branch. Distinguishes "cache miss → silent skip" from "queried but no hit" (the latter doesn't show up in [resolve-bldg] which only fires on attributed hits). 2. DoorCollisionApparatusTests.cs — new grounded test (Apparatus_Grounded_50cmOffCenter_*) attempts to reproduce the production bug via a seeded PhysicsBody (Contact + OnWalkable + ContactPlane + WalkablePolygon). Currently doesn't reproduce because the apparatus's stub-terrain + synthetic-floor setup diverges from production's real Holtburg geometry. Captured as "documents-the-bug" — flip the assertion shape when the fix lands. 3. docs/research/2026-05-24-door-collision-task7-shipped-but-bug-remains.md — full session handoff. Identifies the remaining bug as a Path 5 (Contact branch + StepSphereUp) misbehavior at thin tall obstacles, not in the multi-part registration we just shipped. Leading hypothesis: DoStepUp's downward probe finds the same flat floor on the OTHER side of the door (Holtburg cottages have no Z change between exterior and interior floor), declares step-up success, BSP collision returns OK, sphere walks through. Recommended next move: relaunch with ACDREAM_DUMP_STEPUP=1 to verify the hypothesis. What this commit DOES NOT do: fix the remaining step-up bug. The A6.P4 multi-part registration foundation is correct and stays. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ca9341c2cb
commit
163a1f0d35
3 changed files with 360 additions and 0 deletions
|
|
@ -199,6 +199,104 @@ public class DoorCollisionApparatusTests
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reproduces the LIVE bug: a grounded player (isOnGround=true with
|
||||
/// seeded ContactPlane) walking off-center toward a closed door
|
||||
/// passes through. The path-difference test: this hits Path 5
|
||||
/// (Contact branch + StepSphereUp), while the other apparatus
|
||||
/// tests above hit Path 6 (Default). If Path 5 incorrectly
|
||||
/// declares step-up success the BSP collision returns OK and the
|
||||
/// sphere walks through — exactly what the user reports in the
|
||||
/// live Holtburg session 2026-05-24.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Apparatus_Grounded_50cmOffCenter_FrontApproach_DocumentsBug()
|
||||
{
|
||||
if (!TryBuildScenario(out var ctx)) return;
|
||||
|
||||
PhysicsDiagnostics.ProbeResolveEnabled = true;
|
||||
PhysicsDiagnostics.ProbeBuildingEnabled = true;
|
||||
Env.SetEnvironmentVariable("ACDREAM_DUMP_STEPUP", "1");
|
||||
|
||||
// Synthetic floor plane at Z = 0 so the grounded sphere has a
|
||||
// walkable plane to rest on. Sphere foot center starts at Z=radius
|
||||
// = 0.48, head at 0.48 + 1.20 = 1.68.
|
||||
var floorPlane = new Plane(0f, 0f, 1f, 0f); // z = 0 plane
|
||||
var floorVerts = new[]
|
||||
{
|
||||
new Vector3( 0f, 0f, 0f),
|
||||
new Vector3(24f, 0f, 0f),
|
||||
new Vector3(24f, 24f, 0f),
|
||||
new Vector3( 0f, 24f, 0f),
|
||||
};
|
||||
|
||||
var body = new PhysicsBody
|
||||
{
|
||||
Position = new Vector3(12.5f, 11f, 0.48f),
|
||||
Orientation = Quaternion.Identity,
|
||||
ContactPlaneValid = true,
|
||||
ContactPlane = floorPlane,
|
||||
ContactPlaneCellId = TestCellId,
|
||||
WalkablePolygonValid = true,
|
||||
WalkablePlane = floorPlane,
|
||||
WalkableVertices = floorVerts,
|
||||
WalkableUp = Vector3.UnitZ,
|
||||
TransientState = TransientStateFlags.Contact | TransientStateFlags.OnWalkable,
|
||||
};
|
||||
|
||||
var perTick = new Vector3(0f, 0.10f, 0f);
|
||||
Vector3 pos = body.Position;
|
||||
uint cellId = TestCellId;
|
||||
bool isOnGround = true;
|
||||
bool blocked = false;
|
||||
Vector3 lastNormal = Vector3.Zero;
|
||||
int ticks = 0;
|
||||
|
||||
for (int tick = 0; tick < 30; tick++)
|
||||
{
|
||||
Vector3 target = pos + perTick;
|
||||
var result = ctx.engine.ResolveWithTransition(
|
||||
pos, target, cellId,
|
||||
SphereRadius, SphereHeight,
|
||||
StepUpHeight, StepDownHeight,
|
||||
isOnGround,
|
||||
body: body,
|
||||
moverFlags: ObjectInfoState.IsPlayer | ObjectInfoState.EdgeSlide,
|
||||
movingEntityId: 0);
|
||||
|
||||
ticks = tick;
|
||||
body.Position = result.Position;
|
||||
pos = result.Position;
|
||||
cellId = result.CellId;
|
||||
isOnGround = result.IsOnGround;
|
||||
lastNormal = result.CollisionNormal;
|
||||
|
||||
if (result.CollisionNormalValid)
|
||||
{
|
||||
blocked = true;
|
||||
_out.WriteLine($"Tick {tick}: BLOCKED at pos=({pos.X:F3},{pos.Y:F3},{pos.Z:F3}) normal=({lastNormal.X:F3},{lastNormal.Y:F3},{lastNormal.Z:F3})");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_out.WriteLine($"Final pos = ({pos.X:F3}, {pos.Y:F3}, {pos.Z:F3}) after {ticks + 1} ticks; blocked={blocked}");
|
||||
_out.WriteLine($"Grounded={isOnGround}");
|
||||
|
||||
// EXPECTED FAILURE (documents-the-bug): the grounded sphere walks
|
||||
// straight through, reaching the far side at Y > 12.30. When the
|
||||
// fix lands, flip this to Assert.True(blocked) — same shape as
|
||||
// the Path-6 apparatus tests above.
|
||||
PhysicsDiagnostics.ProbeResolveEnabled = false;
|
||||
PhysicsDiagnostics.ProbeBuildingEnabled = false;
|
||||
Env.SetEnvironmentVariable("ACDREAM_DUMP_STEPUP", null);
|
||||
|
||||
Assert.True(pos.Y > 12.30f,
|
||||
$"This test documents the production bug. If this is failing " +
|
||||
$"because the sphere now blocks, the door fix worked — flip " +
|
||||
$"the assertion to Assert.True(blocked) and Assert.True(pos.Y < 12.0f). " +
|
||||
$"Current pos=({pos.X:F3},{pos.Y:F3},{pos.Z:F3}) blocked={blocked}");
|
||||
}
|
||||
|
||||
// ───────────────────────────────────────────────────────────────
|
||||
// Apparatus setup
|
||||
// ───────────────────────────────────────────────────────────────
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue