156 lines
9.8 KiB
Markdown
156 lines
9.8 KiB
Markdown
# Pickup handoff — #180 camera-sweep eye strobe (the #176 "stripes") — port retail's stateful sought-position
|
||
|
||
**Paste the companion prompt (bottom of this file / the session log) into a fresh
|
||
session.** Read this file, then `claude-memory/project_physics_collision_digest.md`
|
||
(top banner) + `claude-memory/project_render_pipeline_digest.md` (top banner), then
|
||
**ISSUES #180** (and #176's gate-2 note).
|
||
|
||
## TL;DR — what #180 is
|
||
|
||
The user's #176 residual — "geometrical patterns, triangles, that get weird
|
||
stripes… especially when I push the camera to the wall or the openings; if I zoom
|
||
out and the camera does not touch the walls I get no pattern" — is **NOT a render
|
||
defect. The camera-collision sweep is BISTABLE while the compressed chase boom
|
||
moves along a wall**, and the per-frame view hard-cuts tear-interleave on screen:
|
||
|
||
> `[flap-sweep]` (launch-176-cameye.log, frames ~38607–38861): consecutive sweeps
|
||
> whose INPUT moved **~1.4 mm** (the player's glide) flipped the OUTPUT **0.27 m
|
||
> along the boom** — `pulledIn` 0.27 ↔ 0.53, eye (78.500,−38.633,−3.845) ↔
|
||
> (78.669,−38.815,−3.938) — re-flipping every ~5–10 frames. All 368,357 sweeps
|
||
> returned `ok=True` (this is NOT the fallback path — the sweep itself has two
|
||
> first-contact solutions at an r±ε graze on the corridor's double-faced slabs,
|
||
> the #137 threshold family, camera edition). At ~1700 fps with no vsync, each
|
||
> monitor refresh interleaves scanline slices of BOTH views → the fine
|
||
> stripe/hatch patterns (worst near seams where the 0.27 m parallax is largest),
|
||
> flickering with movement. Parked camera = static (all prior "camera stable"
|
||
> evidence was parked-camera; the strobe needs motion + a compressed boom).
|
||
|
||
This very plausibly also produced the ORIGINAL #176 seam flashes (one of the two
|
||
alternating eyes sees the purple under-room parallax, the other doesn't).
|
||
|
||
## Eliminated for the stripes (DO-NOT-RETRY — all isolation-killed)
|
||
|
||
| Ruled OUT | How |
|
||
|---|---|
|
||
| Texture / grout-line interaction | `ACDREAM_LIGHT_DEBUG=3` (raw vLit field, texture ignored) still shows the pattern |
|
||
| The per-cell shell clip trim (gl_ClipDistance) | `ACDREAM_CLIP_DEBUG=1` (shells drawn WHOLE, slots forced 0) — user: "Not gone, still there" |
|
||
| Coplanar dat geometry | 2 cm-epsilon sweep: corridor floor (z=−6) clean; the only stack is the z=−12 under-hall quad×4 — SAME-mesh, bit-identical depth ⇒ stable winner, cannot moiré |
|
||
| Shell double-instance / floor-coincident entity / portal seals | `[seam-*]` probe: n=1 per cell at the lifted z; portal entities at z=−12.05; zero depth fans (sealed dungeon) |
|
||
| Light-set churn under movement | `[seam-blk]`: the floor's applied set held the SAME 8 identities through a 148k-frame session incl. ~12k distinct positions |
|
||
| The light pool tracking the camera | FIXED `d8984e87` (resident collection, player anchor) — verified: flood churned 8→41 across a full turn, set constant. Do NOT re-open; re-gate VISUALLY only after #180 |
|
||
| SweepEye itself misporting update_viewer | Read side-by-side: flags 0x5c, AdjustPosition seating, fallbacks all match 0x00453ce0. The bistability is in the transition's contact solution, not the port shape |
|
||
|
||
## The retail anchor (the fix direction — read BEFORE coding)
|
||
|
||
Retail's camera target is **STATEFUL**; ours re-demands the full boom every frame:
|
||
|
||
- `SmartBox` per-frame (pseudo-C line ~91842, addr 0x00452d75):
|
||
`CameraManager::UpdateCamera(this->camera_manager, &ret, &this->viewer)` — the
|
||
argument is the **CURRENT swept viewer**, and the RETURN is assigned to
|
||
`this->viewer_sought_position` (0x00452d84). So the next frame's sweep target
|
||
derives from the collided position — the target CONVERGES onto the wall
|
||
contact and re-extends gradually; the knife-edge full-length ray is not
|
||
re-rolled per frame. That is why retail's camera glides along walls instead of
|
||
strobing.
|
||
- `CameraManager::UpdateCamera` = **0x00456660** (pseudo-C line ~95505). Only the
|
||
head was read this session (offset-movement integration, pivot query); the
|
||
sought-position derivation in the tail is UNREAD — **read it fully, write the
|
||
pseudocode doc (workflow step 3), then port**.
|
||
- `SmartBox::update_viewer` = **0x00453ce0** (line ~92761) — already faithfully
|
||
ported by `PhysicsCameraCollisionProbe.SweepEye`; leave it alone.
|
||
- **No damping band-aid on the swept result without the UpdateCamera reading**
|
||
(the no-workaround rule; the user has already reverted redesigns that replaced
|
||
retail mechanisms).
|
||
|
||
Port site: `src/AcDream.App/Rendering/RetailChaseCamera.cs` (the desired-eye /
|
||
boom derivation) — it must consume the previous swept viewer per retail.
|
||
|
||
## Also open from this arc
|
||
|
||
- **Site-A weenie light-registration LEAK**: `[seam-ent]` showed one portal cell's
|
||
I100 light ×2 → ×4 within a session — re-CreateObject re-registers the light
|
||
under a fresh `entity.Id` (GameWindow ~3679: `Id = _liveEntityIdCounter++`)
|
||
without tearing down the previous registration. The wash intensifies over
|
||
time. Fix with #180's gate or fold into A7 (noted in ISSUES #176).
|
||
- **#176 re-gate** happens only after #180 lands: camera pressed into
|
||
walls/openings while moving → no patterns; corridor seam turn → steady purple
|
||
wedge (the faceted SHAPE is cdb-proven retail — only instability is a defect).
|
||
- After BOTH pass: strip the throwaway probes in one cleanup commit —
|
||
`[seam-*]` (ACDREAM_PROBE_SEAMDRAW), `ACDREAM_LIGHT_DEBUG` modes,
|
||
`ACDREAM_CLIP_DEBUG`. Keep `[flap-sweep]` (it rides ACDREAM_PROBE_FLAP).
|
||
|
||
## Apparatus (reuse, don't rebuild)
|
||
|
||
- `ACDREAM_PROBE_FLAP=1` → `[flap-sweep]` per-sweep line: `desiredBack/eyeBack/
|
||
pulledIn/in=/out=` — THE #180 instrument (plus [flap]/[flap-cam]).
|
||
- `ACDREAM_PROBE_PVINPUT=1` → per-frame `[pv-input] eye=` at 6 dp.
|
||
- **The autonomous visual loop** (no user needed, works where RenderDoc can't —
|
||
RenderDoc doesn't support GL_ARB_bindless_texture and the modern gate throws):
|
||
1. Launch via `dotnet run` (background) with probes; wait ~12 s.
|
||
2. Input: `keybd_event` **with real scan codes + KEYEVENTF_EXTENDEDKEY**
|
||
(GLFW decodes scancodes; vk-only silently does nothing). Arrows: Left
|
||
0x25/0x4B, Right 0x27/0x4D, Down 0x28/0x50. `SetForegroundWindow` first,
|
||
verify with `GetForegroundWindow`. Hold-key = down, Sleep, up.
|
||
3. Capture: `GetWindowRect` + `Graphics.CopyFromScreen` → PNG in the
|
||
scratchpad → **the Read tool renders it** (take 3 captures ~150 ms apart —
|
||
frame-pair diffs expose per-frame strobes).
|
||
4. Repro recipe: back the character into a wall (hold Down ~2.5 s) — the boom
|
||
compresses; the strobe fires DURING/just after motion near the wall.
|
||
5. Close gracefully via `CloseMainWindow()` (ACE session clears in ~5 s).
|
||
- Launch logs on disk (worktree root): `launch-176-cameye.log` (THE strobe
|
||
capture), `launch-176-user-gate.log` (148k-frame user session incl. the light
|
||
leak), `launch-176-seamdraw.log`, `launch-176-fix-verify.log`.
|
||
- `ACDREAM_LIGHT_DEBUG=1/2/3` + `ACDREAM_CLIP_DEBUG=1` — shader/clip isolation
|
||
toggles (throwaway; strip at cleanup).
|
||
|
||
## State
|
||
|
||
- `main` = worktree branch `claude/vigorous-joliot-f0c3ad` = **`6aabe0b5`**
|
||
(lighting fix `d8984e87` + isolation apparatus `6aabe0b5`). Suites green
|
||
(Core 2599+2skip / App 726+2skip / UI 425 / Net 385).
|
||
- Register: AP-85 rewritten (resident+player-anchored pool; residual = single
|
||
128 pool vs retail 7-dyn/40-static). The a7 pseudocode doc carries a
|
||
correction banner (`visible_cell_table` = RESIDENT registry — the
|
||
identifier-name-≠-semantics lesson, memory
|
||
`feedback_bn_decomp_field_names` class 4).
|
||
- A client may be running — the user manages its lifecycle; ASK before
|
||
rebuilding if the App DLL is locked (MSB3027 = lock, not code).
|
||
- The test char spawns in the Facility Hub corridor (cell `0x8A020164`).
|
||
|
||
## Companion prompt (paste into the fresh session)
|
||
|
||
```
|
||
Fix #180 — the camera-collision sweep strobes the eye 0.27m per few frames when
|
||
the compressed chase boom moves along walls; at ~1700fps the tear-interleaved
|
||
views ARE the #176 "stripes/triangles" the gates keep failing on. The mechanism
|
||
is probe-pinned; every render suspect is isolation-killed. Do NOT re-investigate
|
||
the render, the light pool (fixed d8984e87, data-verified), or SweepEye's port
|
||
(faithful, exonerated).
|
||
|
||
READ FIRST, in order:
|
||
1. docs/research/2026-07-06-180-camera-sweep-strobe-handoff.md (evidence,
|
||
DO-NOT-RETRY table, retail anchors, the autonomous visual-loop recipe)
|
||
2. claude-memory/project_physics_collision_digest.md (top banner)
|
||
3. docs/ISSUES.md #180 (+ #176's gate-2 note)
|
||
|
||
THE FIX = port retail's STATEFUL camera target: SmartBox (0x00452d75) feeds the
|
||
CURRENT swept viewer into CameraManager::UpdateCamera (0x00456660) and assigns
|
||
the RETURN to viewer_sought_position (0x00452d84) — the target converges onto
|
||
the wall contact instead of re-rolling the full knife-edge boom ray per frame
|
||
like RetailChaseCamera does. Workflow: read UpdateCamera's tail (the sought
|
||
derivation — UNREAD so far, pseudo-C line ~95505), write the pseudocode doc,
|
||
port into RetailChaseCamera. NO damping band-aids on the swept result.
|
||
|
||
Verify autonomously with the handoff's visual loop (keybd_event scan-codes +
|
||
GDI window capture + [flap-sweep]): back into a wall, confirm consecutive-frame
|
||
eye deltas stay continuous and no stripe patterns in captures. Then the user
|
||
gate covers #180 AND the #176 re-gate (steady purple wedge at the seam — the
|
||
wedge SHAPE is retail, cdb-proven). After both pass: fix the site-A light-
|
||
registration leak (one portal light stacked ×4/session — re-CreateObject
|
||
re-registers under fresh entity ids) and strip the throwaway probes
|
||
([seam-*], ACDREAM_LIGHT_DEBUG, ACDREAM_CLIP_DEBUG) in a cleanup commit.
|
||
|
||
State: main @ 6aabe0b5, suites green (Core 2599+2skip). Test char spawns in the
|
||
Facility Hub corridor 0x8A020164. A client may be running — the user manages
|
||
its lifecycle; ASK before rebuilding if the App DLL is locked.
|
||
```
|