test(physics): BSPQuery.FindCollisions writes world-space plane with translated origin
Regression test for indoor BSP world-origin fix (Bug B). Verifies that BSPQuery.FindCollisions with path.StepDown=true and a non-zero worldOrigin parameter writes a world-space ContactPlane to CollisionInfo (not a cell-local-space one). Passes before the call-site fix at TransitionTypes.cs:1442 because BSPQuery itself is correct when called with the right args — it's the caller that was passing the defaults. This test locks in the BSPQuery contract so the relationship between worldOrigin/localToWorld input and ContactPlane.D output cannot regress silently. Spec: docs/superpowers/specs/2026-05-20-indoor-bsp-worldorigin-fix-design.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
56816fcbe4
commit
39d4e6512b
1 changed files with 92 additions and 0 deletions
|
|
@ -418,4 +418,96 @@ public class BSPQueryTests
|
|||
|
||||
Assert.False(found);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// FindCollisions — world-origin / world-rotation correctness (spec 2026-05-20)
|
||||
// =========================================================================
|
||||
|
||||
/// <summary>
|
||||
/// Build a single-leaf BSP with one horizontal floor polygon at the given
|
||||
/// cell-local Z. Vertex array forms a 4x4 m square centered at cell-local
|
||||
/// (0, 0).
|
||||
/// </summary>
|
||||
private static (PhysicsBSPNode root, Dictionary<ushort, ResolvedPolygon> resolved)
|
||||
BuildSingleFloorBsp(float floorZ)
|
||||
{
|
||||
var verts = new[]
|
||||
{
|
||||
new Vector3(-2f, -2f, floorZ),
|
||||
new Vector3( 2f, -2f, floorZ),
|
||||
new Vector3( 2f, 2f, floorZ),
|
||||
new Vector3(-2f, 2f, floorZ),
|
||||
};
|
||||
|
||||
var root = new PhysicsBSPNode
|
||||
{
|
||||
Type = BSPNodeType.Leaf,
|
||||
BoundingSphere = new Sphere
|
||||
{
|
||||
Origin = new Vector3(0f, 0f, floorZ),
|
||||
Radius = 3f,
|
||||
},
|
||||
};
|
||||
root.Polygons.Add(0);
|
||||
|
||||
var resolved = new Dictionary<ushort, ResolvedPolygon>
|
||||
{
|
||||
[0] = new ResolvedPolygon
|
||||
{
|
||||
Vertices = verts,
|
||||
Plane = new Plane(Vector3.UnitZ, -floorZ),
|
||||
NumPoints = 4,
|
||||
SidesType = CullMode.None,
|
||||
},
|
||||
};
|
||||
|
||||
return (root, resolved);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindCollisions_StepDown_TranslatedWorldOrigin_WritesWorldSpacePlane()
|
||||
{
|
||||
// Cell is translated +94 m in world Z (i.e., the cell-local floor at
|
||||
// Z=0 sits at world Z=94). This mirrors the Holtburg cottage scenario
|
||||
// captured in launch-cp-probe.log (cell 0xA9B40150, floor world
|
||||
// Z≈94.02).
|
||||
var (root, resolved) = BuildSingleFloorBsp(floorZ: 0f);
|
||||
|
||||
var transition = new Transition();
|
||||
transition.SpherePath.WalkableAllowance = PhysicsGlobals.FloorZ;
|
||||
transition.SpherePath.WalkInterp = 1.0f;
|
||||
transition.SpherePath.StepDown = true;
|
||||
transition.SpherePath.StepDownAmt = 0.5f;
|
||||
|
||||
// Foot sphere in cell-local space: overlapping the floor (Z=0.4 with
|
||||
// radius 0.48 → dist 0.4 < radius−epsilon = 0.4798, so the precise
|
||||
// overlap test accepts the contact).
|
||||
var localSphere = new Sphere
|
||||
{
|
||||
Origin = new Vector3(0f, 0f, 0.4f),
|
||||
Radius = 0.48f,
|
||||
};
|
||||
|
||||
var state = BSPQuery.FindCollisions(
|
||||
root,
|
||||
resolved,
|
||||
transition,
|
||||
localSphere,
|
||||
localSphere1: null,
|
||||
localCurrCenter: localSphere.Origin,
|
||||
localSpaceZ: Vector3.UnitZ,
|
||||
scale: 1.0f,
|
||||
localToWorld: Quaternion.Identity,
|
||||
engine: null,
|
||||
worldOrigin: new Vector3(0f, 0f, 94f));
|
||||
|
||||
// Path 3 step-down should fire and adjust the sphere onto the floor.
|
||||
Assert.Equal(TransitionState.Adjusted, state);
|
||||
|
||||
// ContactPlane must be in world space: normal stays (0,0,1) since the
|
||||
// cell rotation is identity; D = -world_floor_Z = -94.
|
||||
Assert.True(transition.CollisionInfo.ContactPlaneValid);
|
||||
Assert.Equal(1.0f, transition.CollisionInfo.ContactPlane.Normal.Z, precision: 3);
|
||||
Assert.Equal(-94.0f, transition.CollisionInfo.ContactPlane.D, precision: 2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue