docs(research): handoff prompt for #42 PhysicsEngine investigation

Self-contained next-session brief for the airborne XY drift
follow-up. Captures: confirmed root cause (ResolveWithTransition,
verified A/B), three ranked hypotheses for the in-sweep mechanism
(initial-overlap depenetration on non-+Z terrain normal is leading),
three fix paths in preference order, repro steps with terrain-slope
direction-correlation test, and the acceptance criteria.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-05 15:48:45 +02:00
parent b37b7137f6
commit 5cc281251a

View file

@ -0,0 +1,96 @@
# #42 follow-up — PhysicsEngine.ResolveWithTransition airborne XY drift
**Context:** L.3 motion port landed in this branch (commits `de129bc`
`40d88b9` `2365c8c` `d57ace0` `c26bbbb` `b37b713`) — player-remote
running/walking/strafing/NPCs all visually verified clean. M4 jump
landing was fixed (CellId update). But that fix re-enabled
`ResolveWithTransition` per-tick during airborne arcs and exposed a
pre-existing PhysicsEngine bug: stationary jumps render with ~1 m
horizontal offset from the actor's actual XY, then snap back on the
next UM/UP.
**Confirmed root cause** (A/B-tested 2026-05-05): drift originates
inside `ResolveWithTransition`, not from wire data, local Euler error,
or stale velocity. With the sweep skipped, jumps render geometrically
correct (but body falls through floor). With it enabled, jumps land
correctly but show the drift. So the bug lives in the sweep.
## Most likely mechanism
**Initial-overlap depenetration along non-+Z terrain normal.** At
jump start the collision sphere is touching the floor at body Z. Most
outdoor terrain triangles have non-vertical normals (small horizontal
component). The sweep's first-frame action is to resolve the
penetration by separating the sphere along the contact normal — and
on a tilted triangle that separation has horizontal magnitude. The
body gets shoved sideways the first frame; the rest of the arc
carries the offset.
Direction-correlation test: jump at multiple landblock positions; if
drift direction varies with terrain slope orientation (not actor
facing), this hypothesis is confirmed.
Other candidates ranked by probability:
2. Step-down probe firing despite `isOnGround: false` parameter.
3. EdgeSlide on near-vertical motion against near-vertical surface.
## Files to investigate
- `src/AcDream.Core/Physics/PhysicsEngine.cs``ResolveWithTransition`
+ any internal `CTransition` / `find_valid_position` helpers. The
initial-overlap depenetration path is the primary target.
- Reference at `docs/research/named-retail/acclient_2013_pseudo_c.txt`:
- `CTransition::find_valid_position` (called from `transition()`)
- `SpherePath` initialization
- Verbatim retail depenetration logic for airborne bodies
If our port differs from retail in this region, that diff is the bug.
## Fix paths (in order of preference)
**(a) Skip initial-overlap depenetration when airborne.** Gate the
"separate from initial contact plane" step inside
`ResolveWithTransition` on `isOnGround: true`. Trusts the previous
tick's resolve to have left the body in a non-overlapping position.
Most likely correct fix.
**(b) Zero step-up/down for airborne sweeps.** Pass
`stepUpHeight: 0f, stepDownHeight: 0f` from
`GameWindow.cs:6478+` when `rm.Airborne`. No side effects since
airborne bodies don't step.
**(c) Stripped airborne sweep.** Replace the full sphere sweep with a
simpler vertical sphere-vs-terrain intersection + wall-collision
stop. Loses retail fidelity but eliminates all three mechanisms.
Probably overkill if (a) or (b) suffices.
## Repro
1. Launch acdream + retail client side-by-side on local ACE
(127.0.0.1:9000).
2. Have a retail-controlled toon stand still on outdoor terrain.
3. Jump in place.
4. Observe acdream window: arc shows ~1 m XY offset, lands offset,
snaps back on next inbound UM.
To verify hypothesis (1) specifically: repeat the jump on terrain
patches with different visible slope orientations; if drift direction
changes accordingly, depenetration is confirmed.
## Acceptance
- Stationary jumps render at the actor's actual XY (no perceptible
drift, no snap-back on next UM).
- Wall-collision airborne still works (jumping into doorways, jumping
puzzles where you have to thread between platforms or through arches).
## Operating notes
- This is a `PhysicsEngine` bug, not a motion-port bug. The L.3 work
is done; this is a separate investigation.
- The `[VU.WIRE]` instrumentation idea from #42's earlier draft can
be skipped — we already proved wire data isn't the source via the
A/B test.
- cdb attach to retail (`docs/research/2026-05-04-l3-port/`-adjacent
toolchain documented in CLAUDE.md) is available if comparing
retail's airborne sweep behavior against ours becomes useful.