fix(runtime): align portal and movement presentation
Port retail portal viewport projection and reveal behavior, preserve outbound combat style, drive remote and local grounded movement from authored CSequence root frames, and reuse the local prepared pose so animation hooks advance once. User-verified portal, observer movement, combat stance, and short-tap locomotion gates. Release build passed with 5,767 tests and five intentional skips. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
e95f55f25b
commit
124e046976
30 changed files with 1362 additions and 348 deletions
|
|
@ -10,7 +10,7 @@ namespace AcDream.Core.Tests.Physics;
|
|||
// from PositionManager; see RemoteMotionCombiner's class doc).
|
||||
//
|
||||
// Mirrors retail CPhysicsObj::UpdateObjectInternal (acclient @ 0x00513730).
|
||||
// Pure-function combiner: animation root motion (seqVel × dt, rotated by
|
||||
// Pure-function combiner: CSequence root-motion delta (rotated by
|
||||
// body orientation) + InterpolationManager.AdjustOffset correction.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ public sealed class RemoteMotionCombinerTests
|
|||
Vector3 offset = pm.ComputeOffset(
|
||||
dt: 0.1,
|
||||
currentBodyPosition: Vector3.Zero,
|
||||
seqVel: Vector3.Zero,
|
||||
rootMotionLocalDelta: Vector3.Zero,
|
||||
ori: Quaternion.Identity,
|
||||
interp: interp,
|
||||
maxSpeed: 4f);
|
||||
|
|
@ -53,11 +53,11 @@ public sealed class RemoteMotionCombinerTests
|
|||
var pm = Make();
|
||||
var interp = EmptyInterp();
|
||||
|
||||
// seqVel = (0, 4, 0), dt = 0.1 → rootMotion = (0, 0.4, 0)
|
||||
// CSequence accumulated (0, 0.4, 0) for this 0.1-second quantum.
|
||||
Vector3 offset = pm.ComputeOffset(
|
||||
dt: 0.1,
|
||||
currentBodyPosition: Vector3.Zero,
|
||||
seqVel: new Vector3(0f, 4f, 0f),
|
||||
rootMotionLocalDelta: new Vector3(0f, 0.4f, 0f),
|
||||
ori: Quaternion.Identity,
|
||||
interp: interp,
|
||||
maxSpeed: 0f);
|
||||
|
|
@ -83,7 +83,7 @@ public sealed class RemoteMotionCombinerTests
|
|||
Vector3 offset = pm.ComputeOffset(
|
||||
dt: 0.1,
|
||||
currentBodyPosition: Vector3.Zero,
|
||||
seqVel: new Vector3(0f, 4f, 0f),
|
||||
rootMotionLocalDelta: new Vector3(0f, 0.4f, 0f),
|
||||
ori: ori,
|
||||
interp: interp,
|
||||
maxSpeed: 0f);
|
||||
|
|
@ -110,7 +110,7 @@ public sealed class RemoteMotionCombinerTests
|
|||
Vector3 offset = pm.ComputeOffset(
|
||||
dt: 0.1,
|
||||
currentBodyPosition: Vector3.Zero,
|
||||
seqVel: Vector3.Zero,
|
||||
rootMotionLocalDelta: Vector3.Zero,
|
||||
ori: Quaternion.Identity,
|
||||
interp: interp,
|
||||
maxSpeed: 4f);
|
||||
|
|
@ -146,7 +146,7 @@ public sealed class RemoteMotionCombinerTests
|
|||
Vector3 offset = pm.ComputeOffset(
|
||||
dt: 0.1,
|
||||
currentBodyPosition: Vector3.Zero,
|
||||
seqVel: new Vector3(0f, 4f, 0f),
|
||||
rootMotionLocalDelta: new Vector3(0f, 0.4f, 0f),
|
||||
ori: Quaternion.Identity,
|
||||
interp: interp,
|
||||
maxSpeed: 4f);
|
||||
|
|
@ -170,12 +170,12 @@ public sealed class RemoteMotionCombinerTests
|
|||
// body-local +Y → world -X
|
||||
Quaternion ori = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, MathF.PI / 2f);
|
||||
|
||||
// seqVel = (0, 1, 0), dt = 1 → rootMotionLocal = (0, 1, 0)
|
||||
// CSequence accumulated rootMotionLocal = (0, 1, 0).
|
||||
// after Transform by ori → (-1, 0, 0) approximately
|
||||
Vector3 offset = pm.ComputeOffset(
|
||||
dt: 1.0,
|
||||
currentBodyPosition: Vector3.Zero,
|
||||
seqVel: new Vector3(0f, 1f, 0f),
|
||||
rootMotionLocalDelta: new Vector3(0f, 1f, 0f),
|
||||
ori: ori,
|
||||
interp: interp,
|
||||
maxSpeed: 0f);
|
||||
|
|
@ -196,7 +196,7 @@ public sealed class RemoteMotionCombinerTests
|
|||
// =========================================================================
|
||||
|
||||
[Fact]
|
||||
public void ComputeOffset_SeqVelFallback_SlopedTerrainNormal_ProjectsZOntoSlope()
|
||||
public void ComputeOffset_RootMotionFallback_SlopedTerrainNormal_ProjectsZOntoSlope()
|
||||
{
|
||||
var pm = Make();
|
||||
var interp = EmptyInterp(); // queue empty → fallback path runs
|
||||
|
|
@ -213,7 +213,7 @@ public sealed class RemoteMotionCombinerTests
|
|||
Vector3 offset = pm.ComputeOffset(
|
||||
dt: 1.0,
|
||||
currentBodyPosition: Vector3.Zero,
|
||||
seqVel: new Vector3(4f, 0f, 0f),
|
||||
rootMotionLocalDelta: new Vector3(4f, 0f, 0f),
|
||||
ori: Quaternion.Identity,
|
||||
interp: interp,
|
||||
maxSpeed: 0f,
|
||||
|
|
@ -225,7 +225,7 @@ public sealed class RemoteMotionCombinerTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ComputeOffset_SeqVelFallback_FlatTerrainNormal_NoZChange()
|
||||
public void ComputeOffset_RootMotionFallback_FlatTerrainNormal_NoZChange()
|
||||
{
|
||||
var pm = Make();
|
||||
var interp = EmptyInterp();
|
||||
|
|
@ -234,7 +234,7 @@ public sealed class RemoteMotionCombinerTests
|
|||
Vector3 offset = pm.ComputeOffset(
|
||||
dt: 0.1,
|
||||
currentBodyPosition: Vector3.Zero,
|
||||
seqVel: new Vector3(0f, 4f, 0f),
|
||||
rootMotionLocalDelta: new Vector3(0f, 0.4f, 0f),
|
||||
ori: Quaternion.Identity,
|
||||
interp: interp,
|
||||
maxSpeed: 0f,
|
||||
|
|
@ -244,4 +244,33 @@ public sealed class RemoteMotionCombinerTests
|
|||
Assert.Equal(0.4f, offset.Y, precision: 4);
|
||||
Assert.Equal(0f, offset.Z, precision: 4);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ComputeOffset_QueueHeadReached_WithLiteralZeroRootMotion_DoesNotOvershoot()
|
||||
{
|
||||
var pm = Make();
|
||||
var interp = new InterpolationManager();
|
||||
var target = new Vector3(0.4f, 0f, 0f);
|
||||
interp.Enqueue(target, heading: 0f, isMovingTo: false);
|
||||
|
||||
Vector3 catchUp = pm.ComputeOffset(
|
||||
dt: 0.1,
|
||||
currentBodyPosition: Vector3.Zero,
|
||||
rootMotionLocalDelta: Vector3.Zero,
|
||||
ori: Quaternion.Identity,
|
||||
interp: interp,
|
||||
maxSpeed: 4f);
|
||||
Vector3 reachedPosition = catchUp;
|
||||
|
||||
Vector3 afterReach = pm.ComputeOffset(
|
||||
dt: 0.1,
|
||||
currentBodyPosition: reachedPosition,
|
||||
rootMotionLocalDelta: Vector3.Zero,
|
||||
ori: Quaternion.Identity,
|
||||
interp: interp,
|
||||
maxSpeed: 4f);
|
||||
|
||||
Assert.Equal(target, reachedPosition);
|
||||
Assert.Equal(Vector3.Zero, afterReach);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue