feat(physics): port retail complete object frame pipeline

Restore the named-retail object update order across local, remote, static, projectile, animation, shadow, teleport, and effect lifetimes. Separate authoritative root commits from spatial rebucketing, preserve per-owner hook/FIFO ordering, and remove update-path allocations with exact lifecycle and residency gates.

Add deterministic conformance, adversarial lifetime, GUID-reuse, pending-cell, quaternion, timestamp, and allocation coverage. Release build is warning-free and all 6,446 tests pass with five intentional skips; retail, architecture, and adversarial reviews are clean.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-20 09:10:31 +02:00
parent 31a0889f08
commit f961d70023
77 changed files with 12513 additions and 1871 deletions

View file

@ -15,10 +15,10 @@ namespace AcDream.Core.Physics.Motion;
///
/// <para><see cref="Origin"/> = retail <c>m_fOrigin</c> (the accumulated
/// position delta, in the mover's LOCAL frame after
/// <c>Position::globaltolocalvec</c>). <see cref="Orientation"/> carries the
/// heading retail's <c>Frame::set_heading</c> writes; read/write it as a
/// compass heading via <see cref="GetHeading"/> / <see cref="SetHeading"/>
/// (P5 convention, degrees).</para>
/// <c>Position::globaltolocalvec</c>). <see cref="Orientation"/> is the full
/// relative quaternion carried by retail <c>Frame</c>; the heading accessors
/// are narrow helpers for managers that explicitly call
/// <c>Frame::set_heading</c>.</para>
/// </summary>
public sealed class MotionDeltaFrame
{
@ -26,10 +26,50 @@ public sealed class MotionDeltaFrame
/// delta (mover-local frame).</summary>
public Vector3 Origin;
/// <summary>Retail <c>Frame</c> rotation — carries the
/// <c>Frame::set_heading</c> output.</summary>
/// <summary>Retail <c>Frame</c>'s complete relative rotation.</summary>
public Quaternion Orientation = Quaternion.Identity;
/// <summary>
/// Restore retail's identity <c>Frame</c>: zero translation and identity
/// orientation. Object ticks reuse these accumulators to avoid allocating
/// one transform per entity per render frame.
/// </summary>
public void Reset()
{
Origin = Vector3.Zero;
Orientation = Quaternion.Identity;
}
/// <summary>
/// Retail <c>Frame::combine</c> (0x005122E0), specialized for the mutable
/// per-tick delta frame. The incoming translation is expressed in this
/// frame's local coordinates, so the current orientation rotates it before
/// addition; the incoming orientation is then post-multiplied. Translation
/// scaling is the separate <c>m_scale</c> operation performed by
/// <c>CPhysicsObj::UpdatePositionInternal</c>.
/// </summary>
public void Combine(
Vector3 localOrigin,
Quaternion localOrientation,
float originScale = 1f)
{
Origin += Vector3.Transform(localOrigin * originScale, Orientation);
Orientation = FrameOps.SetRotate(
Origin,
Orientation,
Orientation * localOrientation);
}
/// <summary>
/// Compose another complete delta frame using retail
/// <c>Frame::combine</c> semantics.
/// </summary>
public void Combine(MotionDeltaFrame delta, float originScale = 1f)
{
ArgumentNullException.ThrowIfNull(delta);
Combine(delta.Origin, delta.Orientation, originScale);
}
/// <summary>Retail <c>Frame::get_heading</c> (P5 compass degrees).</summary>
public float GetHeading() => MoveToMath.GetHeading(Orientation);