diag(physics): #42 add ACDREAM_AIRBORNE_DIAG [SWEEP] trace
Phase 1 of #42 root-cause investigation per the handoff doc. We
A/B confirmed (commit b37b713) that the ~1m XY drift on retail-
observed stationary jumps comes from inside ResolveWithTransition
when the per-tick airborne sweep runs (CellId fix at GameWindow.cs
3467). What we don't yet know: whether the drift originates in
H1 (initial-overlap depenetration along a tilted-terrain normal),
H2 (step-down probe firing despite isOnGround=false), or H3
(EdgeSlide on near-vertical motion grazing a wall).
This diagnostic gates a one-line Console trace on
ACDREAM_AIRBORNE_DIAG=1 AND !isOnGround so it doesn't pollute
grounded movement, and prints:
[SWEEP] airborne pre=(...) target=(...) post=(...)
cell=PRE->POST ok=BOOL deltaXY=(dx,dy)
cp=valid|none cpN=(nx,ny,nz)
deltaXY = post - target — for a clean stationary +Z jump we
expect (0,0). Non-zero with cp=valid and a tilted cpN confirms
H1; non-zero direction tracking actor facing instead of terrain
orientation points to H2/H3.
Code-walk findings recorded for the next investigation pass:
- K-fix7 already prevents seeding ContactPlane on entry for
airborne (PhysicsEngine.cs:493-519), so step 0's AdjustOffset
cannot consume a stale plane.
- BUT ValidateWalkable can still SET ContactPlane during step 0's
collision pass via the "below plane" branch (TransitionTypes.cs
1320-1352) when sphere lowPoint dips below the tilted terrain
triangle. Step 1's AdjustOffset would then consume that fresh
plane and the "moving away from contact plane" branch
(TransitionTypes.cs:1749-1754) projects the +Z offset along the
slope normal, redirecting Z motion into XY.
- Step-down branch is correctly gated on oi.Contact (matches
retail CTransition::transitional_insert at named-retail
acclient_2013_pseudo_c.txt:273249, "(state & 1) == 0" returns
OK without firing step-down).
- Retail's IS_VIEWER_OI=0x4 branch in OBJECTINFO::validate_walkable
(acclient.h:6185) is never set anywhere in the named decomp,
so the airborne path runs the same code in retail as in acdream.
User repros at flat plaza / east hillside / north hillside; the
direction-correlation of deltaXY with local terrain orientation
identifies which hypothesis is firing.
Build green; 13 PhysicsEngine tests green. No behavior change
when ACDREAM_AIRBORNE_DIAG is unset.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ce638eb56f
commit
a36369d8ca
1 changed files with 27 additions and 0 deletions
|
|
@ -625,6 +625,33 @@ public sealed class PhysicsEngine
|
||||||
bool collisionNormalValid = ci.CollisionNormalValid;
|
bool collisionNormalValid = ci.CollisionNormalValid;
|
||||||
Vector3 collisionNormal = ci.CollisionNormal;
|
Vector3 collisionNormal = ci.CollisionNormal;
|
||||||
|
|
||||||
|
// #42 diagnostic (2026-05-05): trace airborne sweeps to identify the
|
||||||
|
// source of the ~1m XY drift on retail-observed stationary jumps.
|
||||||
|
// Gated on ACDREAM_AIRBORNE_DIAG=1 and !isOnGround. One line per
|
||||||
|
// resolve call. deltaXY = post - target tells us how much the sweep
|
||||||
|
// diverged from the requested target; for a clean stationary +Z
|
||||||
|
// jump we expect (0,0). cp=valid with a tilted normal would confirm
|
||||||
|
// H1 (initial-overlap depenetration → next-step AdjustOffset projects
|
||||||
|
// the +Z offset along a non-+Z normal). User repros at flat plaza /
|
||||||
|
// east hillside / north hillside; if drift direction tracks terrain
|
||||||
|
// orientation, H1 is the cause; if it tracks actor facing, H2 / H3.
|
||||||
|
if (!isOnGround
|
||||||
|
&& Environment.GetEnvironmentVariable("ACDREAM_AIRBORNE_DIAG") == "1")
|
||||||
|
{
|
||||||
|
var post = sp.CheckPos;
|
||||||
|
float dx = post.X - targetPos.X;
|
||||||
|
float dy = post.Y - targetPos.Y;
|
||||||
|
string cpInfo = ci.ContactPlaneValid
|
||||||
|
? $"valid cpN=({ci.ContactPlane.Normal.X:F3},{ci.ContactPlane.Normal.Y:F3},{ci.ContactPlane.Normal.Z:F3})"
|
||||||
|
: "none";
|
||||||
|
Console.WriteLine(
|
||||||
|
$"[SWEEP] airborne pre=({currentPos.X:F3},{currentPos.Y:F3},{currentPos.Z:F3}) " +
|
||||||
|
$"target=({targetPos.X:F3},{targetPos.Y:F3},{targetPos.Z:F3}) " +
|
||||||
|
$"post=({post.X:F3},{post.Y:F3},{post.Z:F3}) " +
|
||||||
|
$"cell={cellId:X8}->{sp.CheckCellId:X8} ok={ok} " +
|
||||||
|
$"deltaXY=({dx:F3},{dy:F3}) cp={cpInfo}");
|
||||||
|
}
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
bool onGround = ci.ContactPlaneValid
|
bool onGround = ci.ContactPlaneValid
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue