fix(motion): port calc_acceleration + sequencer omega to retail tick (L.3.1+L.3.2)
Visual verification (Task 4) revealed two missing pieces from the retail per-frame tick port (acclient!CPhysicsObj::update_object @ 0x00513730): 1. body.calc_acceleration() must run BEFORE UpdatePhysicsInternal so gravity (set via PhysicsStateFlags.Gravity in OnLiveVectorUpdated) actually decays jump velocity. Without it body.Acceleration stays stale or zero → endless rise on jumps. 2. sequencer.CurrentOmega must be applied to body.Orientation per frame. Retail's TurnRight/TurnLeft cycles bake angular velocity that drives smooth rotation between UPs; we were only snapping orientation on UP receipt (~1 Hz), producing visible chop on turning remotes. Both fixes are part of the retail tick we already started porting in PositionManager — just missing pieces. Speed-overshoot bug (sequencer.CurrentVelocity > server's actual broadcast pace) is still being investigated in a follow-up. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
e94e7913fb
commit
c1bfd64834
1 changed files with 33 additions and 2 deletions
|
|
@ -5789,14 +5789,23 @@ public sealed class GameWindow : IDisposable
|
||||||
if (System.Environment.GetEnvironmentVariable("ACDREAM_INTERP_MANAGER") == "1")
|
if (System.Environment.GetEnvironmentVariable("ACDREAM_INTERP_MANAGER") == "1")
|
||||||
{
|
{
|
||||||
// ── NEW PATH: PositionManager (animation root motion + InterpolationManager) ──
|
// ── NEW PATH: PositionManager (animation root motion + InterpolationManager) ──
|
||||||
// (L.3.1+L.3.2 Task 3 — ACDREAM_INTERP_MANAGER=1 gates this path)
|
// (L.3.1+L.3.2 Task 3/follow-up — ACDREAM_INTERP_MANAGER=1 gates this path)
|
||||||
//
|
//
|
||||||
// Always-run-all-steps per retail CPhysicsObj::UpdateObjectInternal
|
// Always-run-all-steps per retail CPhysicsObj::UpdateObjectInternal
|
||||||
// (acclient @ 0x00513730):
|
// (acclient @ 0x00513730):
|
||||||
// 1+2. animation root motion + interpolation correction (combined)
|
// 1+2. animation root motion + interpolation correction (combined)
|
||||||
// 3. physics integration (gravity for airborne; no-op for grounded)
|
// 2.5 sequencer omega → body orientation (TurnRight/TurnLeft angular velocity)
|
||||||
|
// 3. calc_acceleration (gravity flag → body.Acceleration)
|
||||||
|
// 4. physics integration (gravity for airborne; no-op for grounded)
|
||||||
|
|
||||||
|
// Sequencer-driven motion sources: linear velocity (root motion)
|
||||||
|
// AND angular velocity (turn-cycle omega).
|
||||||
System.Numerics.Vector3 seqVel = ae.Sequencer?.CurrentVelocity
|
System.Numerics.Vector3 seqVel = ae.Sequencer?.CurrentVelocity
|
||||||
?? System.Numerics.Vector3.Zero;
|
?? System.Numerics.Vector3.Zero;
|
||||||
|
System.Numerics.Vector3 seqOmega = ae.Sequencer?.CurrentOmega
|
||||||
|
?? System.Numerics.Vector3.Zero;
|
||||||
|
|
||||||
|
// Step 1+2: animation root motion + Interp correction (combined via PositionManager).
|
||||||
float maxSpeed = rm.Motion.GetMaxSpeed();
|
float maxSpeed = rm.Motion.GetMaxSpeed();
|
||||||
System.Numerics.Vector3 offset = rm.Position.ComputeOffset(
|
System.Numerics.Vector3 offset = rm.Position.ComputeOffset(
|
||||||
dt: (double)dt,
|
dt: (double)dt,
|
||||||
|
|
@ -5806,6 +5815,28 @@ public sealed class GameWindow : IDisposable
|
||||||
interp: rm.Interp,
|
interp: rm.Interp,
|
||||||
maxSpeed: maxSpeed);
|
maxSpeed: maxSpeed);
|
||||||
rm.Body.Position += offset;
|
rm.Body.Position += offset;
|
||||||
|
|
||||||
|
// Step 2.5: animation-driven rotation. Retail's sequencer bakes Omega
|
||||||
|
// for TurnRight/TurnLeft cycles; we apply it as a per-frame quaternion
|
||||||
|
// rotation. seqOmega is body-local angular velocity (axis-angle: axis
|
||||||
|
// is omega.Normalized, magnitude is rad/sec). For Z-axis turns it's
|
||||||
|
// (0, 0, ±π/2 × turnSpeed) typically.
|
||||||
|
if (seqOmega.LengthSquared() > 1e-9f)
|
||||||
|
{
|
||||||
|
float angleDelta = seqOmega.Length() * (float)dt;
|
||||||
|
System.Numerics.Vector3 axis = System.Numerics.Vector3.Normalize(seqOmega);
|
||||||
|
var rot = System.Numerics.Quaternion.CreateFromAxisAngle(axis, angleDelta);
|
||||||
|
rm.Body.Orientation = System.Numerics.Quaternion.Normalize(
|
||||||
|
System.Numerics.Quaternion.Concatenate(rm.Body.Orientation, rot));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: calc_acceleration sets body.Acceleration from the Gravity flag
|
||||||
|
// (mirrors retail CPhysicsObj::calc_acceleration @ FUN_00511420, called
|
||||||
|
// per-frame in update_object). Without this, body.Acceleration stays stale
|
||||||
|
// or zero → gravity never decays jump velocity → endless rise on jumps.
|
||||||
|
rm.Body.calc_acceleration();
|
||||||
|
|
||||||
|
// Step 4: physics integration (Euler: pos += vel*dt + 0.5*accel*dt²).
|
||||||
rm.Body.UpdatePhysicsInternal(dt);
|
rm.Body.UpdatePhysicsInternal(dt);
|
||||||
|
|
||||||
ae.Entity.Position = rm.Body.Position;
|
ae.Entity.Position = rm.Body.Position;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue