docs: A6.P3 #98 resolution + A6.P4 design + #99/#100 filed
Knowledge-preservation pass after the issue #98 cellar-up fix shipped (`b3ce505`). Closes the saga's documentation loop and plans the next phase. Changes: - docs/research/2026-05-23-a6-p3-issue98-comparison-harness-findings.md Appended "Resolution 2026-05-24" section: v3 hypothesis falsified, actual mechanism (head-bump cottage GfxObj floor poly from below) confirmed,b3ce505fix shipped, known door regression flagged. Memory artifacts cross-referenced. - docs/ISSUES.md #98 moved to DONE with full resolution writeup + decomp anchors. #99 filed: door regression at building thresholds (caused by b3ce505's indoor-primary gate). Closes via A6.P4. #100 filed: transparent rectangular patches around houses (terrain rendering). Bisect found commit35b37dfintroduced the hiddenTerrainCells mechanism that collapses 24m outdoor cells when buildings sit in them; cottage building only fills part of its cell so the rest of the 24m cell shows the sky-bleeding gap. Three fix-path options documented. - docs/superpowers/specs/2026-05-24-phase-a6-p4-retail-shadow-architecture.md Full A6.P4 design doc. Three-slice plan: (1) query-side portal expansion to close #99 while preserving #98 fix, (2) port retail's BuildShadowCellSet at registration time so per-cell semantics match `CObjCell::find_cell_list`, (3) removeb3ce505stopgap entirely. Decomp anchors, file-by-file plan, risk inventory, open questions. Memory entries written separately (out-of-tree at ~/.claude/projects/.../memory/): - feedback_retail_per_cell_shadow_list.md The architectural lesson: retail uses per-cell shadow_object_list with portal-aware registration; our landblock-wide spatial registry diverges at indoor/outdoor seams. - feedback_apparatus_for_physics_bugs.md The apparatus-first pattern that cracked the saga: live capture + fixture dump + replay harness. Template for future physics bugs. Quote rule: "when a physics bug is resisting and you catch yourself about to ship 'fix attempt N+1 with no new evidence,' STOP. Build the apparatus first." - MEMORY.md index updated with both new entries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b3ce505ca8
commit
b55ae831bd
3 changed files with 487 additions and 1 deletions
154
docs/ISSUES.md
154
docs/ISSUES.md
|
|
@ -664,7 +664,159 @@ Falsifiable: if #96 fix closes #97 as a side-effect, the hypothesis is confirmed
|
|||
|
||||
---
|
||||
|
||||
## #98 — Cellar ascent stuck at top (BSP step physics; NOT cell-resolver)
|
||||
## #98 — [DONE 2026-05-24 · `b3ce505`] Cellar ascent stuck at top (NOT BSP step; per-cell-list architectural divergence)
|
||||
|
||||
**Closed:** 2026-05-24
|
||||
**Commit:** `b3ce505 fix(phys): A6.P3 #98 — gate outdoor shadow radial sweep on indoor primary cell`
|
||||
|
||||
**Resolution:** The proximate fix is the indoor-primary radial-sweep
|
||||
gate in `ShadowObjectRegistry.GetNearbyObjects`. Architectural root
|
||||
cause: our landblock-wide spatial shadow registry diverges from
|
||||
retail's per-cell `shadow_object_list` with portal-aware registration —
|
||||
the cottage GfxObj (registered landblock-wide via cellScope=0) was
|
||||
returned to sphere queries inside the cellar EnvCell, and its
|
||||
downward-facing floor poly at world Z=94 head-bumped the climbing
|
||||
sphere from below.
|
||||
|
||||
After ~10 failed speculative fix attempts across four sessions, the
|
||||
fix landed cleanly once the apparatus converged. The "v3 stale ramp
|
||||
contact plane" hypothesis was falsified by chronological replay against
|
||||
`a6-issue98-resolve-capture-2.jsonl` — the player IS on the ramp at the
|
||||
cap event; the contact plane is correctly the ramp's plane; the head
|
||||
sphere bumps the cottage GfxObj's floor poly from below (the
|
||||
evening-v2 finding was correct all along).
|
||||
|
||||
Decomp anchors (`docs/research/named-retail/acclient_2013_pseudo_c.txt`):
|
||||
- 308742+ : `CObjCell::find_cell_list` — indoor/outdoor branch
|
||||
- 308751-308769 : the branch — indoor adds 1 cell; outdoor calls `add_all_outside_cells`
|
||||
- 308773-308825 : portal-visible neighbor recursion
|
||||
- 308916 : `CObjCell::find_obj_collisions(this, ...)` — strict per-cell iteration
|
||||
|
||||
**Visual verification 2026-05-24:** user confirmed "Finally I can go up!"
|
||||
|
||||
**Knowledge artifacts:**
|
||||
- Findings doc resolution section: [`docs/research/2026-05-23-a6-p3-issue98-comparison-harness-findings.md`](research/2026-05-23-a6-p3-issue98-comparison-harness-findings.md) (bottom)
|
||||
- Memory: `feedback_retail_per_cell_shadow_list.md`, `feedback_apparatus_for_physics_bugs.md`
|
||||
- A6.P4 phase planned to do the full retail-faithful per-cell port and obviate the b3ce505 stopgap
|
||||
|
||||
**Known regression introduced:** doors at doorway thresholds — see #99 below.
|
||||
|
||||
---
|
||||
|
||||
## #99 — Run-through doors at building thresholds (regression from b3ce505)
|
||||
|
||||
**Status:** OPEN
|
||||
**Severity:** HIGH (M1 demo regression — opening doors was previously a working demo target)
|
||||
**Filed:** 2026-05-24
|
||||
**Component:** physics, shadow-object collision query
|
||||
|
||||
**Description:** With the issue #98 fix (commit `b3ce505`), the
|
||||
indoor-primary radial-sweep gate causes our engine to miss outdoor-
|
||||
registered door entities when a sphere has crossed the threshold and
|
||||
the primary cell resolves to the indoor side. Players can walk through
|
||||
doors that previously blocked them.
|
||||
|
||||
User report 2026-05-24: "I can also run through doors."
|
||||
|
||||
**Root cause / status:** This is the doorway edge case explicitly
|
||||
flagged in the b3ce505 commit message. Doors are server-spawned
|
||||
entities with their own cylinder collision, registered via
|
||||
`UpdatePosition` to whichever cell their position resolves to. Doors
|
||||
at building thresholds typically resolve to **outdoor** cells. The
|
||||
b3ce505 gate skips the outdoor radial sweep when the sphere's primary
|
||||
cell is indoor → outdoor-registered doors are not returned → no
|
||||
collision → walk-through.
|
||||
|
||||
Retail handles this case via the portal-visible recursion in
|
||||
`find_cell_list` (lines 308773-308825 of the named-retail decomp): at
|
||||
registration time, an object is added to its position's cell PLUS all
|
||||
portal-visible neighbor cells. So a door at a doorway portal ends up in
|
||||
both the outdoor cell's shadow list AND the indoor cell's list — a
|
||||
sphere on either side sees it.
|
||||
|
||||
**Fix path:** Closes naturally as part of A6.P4 (per-cell shadow
|
||||
architecture refactor — see design spec at
|
||||
`docs/superpowers/specs/2026-05-24-phase-a6-p4-retail-shadow-architecture.md`).
|
||||
A6.P4 ports retail's `find_cell_list` indoor branch + portal recursion
|
||||
into `ShadowObjectRegistry.Register`, eliminates the cellScope=0
|
||||
landblock-wide approximation, and removes the b3ce505 stopgap.
|
||||
|
||||
If A6.P4 takes longer than expected, an intermediate "portal-aware
|
||||
indoor query" patch (~20 lines: walk indoor cells' `VisibleCellIds`,
|
||||
collect portal-reachable outdoor cells, include in `GetNearbyObjects`
|
||||
indoor branch) would close #99 without touching registration. Tagged
|
||||
as fallback option B in the A6.P4 spec.
|
||||
|
||||
**Files:**
|
||||
- `src/AcDream.Core/Physics/ShadowObjectRegistry.cs` — `GetNearbyObjects` indoor branch
|
||||
- `src/AcDream.Core/Physics/TransitionTypes.cs:2180+` — `FindObjCollisions` caller
|
||||
|
||||
**Acceptance:** Doors at Holtburg cottage/inn doorways block the player
|
||||
from both sides (outside walking in, inside walking out). Issue #98's
|
||||
cellar-up fix remains intact.
|
||||
|
||||
**Related:** #98 (sibling — same architectural cause), #97 (phantom
|
||||
collisions on 2nd floor — also likely closed by A6.P4), Finding 3
|
||||
family (sling-out — also likely).
|
||||
|
||||
---
|
||||
|
||||
## #100 — Transparent rectangular patches around every house (terrain rendering)
|
||||
|
||||
**Status:** OPEN
|
||||
**Severity:** MEDIUM (visual regression; affects every Holtburg house)
|
||||
**Filed:** 2026-05-24
|
||||
**Component:** rendering, terrain
|
||||
|
||||
**Description:** Standing outside any Holtburg house, the ground in a
|
||||
rectangular footprint around the building appears as a flat dark patch
|
||||
instead of cobblestone / grass terrain. Visible as a sharp-edged
|
||||
rectangle the size of the house's outdoor footprint. Same shape on
|
||||
every house observed.
|
||||
|
||||
User report 2026-05-24 (with screenshot): "around every house now I
|
||||
missing the ground texture, it is transparent. I can see through the
|
||||
ground."
|
||||
|
||||
**Root cause / status:** **Bisect 2026-05-24 — commit `35b37df`** is the introducer (the only commit on this worktree branch that touches `src/AcDream.Core/Terrain/`). It added a `hiddenTerrainCells` parameter to `LandblockMesh.Build` that collapses terrain triangles owned by buildings to zero-area degenerates, intended so the building's own ground-level mesh visually fills the gap (avoids Z-fighting between terrain and building floor).
|
||||
|
||||
The hide mechanism works at **outdoor-cell granularity** — 24 m × 24 m cells indexed by `cy * 8 + cx` from `LandBlockInfo.Buildings`. A cottage building only fills ~half of one outdoor cell (cottage footprint ~12 m × 12 m vs cell 24 m × 24 m), so the entire 24 × 24 cell terrain gets hidden but the cottage geometry only covers a smaller area inside it. The visible result: a dark rectangle (sky / framebuffer clear bleeding through) around every house where terrain was hidden but no building mesh fills the gap.
|
||||
|
||||
Confirmed in [`src/AcDream.Core/Terrain/LandblockMesh.cs:178`](src/AcDream.Core/Terrain/LandblockMesh.cs:178):
|
||||
```csharp
|
||||
if (hiddenTerrainCells is not null && hiddenTerrainCells.Contains(cellIdx))
|
||||
{
|
||||
indices[i] = (uint)(cellIdx * VerticesPerCell); // collapse to vertex 0 → degenerate
|
||||
continue;
|
||||
}
|
||||
```
|
||||
|
||||
The cells flagged hidden come from `LandblockLoader.BuildBuildingTerrainCells` (also kept by 35b37df), which reads `LandBlockInfo.Buildings` and emits one cellIdx per listed building's `cy*8+cx`.
|
||||
|
||||
The b3ce505 issue-#98 fix did NOT cause or interact with this — it only touched physics collision code.
|
||||
|
||||
**Fix paths** (need design decision):
|
||||
1. **Polygon-level terrain occlusion** instead of cell-level. Build per-poly cutouts from each building's ground-footprint convex hull / bounding box, modify the terrain mesh to actually have a hole the building exactly fits. Retail-faithful for this case but a real engineering change to `LandblockMesh.Build`.
|
||||
2. **Drop the hiddenTerrainCells mechanism entirely** and accept Z-fighting on the building floor vs terrain seam (or solve Z-fighting via a tiny render-only Z lift on the building floor mesh, the same trick we already use for env cell floors at line 5363 `+ new Vector3(0f, 0f, 0.02f)`).
|
||||
3. **Render the building's "yard" mesh** if buildings have such a thing in retail. (Need to check — Holtburg cottages may have stone foundation polys around them that retail renders.)
|
||||
|
||||
Option 2 is the smallest change; option 1 is the most faithful. Option 3 needs retail visual research.
|
||||
|
||||
**Files:**
|
||||
- `src/AcDream.Core/Terrain/LandblockMesh.cs:178` — the collapse code
|
||||
- `src/AcDream.Core/World/LandblockLoader.cs` — `BuildBuildingTerrainCells`
|
||||
- `src/AcDream.App/Rendering/GameWindow.cs:1808, 5366, 8761` — sites calling `LandblockMesh.Build` with `hiddenTerrainCells`
|
||||
|
||||
**Acceptance:** Standing outside a Holtburg house, the ground around it
|
||||
renders with the same cobblestone / grass texture as the surrounding
|
||||
terrain — no dark rectangular patches.
|
||||
|
||||
---
|
||||
|
||||
## #98-old-context-preserved-for-reference
|
||||
|
||||
(retained from the OPEN form for historical context — superseded by the
|
||||
DONE resolution above. Skip to next active issue if you've read enough.)
|
||||
|
||||
**Status:** OPEN — **NEW diagnosis after A6.P3 slice 3 (2026-05-22)**
|
||||
**Severity:** HIGH (blocks M1.5 demo cellar half — user can descend but cannot return)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue