diag(phys): [bsp-test] probe + grounded apparatus test + handoff
Visual verification of Task 7 ship: doors block at dead-center (the small Cylinder catches) but the BSP slab doesn't catch off-center or inside-walking-out approaches. Probe-instrumented live capture proves multi-part registration is correct — every door spawns with shapes=cyl1+bsp1, and the BSP part is visited 135 times for a single door at player approaches as close as 0.42 m, with cacheHit=True. But zero [resolve-bldg] attributions for the BSP shape. Three artifacts added: 1. TransitionTypes.cs — new [bsp-test] probe in the BSP collision dispatch, fires BEFORE the cache lookup. Mirrors [cyl-test] on the Cylinder branch. Distinguishes "cache miss → silent skip" from "queried but no hit" (the latter doesn't show up in [resolve-bldg] which only fires on attributed hits). 2. DoorCollisionApparatusTests.cs — new grounded test (Apparatus_Grounded_50cmOffCenter_*) attempts to reproduce the production bug via a seeded PhysicsBody (Contact + OnWalkable + ContactPlane + WalkablePolygon). Currently doesn't reproduce because the apparatus's stub-terrain + synthetic-floor setup diverges from production's real Holtburg geometry. Captured as "documents-the-bug" — flip the assertion shape when the fix lands. 3. docs/research/2026-05-24-door-collision-task7-shipped-but-bug-remains.md — full session handoff. Identifies the remaining bug as a Path 5 (Contact branch + StepSphereUp) misbehavior at thin tall obstacles, not in the multi-part registration we just shipped. Leading hypothesis: DoStepUp's downward probe finds the same flat floor on the OTHER side of the door (Holtburg cottages have no Z change between exterior and interior floor), declares step-up success, BSP collision returns OK, sphere walks through. Recommended next move: relaunch with ACDREAM_DUMP_STEPUP=1 to verify the hypothesis. What this commit DOES NOT do: fix the remaining step-up bug. The A6.P4 multi-part registration foundation is correct and stays. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ca9341c2cb
commit
163a1f0d35
3 changed files with 360 additions and 0 deletions
|
|
@ -0,0 +1,247 @@
|
|||
# Door collision — Task 7 shipped, partial fix, deeper bug remains
|
||||
|
||||
**Date:** 2026-05-24 (evening, continuation of door collision investigation)
|
||||
**Branch:** `claude/strange-albattani-3fc83c`
|
||||
**Status:** A6.P4 architecture is correct. Multi-part registration works.
|
||||
The Holtburg door bug PARTIALLY fixed — center blocks, but off-center
|
||||
and inside-out still walk through. Root cause is downstream in the
|
||||
engine's grounded BSP collision path (Path 5 + step-up), NOT in the
|
||||
multi-part registration we just shipped.
|
||||
|
||||
---
|
||||
|
||||
## TL;DR
|
||||
|
||||
**Three commits shipped** (composable foundation):
|
||||
|
||||
| SHA | Title | What it does |
|
||||
|---|---|---|
|
||||
| `e1d94d7` | dat-inspection test | Confirmed door part `0x010044B5` has full 1.9×0.26×2.5 m BSP slab (6 Landblock polys). Hypothesis A from prior handoff was wrong. |
|
||||
| `3b7dc46` | `GetNearbyObjects` dedup fix | Changed `HashSet<uint>` (entityId) → `HashSet<ShadowEntry>`. Multi-part shapes no longer silently dropped. |
|
||||
| `ca9341c` | Task 7 live wiring | `RegisterLiveEntityCollision` uses `ShadowShapeBuilder.FromSetup` + `RegisterMultiPart`. Doors now register cyl+bsp instead of just cyl. |
|
||||
|
||||
**Live verification (visual user test):**
|
||||
|
||||
| Scenario | Result |
|
||||
|---|---|
|
||||
| Dead center, walk into closed door (outside) | ✅ Blocks |
|
||||
| 50 cm off-center, walk into closed door (outside) | ❌ Walks through |
|
||||
| Inside walking out (closed door) | ❌ Walks through |
|
||||
| Use door → swing → walk through | ✅ Works (ETHEREAL flip path) |
|
||||
|
||||
**Probe-instrumented live capture confirms multi-part registration works:**
|
||||
|
||||
- Every door spawn shows `[entity-source] shapes=cyl1+bsp1` — both shapes register.
|
||||
- BSP part `0x010044B5` is visited 135 times for a single door at player approaches as close as `distXY=0.415 m`.
|
||||
- `cacheHit=True` for every visit — the cache is populated.
|
||||
- BUT: zero `[resolve-bldg]` attributions for the BSP shape (all 19 attributed hits show `gfxObj=0x00000000` = the Cylinder shape).
|
||||
|
||||
So the BSP is being QUERIED but never produces an attributed hit. The
|
||||
sphere walks through despite the BSP geometry being present and
|
||||
visited.
|
||||
|
||||
---
|
||||
|
||||
## What's in the tree right now
|
||||
|
||||
```
|
||||
$ git log --oneline -8
|
||||
ca9341c feat(phys): A6.P4 Task 7 — RegisterLiveEntityCollision uses ShadowShapeBuilder + RegisterMultiPart
|
||||
3b7dc46 fix(phys): GetNearbyObjects dedup-by-entityId silently drops multi-part shadows
|
||||
e1d94d7 test(phys): door setup + GfxObj dat-inspection — Hypothesis A falsified
|
||||
c89df8e docs(handoff): door collision per-part BSP session handoff (2026-05-24)
|
||||
1498697 diag(phys): [cyl-test] probe — log every Cylinder shadow collision test
|
||||
3e5dc8c test(phys): Task 6 regression — Deregister clears _entityShapes cache
|
||||
d5ffb03 feat(phys): UpdatePosition handles multi-part entities
|
||||
fca0a13 feat(phys): ShadowObjectRegistry.RegisterMultiPart
|
||||
```
|
||||
|
||||
**Uncommitted (to commit next):**
|
||||
- `src/AcDream.Core/Physics/TransitionTypes.cs` — new `[bsp-test]` probe in
|
||||
the BSP collision dispatch, mirrors `[cyl-test]`. Fires when a BSP entry
|
||||
is visited, BEFORE the cache lookup. Distinguishes "cache miss → silent
|
||||
skip" from "queried but no hit." Gated on `ACDREAM_PROBE_BUILDING=1`.
|
||||
- `tests/AcDream.Core.Tests/Physics/DoorCollisionApparatusTests.cs` —
|
||||
new test `Apparatus_Grounded_50cmOffCenter_FrontApproach_DocumentsBug`
|
||||
that attempts to reproduce the production bug with a grounded body +
|
||||
seeded ContactPlane. Currently fails because the apparatus's behavior
|
||||
diverges from production (apparatus blocks immediately at tick 0 with
|
||||
a Z+ normal from the synthetic floor; production walks through).
|
||||
|
||||
---
|
||||
|
||||
## Path 5 vs Path 6 — the divergence
|
||||
|
||||
`BSPQuery.FindCollisions` dispatches to 6 paths based on `ObjectInfo`
|
||||
state. The crucial difference:
|
||||
|
||||
- **Path 6 (Default)** — fires when `obj.State` has no `Contact` flag.
|
||||
Calls `SphereIntersectsPolyInternal` and `SetCollide` on hit.
|
||||
**Apparatus tests use this path** (no body, `isOnGround=false`). They
|
||||
all PASS — the door's BSP blocks the sphere correctly.
|
||||
|
||||
- **Path 5 (Contact branch)** — fires when `obj.State.HasFlag(Contact)`.
|
||||
Calls `SphereIntersectsPolyInternal`; on hit, calls
|
||||
`StepSphereUp → DoStepUp → DoStepDown` to attempt climbing over the
|
||||
obstacle. Returns OK if step succeeds, Slid if step fails.
|
||||
**Production uses this path** (player grounded → `isOnGround=true` →
|
||||
engine sets `Contact` flag at `PhysicsEngine.cs:631`). Production
|
||||
WALKS THROUGH.
|
||||
|
||||
So the bug is somewhere in Path 5's step-up logic. The leading
|
||||
hypothesis (not yet proven):
|
||||
|
||||
> When the player is standing on flat ground in front of the door,
|
||||
> step-up's `DoStepDown` probes 0.6 m downward from the sphere's
|
||||
> current position. It finds the SAME flat ground extending to the
|
||||
> OTHER SIDE of the door (Holtburg cottages have no Z change between
|
||||
> exterior and interior floor — both at Z=94). `find_walkable`
|
||||
> declares step-up SUCCESS, the BSP collision returns `OK`, and the
|
||||
> sphere walks through the door.
|
||||
>
|
||||
> The fix probably involves: step-up should reject if a forward probe
|
||||
> at the lifted height STILL hits the same obstacle. The current
|
||||
> DoStepDown probes only DOWNWARD; it doesn't verify that the
|
||||
> forward motion at the lifted height is clear.
|
||||
|
||||
This is speculation — needs apparatus verification.
|
||||
|
||||
---
|
||||
|
||||
## Why the apparatus didn't reproduce the bug
|
||||
|
||||
The grounded apparatus test (`Apparatus_Grounded_50cmOffCenter_*`) was
|
||||
supposed to fail in the same way as production (walk through). Instead
|
||||
it BLOCKED at tick 0 with normal=(0,0,1) — sphere position unchanged.
|
||||
|
||||
Diagnostic output:
|
||||
```
|
||||
[bsp-test] obj=0x000F424F gfx=0x010044B5 ... pos=(11.99,12.12,1.27)
|
||||
distXY=1.234 cacheHit=True
|
||||
[resolve] in=(12.500,11.000,0.480) tgt=(12.500,11.100,0.480)
|
||||
out=(12.500,11.000,0.480) ok=True hit=yes n=(0,0,1) walkable=True
|
||||
```
|
||||
|
||||
`ACDREAM_DUMP_STEPUP=1` produced no `stepup: ENTER` lines, so
|
||||
`DoStepUp` was NOT called. The hit normal `(0,0,1)` came from
|
||||
somewhere else (likely the seeded walkable polygon or the synthetic
|
||||
floor interaction with the engine's terrain step-down).
|
||||
|
||||
The apparatus's stub terrain (Z=-1000) + synthetic walkable poly at
|
||||
Z=0 may be causing the engine to take a different code path than
|
||||
production's real Holtburg terrain. Reproducing production fully
|
||||
would require:
|
||||
|
||||
1. Real terrain heightmap covering the test landblock at Z=94
|
||||
2. EnvCell or stab geometry near the test door
|
||||
3. Proper cottage/cell setup so portal-reachable cells include
|
||||
the door's outdoor cell when player is indoor
|
||||
|
||||
This is significant apparatus investment. Worth it IF the bug
|
||||
requires multi-tick simulation in real geometry to surface. For
|
||||
now, the apparatus shows the broad shape: with proper grounded
|
||||
state + seeded body, the engine doesn't take the same path as
|
||||
the airborne (Path 6) test.
|
||||
|
||||
---
|
||||
|
||||
## Recommended next steps (ranked)
|
||||
|
||||
### Option A — Live diagnostic with ACDREAM_DUMP_STEPUP=1 (cheapest)
|
||||
|
||||
Relaunch with `ACDREAM_PROBE_BUILDING=1` + `ACDREAM_DUMP_STEPUP=1`.
|
||||
Walk into a closed door off-center. The step-up dump will show:
|
||||
- Whether `DoStepUp` fires at all when the BSP hits
|
||||
- If so, what the input normal is
|
||||
- Whether `stepDown` succeeds or fails
|
||||
|
||||
If `stepDown` succeeds (i.e., step-up climbs over the door), we've
|
||||
confirmed the hypothesis above and can target the fix.
|
||||
|
||||
### Option B — Build a richer apparatus
|
||||
|
||||
Replace the stub terrain with a real heightmap-like surface at Z=94
|
||||
spanning the test landblock. Replace the synthetic walkable poly with
|
||||
a proper terrain polygon at the door's world XY. This should let
|
||||
Path 5 run the SAME way as production. Then iterate on the fix
|
||||
locally in <500 ms.
|
||||
|
||||
Estimated effort: 1-2 hours of apparatus work.
|
||||
|
||||
### Option C — Direct retail cdb trace
|
||||
|
||||
Attach cdb to a running retail client at a Holtburg cottage doorway,
|
||||
break on `CTransition::step_up` or `CTransition::step_down`, and
|
||||
observe how retail handles step-up against a door. Compare against
|
||||
acdream's behavior.
|
||||
|
||||
Estimated effort: 30 min - 2 hours depending on what we find.
|
||||
|
||||
### Option D — Pivot to fix-and-verify
|
||||
|
||||
Hypothesis-based fix: in `DoStepUp`, reject step-up if the input
|
||||
collision normal is mostly horizontal AND the obstacle's bounding
|
||||
sphere height range significantly exceeds the step-up height. The
|
||||
door has BS radius 1.975 m centered at Z=1.275 → top of BS at Z=3.25,
|
||||
way above step-up=0.6. If we detect "this obstacle is too tall to
|
||||
step over," fall back to wall-slide.
|
||||
|
||||
Risk: might break stairs / ramps. Need apparatus to verify.
|
||||
|
||||
### Recommendation
|
||||
|
||||
Option A first (~5 min, no code changes needed). If hypothesis
|
||||
confirmed, then Option D (with apparatus from Option B for
|
||||
regression testing).
|
||||
|
||||
---
|
||||
|
||||
## Files touched this session (cumulative)
|
||||
|
||||
**Committed:**
|
||||
- `src/AcDream.Core/Physics/ShadowObjectRegistry.cs` (dedup fix)
|
||||
- `src/AcDream.App/Rendering/GameWindow.cs` (Task 7 wiring)
|
||||
- `tests/AcDream.Core.Tests/Physics/DoorSetupGfxObjInspectionTests.cs` (NEW)
|
||||
- `tests/AcDream.Core.Tests/Physics/DoorCollisionApparatusTests.cs` (NEW)
|
||||
- `docs/research/2026-05-24-door-dat-inspection-findings.md` (NEW)
|
||||
|
||||
**Uncommitted (this doc + 2 file changes):**
|
||||
- `src/AcDream.Core/Physics/TransitionTypes.cs` (added `[bsp-test]` probe)
|
||||
- `tests/AcDream.Core.Tests/Physics/DoorCollisionApparatusTests.cs`
|
||||
(added grounded test scenario — fails for unrelated apparatus
|
||||
reasons but the probe wiring is sound)
|
||||
|
||||
**Memory updated:** `feedback_dedup_keys_after_cardinality_change.md`
|
||||
|
||||
---
|
||||
|
||||
## Pickup prompt for next session
|
||||
|
||||
```
|
||||
A6.P4 Task 7 shipped (RegisterLiveEntityCollision uses
|
||||
ShadowShapeBuilder + RegisterMultiPart) and the foundation fix
|
||||
(GetNearbyObjects dedup on full ShadowEntry instead of entityId).
|
||||
Production verification: center blocks, but off-center + inside-out
|
||||
still walk through closed doors. The multi-part registration is
|
||||
correct (verified by live probes); the remaining bug is downstream
|
||||
in BSPQuery Path 5's step-up logic.
|
||||
|
||||
Read docs/research/2026-05-24-door-collision-task7-shipped-but-bug-remains.md
|
||||
|
||||
State both altitudes:
|
||||
Currently working toward: M1.5 — Indoor world feels right
|
||||
Current phase: A6.P4 door collision — step-up misbehavior
|
||||
investigation. Multi-part registration shipped;
|
||||
step-up at thin tall obstacles is the remaining bug.
|
||||
|
||||
Recommended first move: Option A from the findings doc — relaunch
|
||||
with ACDREAM_PROBE_BUILDING=1 + ACDREAM_DUMP_STEPUP=1, walk into
|
||||
a Holtburg cottage door off-center. The step-up dump will reveal
|
||||
whether DoStepUp is incorrectly succeeding for the door's BSP slab
|
||||
hit (the leading hypothesis: DoStepDown finds the same flat floor
|
||||
on the other side of the door, declaring step-up success).
|
||||
|
||||
DO NOT re-investigate the multi-part registration or GetNearbyObjects
|
||||
dedup — both are confirmed working. Focus on the step-up path 5
|
||||
behavior for thin tall obstacles.
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue