docs(handoff): add second door-bug symptom (over-penetration before block)

This commit is contained in:
Erik 2026-05-25 10:45:41 +02:00
parent fd1548af61
commit 2deb539953

View file

@ -69,6 +69,37 @@ traversal.
Once that's in place, the existing Path 5 changes + TransitionalInsert
NegPolyHit dispatch should fire correctly and produce the block.
## Second symptom flagged by user (2026-05-25 evening)
User flagged: "we get run a bit into the door as well when it blocks.
That is not retail behavior."
Over-penetration before block = our BSP detects collision AFTER the
sphere has already moved into the surface (static overlap detection)
vs retail's swept-sphere collision (predicts the t-value of first
contact along the motion path and stops the sphere at the surface).
This is the SAME ROOT MECHANISM as the squeeze-through:
sphere_intersects_poly in retail does swept collision with the
motion vector (var_44 = sphere_center - prev_center). Our
`SphereIntersectsPolyInternal` takes a `movement` parameter but the
internal poly-test logic may not actually use it for swept detection.
Verifying: read SphereIntersectsPolyInternal and check whether it
uses the `movement` vector for swept-sphere-vs-poly intersection
testing (computes the t-value where sphere first contacts the poly
along motion), or just does static overlap (sphere center +/- radius
overlaps poly plane). Retail does swept (the `var_44` in
sphere_intersects_poly is the motion delta).
Single fix needed in next session: SphereIntersectsPolyInternal needs to:
1. Implement swept-sphere-vs-poly detection (use the motion vector)
2. Record the closest-considered polygon for near-miss handling
Both feed into the existing Path 5 + TransitionalInsert dispatch
(committed today). Once that single function does its job correctly,
both symptoms close at once.
## What the cdb trace proved
| Symbol | v1 hits | v2 hits | v3 hits |
@ -115,14 +146,26 @@ side-effect; our equivalent only sets it on full hits.
Current phase: A6.P4 door bug — implement near-miss polygon
recording in SphereIntersectsPolyInternal.
TWO SYMPTOMS to fix simultaneously (same root cause):
(a) Off-center inside-out: sphere walks (or squeezes) past door
(b) When blocked: sphere visibly penetrates the door before stopping
Both = static overlap detection without near-miss recording.
Retail uses swept-sphere-vs-poly intersection (uses motion vector
to compute t-value of first contact, stops sphere at surface)
AND records the closest near-miss polygon during BSP traversal.
First move: read SphereIntersectsPolyInternal in
src/AcDream.Core/Physics/BSPQuery.cs (the function used at the
Path 5 entry). Identify where polygons are tested during BSP
traversal. Add a "closestPoly" output param that's set to ANY
polygon considered during traversal (not just hit polygons).
src/AcDream.Core/Physics/BSPQuery.cs. Check whether the `movement`
param is actually used for swept-sphere-vs-poly testing. If not
(just static overlap), that's symptom (b). Add swept detection
and a "closestPoly" output param set on ANY polygon considered
during traversal (not just hits). That closes symptom (a) too.
Then the Path 5 branch `if (hitPoly0 is not null)` will fire on
near-miss cases, NegPolyHitDispatch will set NegPolyHit, and the
TransitionalInsert dispatch (already landed) will block the sphere.
TransitionalInsert dispatch (already landed) will block the sphere
at the surface (swept-detected t-value), not after penetration.
Retail oracle: BSPTREE::find_collisions + sphere_intersects_poly
vtable call at acclient_2013_pseudo_c.txt:0053a630-0053a6fb.