From 639f20fa8ac5ea3a57b9f6918ce109ccac67b7a3 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 31 May 2026 10:01:11 +0200 Subject: [PATCH] =?UTF-8?q?feat(render):=20Phase=20U.4c=20=E2=80=94=20Load?= =?UTF-8?q?edCell=20carries=20stab=5Flist=20PVS=20+=20seen=5Foutside?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VisibleCells (full ids) + SeenOutside, populated at the EnvCell-build site from envCell.VisibleCells + envCell.Flags. Mirrors retail CEnvCell.stab_list / seen_outside (acclient.h ~30925). Data already in-process; render path no longer drops it. Consumed by the builder in U.4c-3. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/AcDream.App/Rendering/CellVisibility.cs | 19 +++++++++++++++++++ src/AcDream.App/Rendering/GameWindow.cs | 12 ++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/AcDream.App/Rendering/CellVisibility.cs b/src/AcDream.App/Rendering/CellVisibility.cs index 074aaa4..84638cf 100644 --- a/src/AcDream.App/Rendering/CellVisibility.cs +++ b/src/AcDream.App/Rendering/CellVisibility.cs @@ -83,6 +83,25 @@ public sealed class LoadedCell /// and route IndoorPass cell scoping. /// public uint? BuildingId { get; internal set; } + + /// + /// Phase U.4c: the stab_list PVS as full (landblock-prefixed) cell ids — retail + /// CEnvCell.stab_list (acclient.h ~30925), the stable set of cells potentially + /// visible from this cell, precomputed by the AC content tools. Refreshed only at + /// hydration (= retail's per-cell-entry grab_visible_cells, decomp:311878). + /// PortalVisibilityBuilder grounds set membership in it so a brittle per-frame + /// portal-side test can't drop a potentially-visible cell from the visible set. + /// Empty when the dat carried no stab list (degenerate / old cell). + /// + public IReadOnlyList VisibleCells = System.Array.Empty(); + + /// + /// Phase U.4c: retail CEnvCell.seen_outside (acclient.h ~30925) — this cell sees + /// the exterior (an exit portal is reachable from it). Retail gates the landscape + /// data + draw decision on the camera cell's value (RenderNormalMode decomp:92649, + /// grab_visible_cells decomp:311878). The stable anchor for the terrain-draw test. + /// + public bool SeenOutside; } /// diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 2a8947f..cf84efe 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -5693,6 +5693,16 @@ public sealed class GameWindow : IDisposable portalPolygons.Add(polyVerts); } + // Phase U.4c: surface the stable PVS + seen-outside flag onto the render cell. + // Both come straight off the dat EnvCell — no new parsing (PhysicsDataCache + // already reads VisibleCells the same way; A8CellAudit reads the flag). + uint lbPrefix = envCellId & 0xFFFF0000u; + var visibleCells = new List(); + if (envCell.VisibleCells is not null) + foreach (var lowId in envCell.VisibleCells) + visibleCells.Add(lbPrefix | lowId); + bool seenOutside = envCell.Flags.HasFlag(DatReaderWriter.Enums.EnvCellFlags.SeenOutside); + var loaded = new LoadedCell { CellId = envCellId, @@ -5704,6 +5714,8 @@ public sealed class GameWindow : IDisposable Portals = portals, ClipPlanes = clipPlanes, PortalPolygons = portalPolygons, // Phase A8 + VisibleCells = visibleCells, // Phase U.4c + SeenOutside = seenOutside, // Phase U.4c }; _pendingCells.Add(loaded); }