BR-2 task 1: phantom-site probe (ACDREAM_PROBE_PHANTOM)

The BR-1 pre-check left the #113 phantom residual with two surviving
suspects, both cell-side: (a) flood-admitted cells whose shell draws with
a pass-all slice (NoClipSlice fallback when the assembler handed no slot,
or an assembler slot-0 scissor-fallback slice), and (b) cell entity
buckets drawn unclipped + un-viewcone'd by design.

[phantom-shell]: per shell-pass cell, print-on-change - clip-enable
state, slot presence, every drawn slice's slot + plane count with
PASS-ALL flagged. [phantom-objs]: per object-list cell, print-on-change
- entity bucket size. Env-gated ACDREAM_PROBE_PHANTOM=1, zero cost off,
throwaway (strip when the phantom closes).

Repro protocol: launch with the probe on, stand at the hall bisect spot
(world ~216,-108 looking at the AAB3 meeting hall west face) where the
phantom is visible, read which mechanism fires for stair cells
0xAAB30100..0x106. Shells pass-all -> BR-2/BR-3 close it; statics ->
BR-5 closes it.

Build green; App suite green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-11 06:27:44 +02:00
parent 695eca2c1f
commit 6cba95047c
2 changed files with 64 additions and 1 deletions

View file

@ -385,7 +385,15 @@ public sealed class RetailPViewRenderer
_oneCell.Clear();
_oneCell.Add(cellId);
foreach (var slice in GetCellSlicesOrNoClip(clipAssembly, cellId))
var slices = GetCellSlicesOrNoClip(clipAssembly, cellId);
// BR-2 phantom-site probe: which cells draw their shell with a
// pass-all slice (NoClipSlice fallback or assembler slot-0)?
if (AcDream.Core.Rendering.RenderingDiagnostics.ProbePhantomEnabled)
EmitPhantomShellProbe(cellId, slices, clipShells,
hadSlot: clipAssembly.CellIdToViewSlices.ContainsKey(cellId));
foreach (var slice in slices)
{
UseShellClipRouting(cellId, slice);
_envCells.Render(WbRenderPass.Opaque, _oneCell);
@ -417,6 +425,11 @@ public sealed class RetailPViewRenderer
_oneCell.Clear();
_oneCell.Add(cellId);
// BR-2 phantom-site probe: entity buckets draw unclipped +
// un-viewcone'd by design — log the per-cell exposure.
if (AcDream.Core.Rendering.RenderingDiagnostics.ProbePhantomEnabled)
EmitPhantomObjsProbe(cellId, bucket.Count);
UseIndoorMembershipOnlyRouting();
DrawEntityBucket(ctx, bucket, _oneCell);
@ -425,6 +438,38 @@ public sealed class RetailPViewRenderer
}
}
// BR-2 phantom-site probe state: print-on-change per cell so the log stays
// diffable while the condition persists. Throwaway apparatus — strip when
// the #113 phantom residual closes (plan §BR-2).
private readonly Dictionary<uint, string> _phantomShellSig = new();
private readonly Dictionary<uint, int> _phantomObjsSig = new();
private void EmitPhantomShellProbe(uint cellId, ClipViewSlice[] slices, bool clipShells, bool hadSlot)
{
var sb = new System.Text.StringBuilder(96);
sb.Append(clipShells ? "clip=on" : "clip=OFF");
sb.Append(hadSlot ? " slot=yes" : " slot=NONE(pass-all)");
sb.Append(" slices=[");
for (int i = 0; i < slices.Length; i++)
{
if (i > 0) sb.Append(',');
sb.Append(slices[i].Slot).Append(':').Append(slices[i].Planes.Length).Append("pl");
if (slices[i].Slot == 0) sb.Append("(PASS-ALL)");
}
sb.Append(']');
var sig = sb.ToString();
if (_phantomShellSig.TryGetValue(cellId, out var prev) && prev == sig) return;
_phantomShellSig[cellId] = sig;
Console.WriteLine($"[phantom-shell] cell=0x{cellId:X8} {sig}");
}
private void EmitPhantomObjsProbe(uint cellId, int bucketCount)
{
if (_phantomObjsSig.TryGetValue(cellId, out var prev) && prev == bucketCount) return;
_phantomObjsSig[cellId] = bucketCount;
Console.WriteLine($"[phantom-objs] cell=0x{cellId:X8} entities={bucketCount} (drawn unclipped, no viewcone)");
}
private static ClipViewSlice[] GetCellSlicesOrNoClip(
ClipFrameAssembly clipAssembly,
uint cellId)