From a974504e6e2c264d31ead1d5993b431a6f4297e7 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 11 Jun 2026 18:41:05 +0200 Subject: [PATCH] #119-residual: [viewer] capture probe - the capture half of the tower capture-replay loop One line per change of (root cell, flood size, OutsideView polys, player cell), with the projection eye at mm precision on every line (ACDREAM_PROBE_VIEWER=1, print-on-change, silent while stable). The tower-ascent harness replays the captured production (eye, root) pairs deterministically - replacing the synthetic helix that proved unphysical in the roof-lip band (the real collided camera may never reach it). Suites: App 238+1skip, Core 1422+2skip, UI 420, Net 294. Co-Authored-By: Claude Fable 5 --- src/AcDream.App/Rendering/GameWindow.cs | 19 +++++++++++++++++++ .../Rendering/RenderingDiagnostics.cs | 13 +++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 9881d15b..97b22e5f 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -9669,6 +9669,10 @@ public sealed class GameWindow : IDisposable DisableClipDistances(); } + // #119-residual [viewer] probe state: print-on-change signature so a + // stable climb is silent and every flood/root flip emits exactly one line. + private string? _lastViewerProbeSig; + private void EmitRetailPViewDiagnostics( AcDream.App.Rendering.RetailPViewFrameResult result, LoadedCell clipRoot, @@ -9677,6 +9681,21 @@ public sealed class GameWindow : IDisposable System.Numerics.Vector3 camPos, System.Numerics.Vector3 playerViewPos) { + // #119-residual: the capture half of the tower capture→replay loop. + // One line per change of (root, flood, outPolys, playerCell); the eye + // at mm precision rides every line so the harness can replay the + // exact production (eye, root) pairs. ACDREAM_PROBE_VIEWER=1. + if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeViewerEnabled) + { + string sig = System.FormattableString.Invariant( + $"root=0x{clipRoot.CellId:X8}{(clipRoot.IsOutdoorNode ? "(OUT)" : "")} flood={result.PortalFrame.OrderedVisibleCells.Count} outPolys={result.PortalFrame.OutsideView.Polygons.Count} pCell=0x{playerCellId:X8}"); + if (sig != _lastViewerProbeSig) + { + _lastViewerProbeSig = sig; + Console.WriteLine(System.FormattableString.Invariant( + $"[viewer] {sig} eye=({camPos.X:F3},{camPos.Y:F3},{camPos.Z:F3}) viewerCell=0x{viewerCellId:X8}")); + } + } if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeVisibilityEnabled) AcDream.Core.Rendering.RenderingDiagnostics.EmitVis( clipRoot.CellId, diff --git a/src/AcDream.Core/Rendering/RenderingDiagnostics.cs b/src/AcDream.Core/Rendering/RenderingDiagnostics.cs index 7e77496b..49302d9c 100644 --- a/src/AcDream.Core/Rendering/RenderingDiagnostics.cs +++ b/src/AcDream.Core/Rendering/RenderingDiagnostics.cs @@ -96,6 +96,19 @@ public static class RenderingDiagnostics public static bool ProbeVisibilityEnabled { get; set; } = Environment.GetEnvironmentVariable("ACDREAM_PROBE_VIS") == "1"; + /// + /// #119-residual viewer/flood capture (2026-06-11): one [viewer] + /// line per CHANGE of (root cell, flood size, OutsideView poly count, + /// player cell), with the projection EYE at mm precision on every line — + /// the capture half of the tower-ascent capture→replay loop + /// (TowerAscentReplayTests replays the captured pairs deterministically). + /// Light: silent while the visibility state is stable; a tower climb + /// emits a few dozen lines. Initial state from + /// ACDREAM_PROBE_VIEWER=1. + /// + public static bool ProbeViewerEnabled { get; set; } = + Environment.GetEnvironmentVariable("ACDREAM_PROBE_VIEWER") == "1"; + /// /// Phase U.4c (2026-05-31) flap-convergence probe. When true, the portal /// visibility pass emits, EVERY frame the camera root is an indoor cell, a