From fda6af7ad00d858eadafdac47e7a7576f9df38a2 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 19 May 2026 15:47:59 +0200 Subject: [PATCH] diag: add ACDREAM_PROBE_CELL_CACHE to explain indoor BSP poly=n/a Every [indoor-bsp] probe line reports result=OK poly=n/a, meaning BSPQuery.FindCollisions never records a hit polygon. Four hypotheses: (a) PhysicsPolygons.Count == 0 for all cached EnvCells (empty data), (b) BSP leaf Polygons IDs don't match PhysicsPolygons dict keys, (c) ResolvePolygons filters out all polygons (vertex lookups fail or degenerate normals), or (d) sphere is too far from BSP leaf bounds. Format analysis rules out (b): retail BSPLEAF::PackLeaf writes poly_id (not array index) into the BSP leaf ushort list; CPolygon::Pack writes poly_id as first field; DatReaderWriter reads it as dictionary key. ACE DatLoader does the same. Keys are consistent end-to-end. Add ProbeCellCacheEnabled (ACDREAM_PROBE_CELL_CACHE=1) to PhysicsDiagnostics and a [cell-cache] log line at the end of CacheCellStruct. One line per cached EnvCell: [cell-cache] envCellId=0x... physicsPolyCount=N resolvedCount=M bspRootPolyCount=K bspRootHasChildren=true|false physicsPolyCount=0 -> hypothesis (a). resolvedCount < physicsPolyCount -> hypothesis (c). Non-zero counts + bspRootPolyCount=0 + bspRootHasChildren=true -> expected (internal node, leaves hold poly refs); then investigate (d). Non-zero counts + bspRootPolyCount=0 + bspRootHasChildren=false -> leaf with empty Polygons list, deeper investigation needed. Cross-referencing cell-cache lines with indoor-bsp lines (same envCellId) will pin the root cause in the next launch. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/AcDream.Core/Physics/PhysicsDataCache.cs | 9 +++++++ .../Physics/PhysicsDiagnostics.cs | 26 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/AcDream.Core/Physics/PhysicsDataCache.cs b/src/AcDream.Core/Physics/PhysicsDataCache.cs index 3f89793..6fd45a4 100644 --- a/src/AcDream.Core/Physics/PhysicsDataCache.cs +++ b/src/AcDream.Core/Physics/PhysicsDataCache.cs @@ -168,6 +168,15 @@ public sealed class PhysicsDataCache LocalAabbMin = aabbMin, LocalAabbMax = aabbMax, }; + + if (PhysicsDiagnostics.ProbeCellCacheEnabled) + { + var root = cellStruct.PhysicsBSP?.Root; + int bspRootPolyCount = root?.Polygons?.Count ?? 0; + bool bspRootHasChildren = root?.PosNode is not null || root?.NegNode is not null; + Console.WriteLine(System.FormattableString.Invariant( + $"[cell-cache] envCellId=0x{envCellId:X8} physicsPolyCount={cellStruct.PhysicsPolygons?.Count ?? 0} resolvedCount={resolved.Count} bspRootPolyCount={bspRootPolyCount} bspRootHasChildren={bspRootHasChildren}")); + } } /// diff --git a/src/AcDream.Core/Physics/PhysicsDiagnostics.cs b/src/AcDream.Core/Physics/PhysicsDiagnostics.cs index bb49b20..05935e8 100644 --- a/src/AcDream.Core/Physics/PhysicsDiagnostics.cs +++ b/src/AcDream.Core/Physics/PhysicsDiagnostics.cs @@ -195,4 +195,30 @@ public static class PhysicsDiagnostics /// public static bool ProbeIndoorBspEnabled { get; set; } = Environment.GetEnvironmentVariable("ACDREAM_PROBE_INDOOR_BSP") == "1"; + + /// + /// Indoor walking Phase D follow-up (2026-05-19). When true, emits one + /// [cell-cache] line each time + /// caches a new EnvCell. Reports per-cell polygon counts and BSP root + /// structure so the caller can cross-reference with [indoor-bsp] + /// lines to distinguish between: + /// + /// Empty data (physicsPolyCount=0 or resolvedCount=0) + /// — candidate (a)/(c) in the poly=n/a investigation. + /// Non-zero polygon counts but bspRootPolyCount=0 at + /// root + tree has children — correct structure for non-leaf root, + /// leaves hold the poly refs; not a bug. + /// Non-zero polygon counts but bspRootPolyCount=0 at + /// root AND root is a leaf (bspRootHasChildren=false) — BSP leaf with + /// zero poly refs, candidate (b)/(d). + /// + /// This diagnostic fires at most once per EnvCell (cache is no-op after + /// first population). It does NOT have a DebugPanel mirror yet — this is + /// a one-shot capture tool, not a persistent toggle. Promote to full + /// infrastructure after the root cause is identified. + /// + /// Initial state from ACDREAM_PROBE_CELL_CACHE=1. + /// + public static bool ProbeCellCacheEnabled { get; set; } = + Environment.GetEnvironmentVariable("ACDREAM_PROBE_CELL_CACHE") == "1"; }