fix(physics): fall through to outdoor cell when indoor BSP doesn't contain player (A1.7)
ISSUES #83 Phase A1.7. CellTransit.FindCellList returns currentCellId when no candidate cell's CellBSP contains the sphere center — but this also fires when the player has walked OUTSIDE the entire portal-connected indoor graph (e.g., breached a missing wall poly, walked through a doorway gap). The player's CellId stays stuck on the old indoor cell whose BSP is now far away, NodeIntersects fails at the BSP root for every collision query, and no walls block in their actual location. Probe evidence (launch-stairs.utf8.log, A1.6 verify): - Cell 0xA9B40164: 646 indoor-bsp queries, 644 returned OK (99.7%). No walls firing. - Player local positions in cell 0xA9B40164 ranged X[-0.66..33.18], Y[10.68..63.53] — a 34x53m envelope. The player was geometrically ~62m from the cell's world origin while CellId never updated. Compare to adjacent cells where collision works: - Cell 0xA9B4015A: 230 queries, 32% hit rate - Cell 0xA9B40157: 131 queries, 38% hit rate Fix: after CellTransit.FindCellList returns, verify the resolved cell's CellBSP actually contains the sphere center via BSPQuery.PointInsideCellBsp. If not, fall through to the existing outdoor cell resolution branch (terrain grid + CheckBuildingTransit for re-entry into a different building). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
700abad94c
commit
4679134d66
1 changed files with 26 additions and 1 deletions
|
|
@ -261,7 +261,32 @@ public sealed class PhysicsEngine
|
|||
// Indoor branch needs DataCache to look up cells; outdoor uses
|
||||
// _landblocks (no DataCache dependency).
|
||||
if (DataCache is null) return fallbackCellId;
|
||||
return CellTransit.FindCellList(DataCache, worldPos, sphereRadius, fallbackCellId);
|
||||
uint indoorResult = CellTransit.FindCellList(DataCache, worldPos, sphereRadius, fallbackCellId);
|
||||
|
||||
// ISSUES #83 / Phase A1.7 (2026-05-21): verify the indoor result
|
||||
// actually contains the player. CellTransit.FindCellList falls back
|
||||
// to currentCellId when no candidate cell's CellBSP contains the
|
||||
// sphere center — but this happens even when the player has walked
|
||||
// OUTSIDE the entire portal-connected indoor cell graph (e.g.,
|
||||
// exited through an unblocked wall or doorway gap). In that state
|
||||
// the player's CellId is stuck on an indoor cell whose BSP is
|
||||
// far away, every indoor-bsp query returns OK (NodeIntersects
|
||||
// fails at root), and no walls block.
|
||||
//
|
||||
// If the resolved indoor cell's BSP does NOT contain the sphere
|
||||
// center, fall through to the outdoor cell resolution below — it
|
||||
// will compute the correct landcell from the terrain grid and
|
||||
// optionally re-enter an indoor cell via CheckBuildingTransit.
|
||||
var indoorCell = DataCache.GetCellStruct(indoorResult);
|
||||
if (indoorCell?.CellBSP?.Root is null)
|
||||
return indoorResult; // Can't verify (no CellBSP); trust FindCellList.
|
||||
|
||||
var localCenter = Vector3.Transform(worldPos, indoorCell.InverseWorldTransform);
|
||||
if (BSPQuery.PointInsideCellBsp(indoorCell.CellBSP.Root, localCenter))
|
||||
return indoorResult;
|
||||
|
||||
// Fall through to outdoor resolution: player has left the indoor
|
||||
// portal-connected graph entirely.
|
||||
}
|
||||
|
||||
// Outdoor seed: use terrain grid to compute the prefixed cell id.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue