acdream/docs/research/2026-06-02-phase-w-w2a-shipped-baseline-handoff.md
Erik 3622a658fd docs(render): Phase W — W2a shipped+verified + baseline handoff
W2a (render reads physics CurrCell) visually verified: indoor world-from-below fixed (cellar/stairs seal). Baseline scopes the residuals: W2b (doorway ping-pong 0170<->0031, confirmed) + W3 (one-gate seal: roof, entity bleed, openings) + the EnvCellRenderer GL_BLEND fix (transparent walls). Membership (W2) done.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 10:55:21 +02:00

10 KiB
Raw Blame History

Phase W (Unified Cell Graph) — W2a shipped + baseline handoff (2026-06-02)

Canonical pickup for the next session. This session pivoted the indoor render work to a full retail CObjCell cell-graph migration (Phase W), shipped W1 (scaffold) and W2a (render reads physics membership), visually verified W2a (the indoor "world from below" is fixed), and captured a scoped baseline of the remaining residuals. Read this first, then the W2 spec/plan + the evidence doc.

0. Git / safety state

  • Branch claude/thirsty-goldberg-51bb9b — UNPUSHED. Do not push without the user.
  • Two git stashes preserved — do NOT drop: stash@{0} (#98/#101/A8-culling WIP), stash@{1} (issue98 backup).
  • Working tree clean except throwaway untracked baseline-w2a-*.png / shot-*.png / launch*.log (the baseline evidence — ephemeral, do not commit; delete freely).
  • HEAD = 02acac5.

1. What shipped this session (commit ledger, oldest→newest)

SHA What
e8c7164 Pivot decision: evidence model + W1 (ObjCell scaffold) spec
bd0244f W1 implementation plan
9cb1571 W1 T1 — ObjCell base + CellPortal
76c9e2f W1 T2 — EnvCell + PointInCell (AABB/BSP)
5bc72d5 W1 T3 — EnvCell.FromDat (mirrors BuildLoadedCell)
03f08f0 W1 T3 fix — ResolvePortalPolygon all-or-nothing (review caught a real latent Stage-3 bug)
b4c4318 W1 T4 — LandCell synthesized from TerrainSurface
cf5d60d W1 T5 — CellGraph resolver + registry + inert CurrCell
1aede3d W1 T6 — real cottage-cell fixture grounding test
8e703be W1 T7 — populate CellGraph from CacheCellStruct + AddLandblock (inert)
f2663b7 W1 final-review polish (Opus review: VisibleCells null-guard + Neighbor doc)
07e68e0 Roadmap — register Phase W; W1 shipped
83c452b W2 (one membership) spec + plan
0e27a6c W2 T1ResolveCellId writes CellGraph.CurrCell (additive/write-only)
02acac5 W2 T2 — render root from physics CurrCell (FindCameraCell fallback)

Specs/plans: docs/superpowers/specs/2026-06-02-unified-cell-graph-stage1-design.md, .../2026-06-02-unified-cell-graph-stage2-design.md, docs/superpowers/plans/2026-06-02-unified-cell-graph-stage1.md, .../2026-06-02-unified-cell-graph-stage2.md. Evidence: docs/research/2026-06-02-render-cell-membership-evidence.md.

2. The program (Phase W, 5 stages — see roadmap)

W1 ObjCell scaffold (shipped) → W2 one membership (W2a shipped+verified; W2b next) → W3 render on the graph / one gate → W4 collision on the graph → W5 streaming → ObjCells. The architecture: ONE retail CObjCell cell graph (AcDream.Core.World.Cells) shared by physics + render (+ later collision + streaming). Membership is physics-owned (ResolveCellIdCellGraph.CurrCell); render reads it.

3. W2a — VERIFIED result

Render now reads the physics membership answer (CellGraph.CurrCell) as its visibility root, with a FindCameraCell fallback (so it can't regress below baseline). Visually verified 2026-06-02 at the Holtburg cottage:

  • The indoor "world from below" is fixed. Spawning directly in the cellar and standing still: [vis]=15, [shell]=19448 (baseline spawn-in was 0/0 = render never engaged → terrain/world drawn). The cellar/stairs now seal walls+floor; render follows physics through the cottage.
  • Tests: W2 T1 + T2 spec-reviewed; 166+ Core/App tests green; App builds 0/0.
  • W2a is membership only — it does NOT seal the full interior (that's W3).

4. Baseline of the W2a residuals (scoped by owner — the next-work map)

Captured across cellar / stairs / room / doorway (screenshots baseline-w2a-*.png, ephemeral). None of these are W2 membership — that's done.

Residual Where Probe-grounded cause Owner
Missing ceiling / open roof cellar, stairs ceiling not capped by the drawn shells W3 (seal)
Entities bleed through (NPCs / doors / smoke pillars / particles) everywhere indoors entities drawn ungated — not clipped to the visible cells W3 (entity gate)
Openings show "bluish world" cellar entrance, doorway openings reveal clear-color/sky instead of the adjacent cell W3 (clip)
Transparent interior walls room opaque shells ([shell] tr=0 zh=0) render transparent → EnvCellRenderer inherits a leftover GL_BLEND; opaque texels composite against the bluish clear color Render GL-state fix (memory render-self-contained-gl-state)
Doorway ping-pong 0170↔0031 threshold physics cell flips indoor↔outdoor at a near-static position; no stab-list prune W2b (confirmed needed)

Key cross-cutting observation: the PView builder (PortalVisibilityBuilder) computes sensible visible-cell sets (15 cells depending on root) AND non-empty OutsideView clip regions at exit portals ([vis] root=0171 outside(polys=1,planes=4) from the room's front door). The problem is the render gates don't all obey that output — entities draw ungated, the ceiling isn't drawn/capped, openings show the background. That is exactly W3's "compute visibility once, enforce it once for ALL geometry."

5. Ping-pong evidence (W2b is needed, not optional)

At the doorway threshold, [cell-transit] shows the physics cell flipping at a near-static position:

0xA9B40170 -> 0xA9B40031 pos=(155.054,16.569,94.000)
0xA9B40031 -> 0xA9B40170 pos=(155.075,16.522,94.000)
0xA9B40170 -> 0xA9B40031 pos=(155.035,16.610,94.000)
0xA9B40031 -> 0xA9B40170 pos=(155.129,16.403,94.000)

0170 (indoor) ↔ 0031 (outdoor) at ~(155.1, 16.5). W2b's stab-list prune (hold the indoor cell unless the outdoor candidate is in CurrCell.StabList) is the retail-faithful fix the #98 saga never tried. Plan: W2 plan Task 3 (docs/superpowers/plans/2026-06-02-unified-cell-graph-stage2.md).

6. Apparatus / how to reproduce

  • Launch (per CLAUDE.md "Running the client") with ACDREAM_PROBE_SHELL=1 ACDREAM_PROBE_VIS=1 ACDREAM_PROBE_CELL=1 ACDREAM_PROBE_ENVCELL=1. Pipe to a log via Tee-Objectnote the log is UTF-16; read it with the ripgrep-based Grep tool or PowerShell Get-Content, NOT GNU grep (silently matches nothing).
  • Screenshots: PowerShell System.Drawing CopyFromScreen on the AcDream.App MainWindowHandle → PNG → Read the PNG. (Capture loop used this session; works.)
  • Probes: [vis] (root + visible cells + OutsideView poly/plane counts), [shell] (per-cell shell render + tr/zh flags), [cell-transit] (physics CellId changes + reason), [envcells]. ACE respawns at last logout position (likely the cellar 0xA9B40171/0174).
  • Cottage cells: 0171 room (Z94), 0175 stairs (Z93), 0174 cellar (Z90), 0172/0173 room sub-cells, 0170 vestibule; outdoor neighbours 0031/0032.

7. Do-NOT-repeat / settled facts

  • W2a (membership) is done — the residuals are W2b/W3/GL-state, NOT membership. Don't re-investigate "why doesn't render engage" — it does now.
  • The transparent walls are NOT translucent geometry (tr=0) — it's the EnvCellRenderer inherited-GL_BLEND bug (memory render-self-contained-gl-state, item 3). Mirror WbDrawDispatcher's per-pass Disable/Enable(Blend) + DepthMask.
  • The PView builder works; don't rebuild it. W3 makes the GATES obey it.
  • Disproven earlier (do not revisit): camera/eye as root, cull mode, shell geometry/texture missing, stencil-mask-breaks-outdoors, flag-based per-entity gate routing.

8. Pickup prompt (copy-paste for the next session)

PHASE W (Unified Cell Graph) — continue on branch claude/thirsty-goldberg-51bb9b
(do NOT branch/worktree). Preserve the 2 git stashes — do not drop. Branch UNPUSHED — ask
before pushing. HEAD = 02acac5.

READ FIRST, in full: docs/research/2026-06-02-phase-w-w2a-shipped-baseline-handoff.md, then
the W2 spec docs/superpowers/specs/2026-06-02-unified-cell-graph-stage2-design.md + plan
docs/superpowers/plans/2026-06-02-unified-cell-graph-stage2.md, then the evidence doc
docs/research/2026-06-02-render-cell-membership-evidence.md.

STATE: M1.5 "indoor world feels right." Phase W = full retail CObjCell cell-graph migration,
5 stages. W1 (ObjCell scaffold) SHIPPED. W2a (render reads physics CurrCell) SHIPPED +
visually verified — the indoor "world from below" is FIXED (cellar/stairs seal walls+floor).
W2 membership is done. Remaining residuals are scoped in the handoff §4.

DO NEXT (in order):
1. W2b — stab-list doorway hysteresis (CONFIRMED needed: ping-pong 0170<->0031 at the
   threshold, handoff §5). Implement W2 plan Task 3 (port retail find_cell_list do_not_load_cells
   prune into PhysicsEngine.ResolveCellId; hold indoor cell unless the outdoor candidate is in
   CurrCell.StabList). Behavior-changing -> visual-verify the ping-pong stops, then W2 T4
   (flip W2 shipped in roadmap). Subagent-driven per the plan.
2. W3 — render on the graph / ONE gate (spec it first via superpowers:brainstorming, grounded
   in the handoff §4). Make ALL geometry obey the PView output: draw the ceiling/cap cell,
   CLIP ENTITIES to the visible cells (kills the NPC/door/smoke bleed), clip the outside to
   exit-portal openings (kills "bluish world" through openings). The PView builder already
   produces sensible visible sets + OutsideView regions — W3 makes the gates obey them.
   Fold in the EnvCellRenderer inherited-GL_BLEND fix (transparent walls; memory
   render-self-contained-gl-state) here or as a standalone render-GL-state fix.

EVIDENCE-FIRST for any render/visual question: launch with ACDREAM_PROBE_SHELL/VIS/CELL/ENVCELL,
screenshot (PowerShell CopyFromScreen on AcDream.App), read the UTF-16 log with ripgrep/PowerShell
(NOT GNU grep). Cottage cells: 0171 room, 0175 stairs, 0174 cellar, 0170 vestibule, 0031/0032
outdoor. Visual verification at the cottage is the acceptance gate for W2b + W3.

DO NOT REPEAT: W2a membership is done (render engages now); transparent walls = EnvCellRenderer
inherited GL_BLEND (not translucent geometry); the PView builder works (W3 fixes the GATES, not
the builder); camera/eye-as-root + stencil-mask-breaks-outdoors + flag-based gate routing are
all evidence-disproven.