fix(render): Phase U.2b — resolve reciprocal portal by other_portal_id (retail 433557)
Code review caught a CRITICAL under-inclusion: ApplyReciprocalClip scanned for the first OtherCellId match, so a cell with two portals to the same neighbour clipped both near-side openings against the FIRST reciprocal polygon — hiding geometry through the second opening (real on Holtburg cellar cells 0x148<->0x149). Plumb the dat's OtherPortalId back-link through CellPortalInfo + BuildLoadedCell and index the reciprocal directly (retail arg2->other_portal_id, 433557). Skip (degrade to over-include) when the index is unresolvable — never clip against a guessed polygon. Adds a disjoint two-back- portal regression test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3916b2b23e
commit
65781f5768
7 changed files with 184 additions and 66 deletions
|
|
@ -146,21 +146,33 @@ Retail anchors (`docs/research/named-retail/acclient_2013_pseudo_c.txt`):
|
|||
- `InitCell` — per-cell timestamp init
|
||||
- `AddViewToPortals` 433446 — change-detection that drives the fixpoint
|
||||
|
||||
**Related M-4 stub — CLOSED (Phase U.2b, 2026-05-30):** the
|
||||
neighbour-side `OtherPortalClip` (decomp:433524) is now ported. After a
|
||||
portal's near-side opening is clipped against the current cell's view,
|
||||
`PortalVisibilityBuilder.ApplyReciprocalClip` resolves the neighbour's
|
||||
matching back-portal (scan `neighbour.Portals` for the entry whose
|
||||
`OtherCellId` == the near cell's low-16-bits id; `PortalPolygons` is in
|
||||
lockstep), projects it through the neighbour's `WorldTransform`, and
|
||||
**Related M-4 stub — CLOSED (Phase U.2b, 2026-05-30; reciprocal-resolution
|
||||
fix 2026-05-30):** the neighbour-side `OtherPortalClip` (decomp:433524) is
|
||||
ported. After a portal's near-side opening is clipped against the current
|
||||
cell's view, `PortalVisibilityBuilder.ApplyReciprocalClip` resolves the
|
||||
neighbour's matching back-portal **by direct index via the dat's
|
||||
`CellPortal.OtherPortalId` back-link** (retail `arg2->other_portal_id`,
|
||||
005a54b2), projects it through the neighbour's `WorldTransform`, and
|
||||
intersects it into the propagated region before the union — so a cell's
|
||||
clip region is the intersection of the opening seen from BOTH sides. Can
|
||||
only TIGHTEN; degrades to prior near-side-only behavior when no
|
||||
back-portal is found. The `TODO(A8.F)` marker is removed. Covered by
|
||||
clip region is the intersection of the opening seen from BOTH sides. The
|
||||
reciprocal is `neighbour.PortalPolygons[portal.OtherPortalId]`, NOT a scan
|
||||
for the first `OtherCellId` match. The direct index is load-bearing: a cell
|
||||
with TWO portals to the same neighbour (real on the Holtburg cellar —
|
||||
`0x148` has two portals to `0x149`, polys 40/41, and `0x149` has two
|
||||
reciprocals back to `0x148`) clips each opening against its OWN reciprocal.
|
||||
The earlier scan-by-first-match resolved both near-side openings to the
|
||||
FIRST reciprocal, and disjoint apertures then intersected to empty —
|
||||
HIDING the geometry through the second opening (under-inclusion). The fix
|
||||
plumbs `OtherPortalId` through `CellPortalInfo` + `BuildLoadedCell`. Guards
|
||||
degrade to over-include (never clip against a guessed polygon) when the
|
||||
index is out of range, the polygon is missing/degenerate, or it projects
|
||||
behind the camera. Can only TIGHTEN. Covered by
|
||||
`PortalVisibilityBuilderTests.Build_AppliesReciprocalOtherPortalClip`
|
||||
(reciprocal tightening) + `…_DegradesGracefully_WhenNoBackPortal`.
|
||||
(The diamond-topology onward re-propagation of late growth remains out of
|
||||
scope here — tracked under U.6.)
|
||||
(reciprocal tightening) + `…_DegradesGracefully_WhenNoBackPortal`
|
||||
(over-include degrade) + `…_MultiplePortalsToSameNeighbour_EachResolvesOwnReciprocal`
|
||||
(the disjoint two-back-portal regression). (The diamond-topology onward
|
||||
re-propagation of late growth remains out of scope here — tracked under
|
||||
U.6.)
|
||||
|
||||
**Files:**
|
||||
- `src/AcDream.App/Rendering/PortalVisibilityBuilder.cs` — replace the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue