From 38a52a7dac237b0605de0133e0f233a757a14427 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Jun 2026 15:37:10 +0200 Subject: [PATCH] =?UTF-8?q?feat(core):=20Stage=203=20T3.3=20=E2=80=94=20Ce?= =?UTF-8?q?llGraph.FindVisibleChildCell=20(retail=20find=5Fvisible=5Fchild?= =?UTF-8?q?=5Fcell)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Port CEnvCell::find_visible_child_cell @ 0x0052dc50 (pseudo_c:311397): walk rootId's StabList + the root itself, return the first EnvCell whose PointInCell is true for worldPoint. Used to resolve the camera cell in 3rd-person from the physics cell graph rather than a fresh AABB reclassification. Root is always the player cell (preserves U.4c flap fix). Returns null when no stab-list cell or root itself contains the query point. Confirmed (T3.3 Step 1): no production call site uses FindCameraCell for the camera projection — the only AABB camera resolver is now deleted (T3.1). FindVisibleChildCell is wired implicitly via Stage 4 (camera-outside-door scenario); no GameWindow call site needed in Stage 3. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/AcDream.Core/World/Cells/CellGraph.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/AcDream.Core/World/Cells/CellGraph.cs b/src/AcDream.Core/World/Cells/CellGraph.cs index 8f19e59..3f97bd5 100644 --- a/src/AcDream.Core/World/Cells/CellGraph.cs +++ b/src/AcDream.Core/World/Cells/CellGraph.cs @@ -55,4 +55,24 @@ public sealed class CellGraph /// reserved for the OtherCellPtr neighbor cache (Stage 3); the lookup keys only on the portal. /// public ObjCell? Neighbor(ObjCell cell, in CellPortal portal) => GetVisible(portal.OtherCellId); + + /// + /// Retail CEnvCell::find_visible_child_cell @ 0x0052dc50 (pseudo_c:311397). + /// Walk 's StabList + the root itself, return the first + /// EnvCell whose is true for + /// . Used to resolve the camera cell in 3rd-person + /// from the physics cell graph rather than an independent AABB reclassification — + /// the root is the player cell, never a camera-eye AABB scan. + /// Returns null when no cell in the root's stab list (or the root itself) contains + /// the query point (caller falls back to the player cell as projection root). + /// + public EnvCell? FindVisibleChildCell(uint rootId, Vector3 worldPoint) + { + if (!_envCells.TryGetValue(rootId, out var root)) return null; + if (root.PointInCell(worldPoint)) return root; + foreach (var stabId in root.StabList) + if (_envCells.TryGetValue(stabId, out var stab) && stab.PointInCell(worldPoint)) + return stab; + return null; + } }