#118: outdoor dynamics draw in the outside stage under interior roots - the house-exit clip+vanish was the SEAL z-killing the player

Root cause (pinned by the new deterministic exit-walk harness, NOT guessed):
under an interior render root, the exit-portal SEAL stamps the door fan at
TRUE depth after the gated full depth clear, and T1's "ALL dynamics last"
pass then drew the outdoor-classified player depth-tested - every fragment
beyond the door plane z-failed against the seal across the whole aperture.
Harness measured the full window: from the moment the sphere center crosses
the plane until the eye follows (~2.6 m of camera lag, ~2.2 s at walk speed)
the player is invisible; while straddling, the beyond-plane body half clips
at the plane. The handoff's three cone-level candidates are all EXONERATED:
the cone walk passes every step; (eye, ViewerCellId) come from the same
SweepEye call with camera-update-before-visibility-read in the same frame;
the side-test window is sub-epsilon under healthy resolution.

Retail oracle (grep-named-first): PView::DrawCells 0x005a4840 runs
LScape::draw FIRST (pc:432719), then the gated depth clear (pc:432731-32)
and the exit-portal seals (pc:432785-86); outdoor cell objects draw inside
the landscape stage (DrawBlock 0x005a17c0 -> DrawSortCell pc:430124), and
an object draws once per overlapped shadow cell (pc:430056-64) - the
straddling body composes from both stages, neither half clips.

Fix: RetailPViewRenderer assigns dynamics to the OUTSIDE stage under an
interior root when outdoor-classified OR sphere-straddling an exit-portal
plane of their flood-visible cell (DynamicDrawsInOutsideStage - pure, the
harness drives it as the ordering contract); they ride the landscape slice
draw (pre-clear, seal-protected) with the same per-slice cone test as
outdoor statics. Indoor dynamics keep the last pass (retail loop C);
straddlers draw in both (retail shadow dual-draw). Outdoor roots keep
all-dynamics-last - the BR-2 punch-after-dynamics lesson (88be519) stands.

Apparatus: HouseExitWalkReplayTests - dat-backed corner-building exit walk
driving the production stack headlessly (RetailChaseCamera damping ->
healthy-sweep viewer resolution -> PortalVisibilityBuilder.Build ->
ClipFrameAssembler -> ViewconeCuller -> the DrawDynamicsLast predicate +
a CPU seal-depth model). 5 tests: cone pin, seal-depth pin, straddle
dual-draw pin, per-step table, stale-root window quantifier (#118 cand 2).

Suites: App 232 (227+5), Core 1416+2skip, UI 420, Net 294.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-06-11 16:49:29 +02:00
parent acaaeae434
commit 5a80a2ee24
5 changed files with 628 additions and 10 deletions

View file

@ -3937,7 +3937,36 @@ AFTER the punch. Compare against the T1 (`579c8b0`) punch pass wiring.
## #118 — Character clipped + disappears for a moment when exiting houses
**Status:** OPEN
**Status:** FIXED 2026-06-11 — pending visual re-gate
**Root cause (pinned by the exit-walk harness, `HouseExitWalkReplayTests`):**
NOT the cone stack — candidates 13 all exonerated (cone-level walk passes
every step; the camera publishes (eye, ViewerCellId) from the SAME SweepEye
call and updates before the visibility read, so the pair is coherent; the
side-test window is ≤ PortalSideEpsilon and never occurs under healthy
resolution). The mechanism is DEPTH ORDERING: under an interior root, the
exit-portal SEAL stamps the door fan at TRUE depth after the full depth
clear, and T1's "ALL dynamics last" then draws the outdoor-classified player
depth-tested — every fragment beyond the door plane z-fails against the seal
across the whole aperture. Full vanish once the center exits (harness: the
entire s=0.04→2.64 m window until the eye crosses, ~2.2 s at walk speed);
the body's beyond-plane half clips at the plane while straddling.
**Retail oracle:** PView::DrawCells (0x005a4840) runs LScape::draw FIRST
(pc:432719), THEN the gated depth clear (pc:432731) + seals (pc:432786);
outdoor cell objects draw inside the landscape stage via DrawBlock →
DrawSortCell (0x005a17c0, pc:430124), and an object draws once per
overlapped shadow cell (pc:430056-430064) — so a threshold-straddling body
draws in both stages and neither half clips.
**Fix (`RetailPViewRenderer`):** under an interior root, outdoor-classified
dynamics draw in the OUTSIDE (landscape) stage — before the clear+seal, so
the seal protects their pixels — and indoor dynamics whose sphere straddles
an exit-portal plane draw in BOTH stages (`DynamicDrawsInOutsideStage`).
Outdoor roots keep all-dynamics-last (the BR-2 punch lesson). Pins:
`ExitWalk_PlayerStaysConeVisible_EveryStep`,
`ExitWalk_PlayerSurvivesSealDepth_WhenConeVisible`,
`ExitWalk_StraddlingPlayerDrawsInOutsideStage`.
**Severity:** MEDIUM-HIGH (every house exit, brief)
**Filed:** 2026-06-11 (T5 comprehensive gate, user item 10)
**Component:** render — dynamics handling at the indoor→outdoor transition