docs: indoor flicker/void root cause (decomp + live cdb) + 3-part fix plan handoff
Diagnosis session: the indoor bluish void + grey/texture flicker is visibility metastability at cell boundaries, not a missing flood (R1's per-cell DrawInside is built; the cellar seals). Confirmed by named-retail decomp AND a live cdb capture of retail (viewer_cell rock-stable: clean monotonic transitions, zero oscillation across 4916 samples). Retail stays stable via boom stability + a 0.2mm viewer-cell dead-zone + clip-space portal clipping; acdream diverges on all three. Handoff documents the root cause, the cdb evidence, and the prioritized 3-part retail-faithful fix (boom stability -> dead-zone -> w-space clip) with decomp anchors + a planning/implementation kickoff prompt. Adds the reusable retail viewer-cell cdb capture script and the superseding CLAUDE.md banner. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9f95252d20
commit
9601ef39c3
3 changed files with 287 additions and 1 deletions
20
CLAUDE.md
20
CLAUDE.md
|
|
@ -763,7 +763,25 @@ H1 (PVS grounding) or H2 (`PortalSide` side-test) — both evidence-disproven.
|
||||||
**Currently working toward: M1.5 — Indoor world feels right** (resumed
|
**Currently working toward: M1.5 — Indoor world feels right** (resumed
|
||||||
from 2026-05-20 baseline after Phase O ship).
|
from 2026-05-20 baseline after Phase O ship).
|
||||||
|
|
||||||
**2026-06-05 — Render Residual A (camera collision) SHIPPED + user-kept; next = the CORE INSIDE RENDER (R1 completion) (READ THIS FIRST).**
|
**2026-06-05 (PM) — Indoor FLICKER + bluish VOID ROOT CAUSE CONFIRMED (decomp + live cdb); 3-part retail-faithful fix PLANNED (READ THIS FIRST).**
|
||||||
|
The "core inside render / cellar floor drops" framing below is **SUPERSEDED** by this session's diagnosis.
|
||||||
|
R1's per-cell `DrawInside` is already built and the cottage/cellar **seals** (user visual-verified). The
|
||||||
|
residual indoor **flicker (grey↔texture while standing still)** + **stable bluish void** are ONE root cause —
|
||||||
|
**visibility metastability at cell boundaries:** the 3rd-person camera **boom drifts at rest**
|
||||||
|
(`desiredBack 3.11→3.07`), walking the eye across a portal plane, and acdream re-resolves the **viewer cell**
|
||||||
|
fresh each frame with **no hysteresis** → it flips `0170↔0171` → the render (rooted at the viewer cell)
|
||||||
|
redraws two solves → flicker; and the 2D project-then-clip **degenerates** at close portals (`proj=0`) → grey
|
||||||
|
void. **Live cdb on retail CONFIRMS** retail's `viewer_cell` is rock-stable here (clean monotonic transitions,
|
||||||
|
ZERO oscillation across 4,916 samples) — retail holds the boom + uses a **0.2 mm cell dead-zone** + clips
|
||||||
|
portals **in clip-space**. **FIX (3 parts, retail-faithful, planned):** (1) camera boom stability
|
||||||
|
[`RetailChaseCamera`; `UpdateCamera` 0x456660] → kills the flicker trigger; (2) viewer-cell ±0.2 mm dead-zone
|
||||||
|
[`PhysicsCameraCollisionProbe.SweepEye`; `point_inside_cell_bsp` 0x53c1f0]; (3) w-space (w=0) portal clip
|
||||||
|
[`PortalProjection`/`PortalVisibilityBuilder`; `GetClip` 0x5a4320 / `polyClipFinish` 0x6b6d00]. Two partial
|
||||||
|
fixes committed: `5f596f2` (NDC side-plane clip — KEEP), `9f95252` (eye-in-portal flood — reassess/revert).
|
||||||
|
Baseline App 183p / Core 1326p-4f-1s. **CANONICAL PICKUP:**
|
||||||
|
[`docs/research/2026-06-05-viewer-cell-flicker-rootcause-and-fix-plan-handoff.md`](docs/research/2026-06-05-viewer-cell-flicker-rootcause-and-fix-plan-handoff.md).
|
||||||
|
|
||||||
|
**2026-06-05 — Render Residual A (camera collision) SHIPPED + user-kept; next = the CORE INSIDE RENDER (R1 completion) (SUPERSEDED 2026-06-05 PM — see the banner above; the cellar IS sealed, the real bug is the boundary flicker/void).**
|
||||||
Residual A = a verbatim port of retail `SmartBox::update_viewer` (pc:92761): the indoor sweep's start
|
Residual A = a verbatim port of retail `SmartBox::update_viewer` (pc:92761): the indoor sweep's start
|
||||||
cell is seated at the head-PIVOT via `AdjustPosition` (pc:280009) → `find_visible_child_cell` (pc:311397),
|
cell is seated at the head-PIVOT via `AdjustPosition` (pc:280009) → `find_visible_child_cell` (pc:311397),
|
||||||
plus the two fallbacks + cellId==0 snap-to-player. Commits `0ffc3f5` (spec) / `5177b54` (Core primitives)
|
plus the two fallbacks + cellId==0 snap-to-player. Commits `0ffc3f5` (spec) / `5177b54` (Core primitives)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,251 @@
|
||||||
|
# Handoff — Indoor flicker/void ROOT CAUSE confirmed (decomp + live cdb); 3-part retail-faithful fix planned — 2026-06-05 (PM)
|
||||||
|
|
||||||
|
> **Canonical pickup for the next (fix) session. Read this FIRST.** This session did the diagnosis
|
||||||
|
> the previous "core inside render (R1)" handoff asked for, and it landed somewhere different than that
|
||||||
|
> handoff predicted. The indoor **bluish void + grey/texture flicker** is NOT a missing per-cell flood
|
||||||
|
> port — R1's per-cell `DrawInside` is built and the cellar/ceiling seal correctly. The residual is
|
||||||
|
> **camera/viewer-cell instability at cell boundaries**, confirmed by both the named-retail decomp AND a
|
||||||
|
> live cdb capture of retail. The fix is a **3-part retail-faithful port** (camera boom stability +
|
||||||
|
> viewer-cell dead-zone + w-space portal clip), de-risked and ready to plan + implement.
|
||||||
|
> Branch `claude/thirsty-goldberg-51bb9b`. PowerShell on Windows; launch logs are UTF-16.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. TL;DR
|
||||||
|
|
||||||
|
- **The premise we started with was stale.** "Cellar floor drops / R1 incomplete" — actually R1's per-cell
|
||||||
|
`DrawInside` + binary inversion already exist (commit `c4fd711`, 2026-06-02) and the cellar **is sealed**
|
||||||
|
(user visual-verified T1 this session). The flood reaches the cellar; the shell draws.
|
||||||
|
- **The real bug is two faces of ONE root cause — visibility metastability at cell boundaries:**
|
||||||
|
1. **Flicker (grey↔texture) at a "stationary" position** = the **viewer (camera) cell flips per-frame**
|
||||||
|
`0170↔0171` because the 3rd-person camera **boom drifts** (`desiredBack 3.11→3.07` while the player
|
||||||
|
stands still), walking the eye across a portal plane, and acdream re-resolves the viewer cell fresh
|
||||||
|
each frame with **no hysteresis**. The render roots at the viewer cell, so it redraws two different
|
||||||
|
solves → flicker.
|
||||||
|
2. **Stable bluish void** = when the eye is firmly in/at a thin/transition cell, the portal flood
|
||||||
|
**degenerates** because acdream projects-to-NDC-then-2D-clips instead of clipping in clip-space, so a
|
||||||
|
close/grazing portal drops (`proj=0`) → no terrain / neighbour not flooded → grey.
|
||||||
|
- **CONFIRMED by live cdb on retail** (this is the payoff): retail's `viewer_cell` is **rock-stable** at
|
||||||
|
the same Holtburg-cottage boundary — clean single monotonic transitions, **zero oscillation** across
|
||||||
|
4,916 samples; retail rests the camera in the *substantial* cell, never lingering in the thin doorway
|
||||||
|
cell. acdream's `[flap-sweep]` flips `0170↔0171` at the same spot. Retail is stable, acdream is not —
|
||||||
|
exactly as the decomp predicted.
|
||||||
|
- **The fix (3 parts, prioritized) is retail-faithful and anchored to specific decomp functions.** §4.
|
||||||
|
- **Two partial fixes shipped this session** (`5f596f2` NDC frustum side-plane clip — keep;
|
||||||
|
`9f95252` eye-in-portal flood — band-aid, likely superseded → reassess/revert). §3.
|
||||||
|
- **Test baseline:** App **183 pass / 0 fail** (179 + 4 new). Core **1326 pass / 4 fail (documented) /
|
||||||
|
1 skip**. Branch HEAD after this handoff commit. Build green.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. The session arc (so you don't repeat it)
|
||||||
|
|
||||||
|
1. Read the "core inside render (R1)" handoff. **Discovered R1's inversion + per-cell `DrawInside` already
|
||||||
|
exist and are live** (`c4fd711`/`4b75c68`/`cf85ea4`, 2026-06-02; not reverted). So this was a *debug*
|
||||||
|
task, not a *port* task.
|
||||||
|
2. **Visual gate (user):** the cellar (T1) is **sealed**. The real symptoms are at **transitions**: a
|
||||||
|
bluish **void flap** exiting the building (screenshot), a **grey flash** cellar→room, **outdoor
|
||||||
|
content through the ground** looking out, and a **stationary flicker** (textures alternate grey↔texture
|
||||||
|
while standing still).
|
||||||
|
3. **Evidence-first (probes `ACDREAM_PROBE_FLAP/_VIS/_SHELL/_CELL`):**
|
||||||
|
- Refuted the prior handoff's hypothesis ("flood doesn't reach the cellar") — rooted at the room, the
|
||||||
|
flood **does** reach the cellar (`[vis] root=0171 ids=[...,0174]`).
|
||||||
|
- Found the void is `terrain=Skip` / `proj=0` on exit/interior portals when the eye is close
|
||||||
|
(`[flap] p->0xFFFF D=-0.28 proj=4 clip=0`; later `p1->0x0171 D=0.16 proj=0`).
|
||||||
|
- Found the **flicker** is the **viewer cell flipping** at a knife-edge boundary: in a held pose the
|
||||||
|
`[flap-sweep] viewerCell` flips `0170↔0171` as `D` crosses `0.00`, while the **player stands still**
|
||||||
|
and the boom **drifts** (`desiredBack 3.11→3.07`).
|
||||||
|
4. **Decomp spike (3 parallel agents + 1 verified-myself crux):** mapped how retail stays stable. §2.
|
||||||
|
5. **Live cdb on retail** (matching v11.4186 binary, PDB-paired): captured retail's `viewer_cell` across
|
||||||
|
the same crossings → **clean, no oscillation**. §2.4. Confirms the fix direction.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. ROOT CAUSE — retail stays stable via THREE mechanisms; acdream diverges on each
|
||||||
|
|
||||||
|
### 2.1 Camera boom is a stable spring (Q3) — `CameraManager::UpdateCamera`
|
||||||
|
- Retail's boom vector `CameraManager::viewer_offset` (default `y = -2.5 m`) is **fixed** (changes only on
|
||||||
|
zoom keys). `UpdateCamera` (≈`0x00456660`, lerp body `0x00456d0d`) lerps the camera *position* toward
|
||||||
|
`pivot + viewer_offset` with stiffness, and **snaps to the current position when within 0.0004 m** → holds
|
||||||
|
a constant fixed point at rest.
|
||||||
|
- **The collided eye is firewalled from the desired position:** `set_viewer(…, arg3=0)` (the normal success
|
||||||
|
path, `update_viewer` pc≈92870) writes `this->viewer` (rendered eye) but **NOT** `viewer_sought_position`.
|
||||||
|
So the collision result never feeds back into the desired boom.
|
||||||
|
- `PlayerPhysicsUpdatedCallback` (`0x00452d60`, pc:91836) computes `viewer_sought_position = UpdateCamera(current_viewer)`.
|
||||||
|
- **acdream diverges:** `RetailChaseCamera` desired boom **drifts at rest** (`desiredBack 3.11→3.07`).
|
||||||
|
Hypotheses (verify in code): the collided eye is fed back into the desired (no firewall), and/or no
|
||||||
|
convergence snap. **This drift is the flicker trigger** (walks the eye across the boundary).
|
||||||
|
|
||||||
|
### 2.2 Viewer cell is sticky via a 0.2 mm dead-zone (Q1) — VERIFIED MYSELF
|
||||||
|
- `SmartBox::update_viewer` (`0x00453ce0`, pc:92761): `viewer_cell = sphere_path.curr_cell` after the
|
||||||
|
collision sweep, which **starts from the stable player cell** each frame (`cell_1` = player cell or
|
||||||
|
`AdjustPosition`-seated).
|
||||||
|
- `SPHEREPATH::init_path` (`0x0050ce20`, pc:274370): `curr_cell = arg2` (the start cell).
|
||||||
|
- The sweep updates the cell only on a **definite** crossing: `check_other_cells` (`0x0050ae50`, pc:272717)
|
||||||
|
→ `find_cell_list` → `check_cell`; `validate_transition` (`0x0050aa70`) promotes `curr_cell = check_cell`
|
||||||
|
(pc:272608) only when the cell/pos actually changed, else **restores `curr_cell`**.
|
||||||
|
- **The dead-zone (VERIFIED at pc:325513/325522):** `BSPNODE::point_inside_cell_bsp` (`0x0053c1f0`) uses
|
||||||
|
`0.000199999995f` (≈0.2 mm) symmetrically — a point within ±0.2 mm of a splitting plane belongs to
|
||||||
|
**neither** cell, so at a boundary graze `check_cell` is null and `curr_cell` stays at the start cell.
|
||||||
|
- **acdream diverges:** `RetailChaseCamera.ViewerCellId = swept.ViewerCellId` is re-resolved fresh **every
|
||||||
|
frame** with **no dead-zone** ("graph-tracked, deterministic, NO grace frames" — the comment) → flips at
|
||||||
|
the boundary.
|
||||||
|
|
||||||
|
### 2.3 Portal clip is homogeneous (w-space), before the divide (Q2) — `GetClip`/`polyClipFinish`
|
||||||
|
- `PView::GetClip` (`0x005a4320`, pc:432344) projects the portal then calls `ACRender::polyClipFinish`
|
||||||
|
(`0x006b6d00`, pc:702749), which **clips against the near plane (w=0) in clip-space, generating synthetic
|
||||||
|
edge vertices, BEFORE the perspective divide** — so a close portal never blows up to garbage NDC.
|
||||||
|
- `PView::InitCell` (`0x005a4b70`, pc:432896) **side-test culls** in-plane/back-facing portals (same 0.2 mm
|
||||||
|
band, pc≈432936) before any projection.
|
||||||
|
- The flood is substantially **root-invariant** for adjacent cells (both seeded full-screen; side-test is
|
||||||
|
symmetric).
|
||||||
|
- **acdream diverges:** projects-to-NDC then 2D-clips → degenerates at grazing/close angles (`proj=0` →
|
||||||
|
portal dropped → grey void / neighbour not flooded). This session's commit `5f596f2` added the eye-plane
|
||||||
|
+ side-plane clip (partial); the missing piece is the **w=0 near-plane clip with synthetic verts** + the
|
||||||
|
side-test dead-band.
|
||||||
|
|
||||||
|
### 2.4 LIVE CDB CONFIRMATION (retail v11.4186, PDB-paired) — the payoff
|
||||||
|
Captured `SmartBox::viewer_cell` (`viewer.objcell_id`) at the Holtburg cottage while passing inside↔outside
|
||||||
|
+ the stairs + standing still. Run-length-encoded camera-cell sequence (4,916 samples):
|
||||||
|
```
|
||||||
|
0xa9b40032 ×3360 → 0031 ×173 → 0170 ×8 → 0171 ×134 → 0170 ×14 → 0031 ×129
|
||||||
|
→ 0170 ×7 → 0171 ×139 → 0170 ×15 → 0031 ×110 → 0170 ×7 → 0171 ×167 → … (clean repeats)
|
||||||
|
```
|
||||||
|
- **Every crossing is a clean, single, monotonic pass** (outside `0031/0032` → vestibule `0170` brief
|
||||||
|
7–15-sample pass-through → room `0171`, and back). **ZERO `0170↔0171` oscillation** anywhere.
|
||||||
|
- Standing still, retail rests in the **substantial** cells (room `0171` ×134–197, outside long runs),
|
||||||
|
**never lingering in the thin vestibule `0170`**.
|
||||||
|
- **Contrast acdream:** `[flap-sweep] viewerCell` flips `0170↔0171` per-frame at the same boundary.
|
||||||
|
- **Conclusion:** retail's viewer cell is stable (boom holds + 0.2 mm dead-zone + sweep-from-player-cell);
|
||||||
|
acdream's is not. No surprises — the fix is de-risked.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. What shipped this session (committed; partial)
|
||||||
|
|
||||||
|
| SHA | What | Keep? |
|
||||||
|
|---|---|---|
|
||||||
|
| `5f596f2` | `PortalProjection.ProjectToNdc` clips eye + 4 frustum **side planes** in clip-space before the divide (replaces the 2026-06-03 `MinW`-only workaround). Bounds NDC to the screen. | **KEEP.** Real correctness, retail-consistent (partial of §2.3). |
|
||||||
|
| `9f95252` | `PortalVisibilityBuilder` floods the neighbour when the eye **stands in** an interior portal (`EyeInsidePortalOpening`). Fixed the cellar **ceiling** (visual-verified). | **REASSESS / likely REVERT.** A coverage band-aid for the thin-cell-root case; the §4 boom + dead-zone keep the camera out of thin cells, and the w=0 clip handles close portals — this may become unnecessary or over-include. Easy `git revert 9f95252`. |
|
||||||
|
|
||||||
|
Neither is the flicker fix. Both green (App 183), Core baseline held (1326/4/1).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. THE FIX — 3-part retail-faithful port (prioritized). Plan, then implement TDD.
|
||||||
|
|
||||||
|
### Part 1 (HIGHEST leverage) — Camera boom stability → kills the flicker trigger
|
||||||
|
- **Goal:** acdream's desired boom settles and **holds** at rest (no drift). Match `UpdateCamera`: desired
|
||||||
|
position derived each frame from a **fixed** boom offset + the player pivot; **firewall the collided eye**
|
||||||
|
out of the desired chain; add the **convergence snap** (return current when within ~0.0004 m).
|
||||||
|
- **acdream targets:** `src/AcDream.App/Rendering/RetailChaseCamera.cs` (the `_dampedEye` / `desiredBack` /
|
||||||
|
the lerp + where the collided `swept.Eye` is consumed). Verify whether `swept.Eye` feeds the next-frame
|
||||||
|
desired (the drift hypothesis) and whether a snap exists.
|
||||||
|
- **Anchors:** `CameraManager::UpdateCamera` `0x00456660` (snap ~`0x00456d0d` region), `PlayerPhysicsUpdatedCallback`
|
||||||
|
`0x00452d60` (pc:91836), `set_viewer` arg3=0 firewall (`update_viewer` pc≈92870).
|
||||||
|
- **Verify:** with the boom stable, the `[flap-sweep] eyeBack/desiredBack` is flat at rest and the eye stops
|
||||||
|
grazing the boundary.
|
||||||
|
|
||||||
|
### Part 2 — Viewer-cell dead-zone hysteresis → belt-and-suspenders for the flicker
|
||||||
|
- **Goal:** acdream's camera-sweep viewer-cell resolution doesn't flip on a sub-mm/boundary graze. Port the
|
||||||
|
retail dead-zone: a point within ±0.2 mm of a portal plane belongs to neither cell → keep the prior/start
|
||||||
|
(player) cell.
|
||||||
|
- **acdream targets:** `src/AcDream.App/Rendering/PhysicsCameraCollisionProbe.cs` (`SweepEye`) and the
|
||||||
|
Core cell-resolution it calls (`CellTransit.FindVisibleChildCell` / the point-in-cell test). Ensure the
|
||||||
|
sweep starts from the player cell and only changes `viewer_cell` on a definite crossing.
|
||||||
|
- **Anchors:** `point_inside_cell_bsp` `0x0053c1f0` (0.000199999995f, pc:325513/325522), `init_path` pc:274370,
|
||||||
|
`validate_transition` pc:272608, `check_other_cells` pc:272717.
|
||||||
|
|
||||||
|
### Part 3 — w-space portal clip robustness → kills the *stable* grey void
|
||||||
|
- **Goal:** extend `5f596f2` to a true **near-plane (w=0) clip with synthetic edge vertices before the
|
||||||
|
divide** + the **InitCell side-test dead-band** that culls in-plane/back-facing portals before projection.
|
||||||
|
- **acdream targets:** `src/AcDream.App/Rendering/PortalProjection.cs` + `PortalVisibilityBuilder.cs`
|
||||||
|
(the side test `CameraOnInteriorSide`). After this, **reassess `9f95252`** (the eye-in-portal flood may be
|
||||||
|
redundant → revert).
|
||||||
|
- **Anchors:** `GetClip` `0x005a4320` (pc:432344), `polyClipFinish` `0x006b6d00` (pc:702749, the w=0 clip),
|
||||||
|
`InitCell` `0x005a4b70` (pc:432896 side-test).
|
||||||
|
|
||||||
|
**Order:** Part 1 → visual gate → Part 2 → Part 3 → reassess `9f95252`. Each is independently verifiable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. KEEP / DON'T
|
||||||
|
|
||||||
|
**KEEP:**
|
||||||
|
- R1 per-cell `DrawInside` + the binary inversion (`c4fd711`) — built and correct; the cellar seals.
|
||||||
|
- Residual A (camera collision, `update_viewer` port) — the viewer cell is *accurate*; we're stabilizing it,
|
||||||
|
not removing it.
|
||||||
|
- Commit `5f596f2` (NDC side-plane clip).
|
||||||
|
- The two-camera-ish reality: eye drives projection; the fix makes the *viewer cell* stable (boom + dead-zone),
|
||||||
|
matching retail (`is_player_outside` decides; `DrawInside(viewer_cell)` roots).
|
||||||
|
|
||||||
|
**DON'T:**
|
||||||
|
- Don't re-attempt "the flood doesn't reach the cellar" — refuted (`[vis]` shows it does).
|
||||||
|
- Don't add a render-side debounce/grace-period for the flicker — it's a **membership/visibility stability**
|
||||||
|
bug; fix the *input* (boom + dead-zone), not the render (memory: render-downstream-of-membership).
|
||||||
|
- Don't switch the render root to the *player* cell — retail roots `DrawInside` at the *viewer* cell; the
|
||||||
|
fix is to make the viewer cell *stable*, not to change which cell roots.
|
||||||
|
- Don't put a `;` inside a cdb `$$` comment (it splits into a command — bit me this session; use `*` comments).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. APPARATUS (committed / ready)
|
||||||
|
|
||||||
|
- **Probes** (all live): `ACDREAM_PROBE_FLAP` (`[flap]`/`[flap-cam]`/`[flap-sweep]`), `ACDREAM_PROBE_VIS`
|
||||||
|
(`[vis]`), `ACDREAM_PROBE_SHELL` (`[shell]`), `ACDREAM_PROBE_CELL` (`[cell-transit]`).
|
||||||
|
- **cdb script** `tools/cdb/retail-viewer-cell.cdb` — samples retail `SmartBox::viewer_cell` ~6/sec,
|
||||||
|
auto-`.detach` after 6000 hits. Binary verified MATCH via `tools/pdb-extract/check_exe_pdb.py`.
|
||||||
|
Re-run pattern + RLE analysis are in this session's transcript (PowerShell `Select-String` on
|
||||||
|
`retail-viewer-cell.log`). **Lesson:** per-frame bp + `dt`/`.printf` is heavy but survived here (retail
|
||||||
|
intact); keep samples sparse. `qd` is ignored in bp actions — use `.detach`.
|
||||||
|
- **TTD** is available (`tools/ttd-record.ps1` / `tools/ttd-query.ps1`) if a lower-overhead capture is needed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. STATE
|
||||||
|
- Branch `claude/thirsty-goldberg-51bb9b`. HEAD: this handoff's docs commit (after `9f95252`). No push (ask first).
|
||||||
|
- Build green. App **183 / 0**. Core **1326 / 4 (documented: 2× DoorBugTrajectoryReplay LiveCompare,
|
||||||
|
BSPStepUpTests.D4, DoorCollisionApparatus) / 1 skip**.
|
||||||
|
- Running the client: see CLAUDE.md "Running the client"; `+Acdream` spawns in the Holtburg cottage.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. KICKOFF PROMPT (copy-paste for the next session)
|
||||||
|
|
||||||
|
```
|
||||||
|
Continue acdream M1.5 indoor render: fix the boundary FLICKER + stable bluish VOID with the 3-part
|
||||||
|
retail-faithful port that the 2026-06-05 spike confirmed. ROOT CAUSE (decomp + live cdb, both done):
|
||||||
|
the indoor flicker/void is VISIBILITY METASTABILITY at cell boundaries, not a missing flood — R1's
|
||||||
|
per-cell DrawInside is built and the cellar seals. Retail stays stable via three mechanisms; acdream
|
||||||
|
diverges on each. Branch claude/thirsty-goldberg-51bb9b (do NOT branch/worktree; do NOT push without
|
||||||
|
asking; NEVER git stash/gc). PowerShell on Windows; launch logs are UTF-16.
|
||||||
|
|
||||||
|
READ FIRST (in order):
|
||||||
|
1. docs/research/2026-06-05-viewer-cell-flicker-rootcause-and-fix-plan-handoff.md (THIS handoff — root
|
||||||
|
cause §2, cdb confirmation §2.4, the 3-part fix §4, KEEP/DON'T §5).
|
||||||
|
2. memory: reference_render_pipeline_state.md, feedback_render_downstream_of_membership.md,
|
||||||
|
feedback_render_one_gate.md, project_camera_visibility_coupling.md.
|
||||||
|
3. The decomp anchors cited in §2/§4 (named-retail) for each part you implement.
|
||||||
|
|
||||||
|
THE FIX (plan first, then implement TDD; each part independently visual-verified):
|
||||||
|
Part 1 (highest leverage) — Camera boom stability (RetailChaseCamera): desired boom settles + HOLDS at
|
||||||
|
rest; firewall the collided eye out of the desired chain; add the convergence snap. Anchors:
|
||||||
|
CameraManager::UpdateCamera 0x00456660, PlayerPhysicsUpdatedCallback 0x00452d60, set_viewer arg3=0.
|
||||||
|
Part 2 — Viewer-cell dead-zone (PhysicsCameraCollisionProbe.SweepEye / Core cell resolution): ±0.2 mm
|
||||||
|
dead-zone so a graze keeps the player/start cell. Anchors: point_inside_cell_bsp 0x0053c1f0
|
||||||
|
(0.000199999995f), validate_transition pc:272608, init_path pc:274370.
|
||||||
|
Part 3 — w-space portal clip (PortalProjection/PortalVisibilityBuilder): near-plane (w=0) clip with
|
||||||
|
synthetic verts before the divide + InitCell side-test dead-band; then reassess/revert the
|
||||||
|
eye-in-portal flood band-aid (commit 9f95252). Anchors: GetClip 0x005a4320, polyClipFinish 0x006b6d00,
|
||||||
|
InitCell 0x005a4b70.
|
||||||
|
|
||||||
|
START by using superpowers:writing-plans (or brainstorming if a part's shape is unclear) to turn §4 into a
|
||||||
|
step plan with per-part acceptance + visual gates, THEN implement Part 1 first via TDD.
|
||||||
|
|
||||||
|
DON'T (§5): no render-side debounce for the flicker (fix the boom/cell input); don't switch the render
|
||||||
|
root to the player cell (retail roots DrawInside at the viewer cell — stabilize it instead); don't reopen
|
||||||
|
"flood doesn't reach the cellar" (refuted).
|
||||||
|
|
||||||
|
TEST BASELINE: App 183 pass / 0 fail. Core 1326 pass / 4 fail (documented) / 1 skip. Build green.
|
||||||
|
This session committed 5f596f2 (NDC side-plane clip — KEEP) + 9f95252 (eye-in-portal flood — reassess).
|
||||||
|
```
|
||||||
17
tools/cdb/retail-viewer-cell.cdb
Normal file
17
tools/cdb/retail-viewer-cell.cdb
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
* Retail viewer-cell stability capture (2026-06-05)
|
||||||
|
* Confirms whether retail SmartBox viewer_cell flips at a portal boundary
|
||||||
|
* or stays stable. Samples viewer.objcell_id ~6/sec to avoid lagging retail.
|
||||||
|
* Auto-detaches after 6000 hits via .detach (cdb ignores qd inside bp actions)
|
||||||
|
* NOTE never put a semicolon inside a comment line, it splits into a command
|
||||||
|
|
||||||
|
.logopen C:\Users\erikn\source\repos\acdream\.claude\worktrees\thirsty-goldberg-51bb9b\retail-viewer-cell.log
|
||||||
|
.sympath C:\Users\erikn\source\repos\acdream\refs
|
||||||
|
.symopt+ 0x40
|
||||||
|
.reload /f acclient.exe
|
||||||
|
|
||||||
|
x acclient!SmartBox::update_viewer
|
||||||
|
|
||||||
|
r $t0 = 0
|
||||||
|
bp acclient!SmartBox::update_viewer "r $t0 = @$t0 + 1; .if (@$t0 % 5 == 1) { .printf \"[vc] hit=%d eyeCell=\", @$t0; dt acclient!SmartBox @ecx viewer.objcell_id }; .if (@$t0 >= 6000) { .detach } .else { gc }"
|
||||||
|
|
||||||
|
g
|
||||||
Loading…
Add table
Add a link
Reference in a new issue