fix(physics): use horizontal distance for cylinder broad-phase
The broad-phase rejection was using 3D distance for cylinder objects, which includes the Z offset between player feet and cylinder base. Trees have their origin at the base (Z=ground) while the player sphere is at chest height (Z=ground+~2.5m). The 3D distance exceeded the combined radius, causing the collision test to be skipped entirely. Fix: use horizontal (XY) distance for cylinder broad-phase since the vertical extent is checked separately in the cylinder test. Also increase broad-phase margin from 1m to 2m. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
efd6a06c7d
commit
4d335c74da
1 changed files with 11 additions and 6 deletions
|
|
@ -657,8 +657,14 @@ public sealed class Transition
|
|||
foreach (var obj in _nearbyObjs)
|
||||
{
|
||||
// Broad-phase: can the moving sphere reach this object?
|
||||
float distToCurr = Vector3.Distance(currPos, obj.Position);
|
||||
float maxReach = sphereRadius + obj.Radius + movement.Length() + 1f;
|
||||
// Use horizontal distance for cylinders (Z extent is checked separately).
|
||||
Vector3 deltaToCurr = currPos - obj.Position;
|
||||
float distToCurr;
|
||||
if (obj.CollisionType == ShadowCollisionType.Cylinder)
|
||||
distToCurr = MathF.Sqrt(deltaToCurr.X * deltaToCurr.X + deltaToCurr.Y * deltaToCurr.Y);
|
||||
else
|
||||
distToCurr = deltaToCurr.Length();
|
||||
float maxReach = sphereRadius + obj.Radius + movement.Length() + 2f;
|
||||
if (distToCurr > maxReach)
|
||||
continue;
|
||||
|
||||
|
|
@ -755,14 +761,13 @@ public sealed class Transition
|
|||
|
||||
if (bestT >= float.MaxValue)
|
||||
{
|
||||
// Debug: log nearby objects that didn't trigger collision
|
||||
if (_debugMissCounter++ % 120 == 0)
|
||||
if (_debugMissCounter++ % 120 == 0 && _nearbyObjs.Count > 0)
|
||||
{
|
||||
foreach (var obj in _nearbyObjs)
|
||||
{
|
||||
float d = Vector3.Distance(checkPos, obj.Position);
|
||||
if (d < 3f)
|
||||
Console.WriteLine($"NEAR: obj {obj.EntityId:X8} gfx={obj.GfxObjId:X8} type={obj.CollisionType} dist={d:F2} r={obj.Radius:F2} cylH={obj.CylHeight:F2} pos={obj.Position}");
|
||||
float hd = MathF.Sqrt((checkPos.X-obj.Position.X)*(checkPos.X-obj.Position.X)+(checkPos.Y-obj.Position.Y)*(checkPos.Y-obj.Position.Y));
|
||||
Console.WriteLine($"MISS: eid={obj.EntityId:X8} gfx={obj.GfxObjId:X8} type={obj.CollisionType} dist={d:F2} hdist={hd:F2} r={obj.Radius:F2} cylH={obj.CylHeight:F1} playerZ={checkPos.Z:F1} objZ={obj.Position.Z:F1} player=({checkPos.X:F1},{checkPos.Y:F1}) obj=({obj.Position.X:F1},{obj.Position.Y:F1})");
|
||||
}
|
||||
}
|
||||
return TransitionState.OK;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue