diff --git a/src/AcDream.Core/Physics/PhysicsDataCache.cs b/src/AcDream.Core/Physics/PhysicsDataCache.cs index 6fd45a4..291aabf 100644 --- a/src/AcDream.Core/Physics/PhysicsDataCache.cs +++ b/src/AcDream.Core/Physics/PhysicsDataCache.cs @@ -174,8 +174,48 @@ public sealed class PhysicsDataCache var root = cellStruct.PhysicsBSP?.Root; int bspRootPolyCount = root?.Polygons?.Count ?? 0; bool bspRootHasChildren = root?.PosNode is not null || root?.NegNode is not null; + + // Recursive walk: count total leaf poly references + how many of + // those poly IDs are absent from the resolved dict. If + // bspTotalLeafPolys == 0 the BSP has no collidable polys at all. + // If bspUnmatchedIds > 0 the BSP references IDs we didn't resolve + // (data-deserialization quirk hypothesis). + int bspTotalLeafPolys = 0; + int bspUnmatchedIds = 0; + if (root is not null) + { + var stack = new System.Collections.Generic.Stack(); + stack.Push(root); + while (stack.Count > 0) + { + var n = stack.Pop(); + if (n.Polygons is not null) + { + foreach (var pid in n.Polygons) + { + bspTotalLeafPolys++; + if (!resolved.ContainsKey(pid)) bspUnmatchedIds++; + } + } + if (n.PosNode is not null) stack.Push(n.PosNode); + if (n.NegNode is not null) stack.Push(n.NegNode); + } + } + + var bs = root?.BoundingSphere; + string bsStr = bs is null + ? "bsphere=n/a" + : System.FormattableString.Invariant( + $"bsphere=({bs.Origin.X:F2},{bs.Origin.Y:F2},{bs.Origin.Z:F2}) r={bs.Radius:F2}"); + + // World origin = cellTransform * (0,0,0,1). Tells us where this cell + // sits in world coordinates, so we can cross-check whether the + // player's worldPos actually lies inside the AABB when transformed + // back to local. + var worldOrigin = Vector3.Transform(Vector3.Zero, worldTransform); + Console.WriteLine(System.FormattableString.Invariant( - $"[cell-cache] envCellId=0x{envCellId:X8} physicsPolyCount={cellStruct.PhysicsPolygons?.Count ?? 0} resolvedCount={resolved.Count} bspRootPolyCount={bspRootPolyCount} bspRootHasChildren={bspRootHasChildren}")); + $"[cell-cache] envCellId=0x{envCellId:X8} physicsPolyCount={cellStruct.PhysicsPolygons?.Count ?? 0} resolvedCount={resolved.Count} bspTotalLeafPolys={bspTotalLeafPolys} bspUnmatchedIds={bspUnmatchedIds} {bsStr} aabbMin=({aabbMin.X:F2},{aabbMin.Y:F2},{aabbMin.Z:F2}) aabbMax=({aabbMax.X:F2},{aabbMax.Y:F2},{aabbMax.Z:F2}) worldOrigin=({worldOrigin.X:F2},{worldOrigin.Y:F2},{worldOrigin.Z:F2})")); } }