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:
parent
31a0889f08
commit
f961d70023
77 changed files with 12513 additions and 1871 deletions
|
|
@ -25,6 +25,48 @@ public static class FrameOps
|
|||
/// square against |v|².</summary>
|
||||
public const float FEpsilon = 0.000199999995f;
|
||||
|
||||
/// <summary>
|
||||
/// Retail <c>Frame::set_rotate</c> (0x00535080). The candidate is
|
||||
/// normalized in extended precision, then the complete frame is checked
|
||||
/// by <c>Frame::IsValid</c> (0x00534ED0). If that check fails, retail
|
||||
/// restores the previous quaternion instead of allowing NaNs to poison
|
||||
/// the live object transform.
|
||||
/// </summary>
|
||||
public static Quaternion SetRotate(
|
||||
Vector3 frameOrigin,
|
||||
Quaternion previous,
|
||||
Quaternion candidate)
|
||||
{
|
||||
double lengthSquared =
|
||||
((double)candidate.W * candidate.W)
|
||||
+ ((double)candidate.X * candidate.X)
|
||||
+ ((double)candidate.Y * candidate.Y)
|
||||
+ ((double)candidate.Z * candidate.Z);
|
||||
double inverseLength = 1.0 / Math.Sqrt(lengthSquared);
|
||||
var normalized = new Quaternion(
|
||||
(float)(candidate.X * inverseLength),
|
||||
(float)(candidate.Y * inverseLength),
|
||||
(float)(candidate.Z * inverseLength),
|
||||
(float)(candidate.W * inverseLength));
|
||||
|
||||
if (float.IsNaN(frameOrigin.X)
|
||||
|| float.IsNaN(frameOrigin.Y)
|
||||
|| float.IsNaN(frameOrigin.Z)
|
||||
|| float.IsNaN(normalized.W)
|
||||
|| float.IsNaN(normalized.X)
|
||||
|| float.IsNaN(normalized.Y)
|
||||
|| float.IsNaN(normalized.Z))
|
||||
{
|
||||
return previous;
|
||||
}
|
||||
|
||||
float normalizedLengthSquared = normalized.LengthSquared();
|
||||
return !float.IsNaN(normalizedLengthSquared)
|
||||
&& MathF.Abs(normalizedLengthSquared - 1f) < FEpsilon * 5f
|
||||
? normalized
|
||||
: previous;
|
||||
}
|
||||
|
||||
/// <summary><c>Frame::grotate</c> — incremental WORLD-space rotation.</summary>
|
||||
public static void GRotate(Frame frame, Vector3 rotationGlobal)
|
||||
{
|
||||
|
|
@ -48,7 +90,10 @@ public static class FrameOps
|
|||
rotationGlobal.Y * s * invMag,
|
||||
rotationGlobal.Z * s * invMag,
|
||||
c);
|
||||
frame.Orientation = Quaternion.Normalize(Quaternion.Multiply(r, frame.Orientation));
|
||||
frame.Orientation = SetRotate(
|
||||
frame.Origin,
|
||||
frame.Orientation,
|
||||
Quaternion.Multiply(r, frame.Orientation));
|
||||
}
|
||||
|
||||
/// <summary><c>Frame::rotate</c> — LOCAL rotation vector, mapped to
|
||||
|
|
@ -65,7 +110,10 @@ public static class FrameOps
|
|||
public static void Combine(Frame frame, Frame pos)
|
||||
{
|
||||
frame.Origin += Vector3.Transform(pos.Origin, frame.Orientation);
|
||||
frame.Orientation = Quaternion.Normalize(frame.Orientation * pos.Orientation);
|
||||
frame.Orientation = SetRotate(
|
||||
frame.Origin,
|
||||
frame.Orientation,
|
||||
frame.Orientation * pos.Orientation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -75,7 +123,9 @@ public static class FrameOps
|
|||
/// </summary>
|
||||
public static void Subtract1(Frame frame, Frame pos)
|
||||
{
|
||||
frame.Orientation = Quaternion.Normalize(
|
||||
frame.Orientation = SetRotate(
|
||||
frame.Origin,
|
||||
frame.Orientation,
|
||||
frame.Orientation * Quaternion.Conjugate(pos.Orientation));
|
||||
frame.Origin -= Vector3.Transform(pos.Origin, frame.Orientation);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue