#119-residual ROOT CAUSE: the +0.02 m render lift leaked into the portal-visibility graph - horizontal portals side-culled anyone standing on them
The live capture pinned it end to end. BuildInteriorEntitiesForStreaming lifts the render-side cell transform +0.02 m Z (shell z-fighting vs terrain - a DRAW concern) and passed that LIFTED transform to BuildLoadedCell, so every plane in the visibility graph sat 2 cm high. The portal side test's in-plane window is +-10 mm: an eye standing ON a floor containing a HORIZONTAL portal (the tower's deck lip 010A->0107, stair landings, cellar mouths) sits 0-10 mm above the TRUE plane = 10-20 mm BELOW the lifted plane -> outside the window -> the cell behind the portal side-culled out of the flood. Captured live at the stair top: root=0xAAB3010A eye z=126.803 vs the portal plane at 126.80, flood=1, 0x0107 (the whole tower interior incl. the staircase) dropped WHILE THE GAZE LOOKED STRAIGHT AT IT - "stairs disappear and you can walk on them", and the roof/edge flap as the gaze swung the marginal admissions. Vertical doorways were immune (the lift slides their planes along themselves) - exactly why this hit stairs/decks/floors and not doors. Chase chain (the apparatus did all the work): [viewer] print-on-change probe with eye@mm -> the user's climb capture -> [viewer-diff] naming the dropped cells per flip -> headless replay of the exact captured (eye,fwd) frame: healthy UNLIFTED, reproduces ONLY with the production lift -> gate-by-gate diagnostic (side test dot=+0.003 unlifted vs -0.017 lifted; clip + rescue exonerated; knife-edge z-sweep all-stable, killing the float-chaos theory). Fix: BuildLoadedCell receives the PHYSICS (unlifted) transform; the drawn shells keep their lift. The seal/punch fans (which read the visibility LoadedCell's WorldTransform) now stamp TRUE depth - MORE consistent with the unlifted terrain they protect. Pins: CapturedTopOfStairs_MainCellStaysInFlood - arm 1 (unlifted = post-fix production) asserts the main cell admitted at the captured frame; arm 2 (lifted) is the mechanism canary asserting the drop, with instructions if it ever starts passing. Plus the gate-by-gate diagnostic + knife-edge sweep as the investigation record. Also this session: Issue127FloodFlipReplayTests (the captured 4 cm outdoor flip pair replays STABLE across fovs/pre-gate arms - the outdoor churn is NOT the flood math; remaining #127 = distant-building admission churn, lower priority now that the tower-cell drops are explained by the lift), and the [viewer-diff] probe (per-flip added/ removed cell naming - keep, it found this). Suites: App 242+1skip, Core 1422+2skip, UI 420, Net 294. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
cd12d3dbbc
commit
f35cb8b164
4 changed files with 448 additions and 4 deletions
|
|
@ -5585,8 +5585,21 @@ public sealed class GameWindow : IDisposable
|
|||
cellRotation: envCell.Position.Orientation,
|
||||
staticObjects: System.Array.Empty<(uint, System.Numerics.Vector3, System.Numerics.Quaternion, bool, System.Numerics.Matrix4x4)>());
|
||||
|
||||
// Step 4: build LoadedCell for portal visibility (UNCHANGED from pre-A8).
|
||||
BuildLoadedCell(envCellId, envCell, cellStruct, cellOrigin, cellTransform);
|
||||
// Step 4: build LoadedCell for portal visibility — with the
|
||||
// PHYSICS (unlifted) transform. The +0.02 m render lift above
|
||||
// is a DRAW concern (shell z-fighting vs terrain); feeding it
|
||||
// into the visibility graph shifted every HORIZONTAL portal
|
||||
// plane 2 cm up, putting an eye standing on a deck/landing
|
||||
// 10–20 mm BELOW the lifted plane — outside the side test's
|
||||
// ±10 mm in-plane window — so the cell behind the portal was
|
||||
// side-culled: the tower-top staircase vanish + roof flap
|
||||
// (#119-residual; captured live at eye z=126.803 vs the
|
||||
// 010A→0107 plane at 126.80, reproduced ONLY with the lift in
|
||||
// TowerAscentReplayTests.CapturedTopOfStairs_*). Vertical
|
||||
// doorways were immune (the lift slides their planes along
|
||||
// themselves), which is why this hit exactly stairs, decks,
|
||||
// and cellar mouths.
|
||||
BuildLoadedCell(envCellId, envCell, cellStruct, physicsCellOrigin, physicsCellTransform);
|
||||
|
||||
// Cache CellStruct physics BSP for indoor collision (UNCHANGED).
|
||||
_physicsDataCache.CacheCellStruct(envCellId, envCell, cellStruct, physicsCellTransform);
|
||||
|
|
@ -9672,6 +9685,10 @@ public sealed class GameWindow : IDisposable
|
|||
// #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;
|
||||
// #127: previous frame's admitted cell set — the [viewer-diff] line names
|
||||
// exactly which cells entered/left the flood when the signature changes.
|
||||
private readonly HashSet<uint> _lastViewerFloodCells = new();
|
||||
private readonly List<uint> _viewerDiffScratch = new();
|
||||
|
||||
private void EmitRetailPViewDiagnostics(
|
||||
AcDream.App.Rendering.RetailPViewFrameResult result,
|
||||
|
|
@ -9698,6 +9715,37 @@ public sealed class GameWindow : IDisposable
|
|||
var v = _cameraController?.Active.View ?? System.Numerics.Matrix4x4.Identity;
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
$"[viewer] {sig} eye=({camPos.X:F3},{camPos.Y:F3},{camPos.Z:F3}) fwd=({-v.M13:F4},{-v.M23:F4},{-v.M33:F4}) viewerCell=0x{viewerCellId:X8}"));
|
||||
|
||||
// #127 [viewer-diff]: name the cells that entered/left since the
|
||||
// last emitted signature — the bistable admission self-attributes.
|
||||
_viewerDiffScratch.Clear();
|
||||
var cur = result.PortalFrame.OrderedVisibleCells;
|
||||
var sb = new System.Text.StringBuilder(96);
|
||||
sb.Append("[viewer-diff] added=[");
|
||||
bool first = true;
|
||||
foreach (uint c in cur)
|
||||
{
|
||||
if (_lastViewerFloodCells.Contains(c)) continue;
|
||||
if (!first) sb.Append(',');
|
||||
sb.Append("0x").Append(c.ToString("X8"));
|
||||
first = false;
|
||||
}
|
||||
sb.Append("] removed=[");
|
||||
first = true;
|
||||
foreach (uint c in _lastViewerFloodCells)
|
||||
{
|
||||
bool present = false;
|
||||
for (int ci = 0; ci < cur.Count; ci++)
|
||||
if (cur[ci] == c) { present = true; break; }
|
||||
if (present) continue;
|
||||
if (!first) sb.Append(',');
|
||||
sb.Append("0x").Append(c.ToString("X8"));
|
||||
first = false;
|
||||
}
|
||||
sb.Append(']');
|
||||
Console.WriteLine(sb.ToString());
|
||||
_lastViewerFloodCells.Clear();
|
||||
foreach (uint c in cur) _lastViewerFloodCells.Add(c);
|
||||
}
|
||||
}
|
||||
if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeVisibilityEnabled)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue