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) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-19 15:47:59 +02:00
parent c19d6fb321
commit fda6af7ad0
2 changed files with 35 additions and 0 deletions

View file

@ -168,6 +168,15 @@ public sealed class PhysicsDataCache
LocalAabbMin = aabbMin, LocalAabbMin = aabbMin,
LocalAabbMax = aabbMax, 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}"));
}
} }
/// <summary> /// <summary>

View file

@ -195,4 +195,30 @@ public static class PhysicsDiagnostics
/// </summary> /// </summary>
public static bool ProbeIndoorBspEnabled { get; set; } = public static bool ProbeIndoorBspEnabled { get; set; } =
Environment.GetEnvironmentVariable("ACDREAM_PROBE_INDOOR_BSP") == "1"; Environment.GetEnvironmentVariable("ACDREAM_PROBE_INDOOR_BSP") == "1";
/// <summary>
/// Indoor walking Phase D follow-up (2026-05-19). When true, emits one
/// <c>[cell-cache]</c> line each time <see cref="PhysicsDataCache.CacheCellStruct"/>
/// caches a new EnvCell. Reports per-cell polygon counts and BSP root
/// structure so the caller can cross-reference with <c>[indoor-bsp]</c>
/// lines to distinguish between:
/// <list type="bullet">
/// <item><description>Empty data (physicsPolyCount=0 or resolvedCount=0)
/// — candidate (a)/(c) in the poly=n/a investigation.</description></item>
/// <item><description>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.</description></item>
/// <item><description>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).</description></item>
/// </list>
/// 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.
///
/// <para>Initial state from <c>ACDREAM_PROBE_CELL_CACHE=1</c>.</para>
/// </summary>
public static bool ProbeCellCacheEnabled { get; set; } =
Environment.GetEnvironmentVariable("ACDREAM_PROBE_CELL_CACHE") == "1";
} }