Prediction: sync delta rotations too [FakeByte]

This commit is contained in:
mischa 2024-02-14 10:45:50 +01:00 committed by mischa
parent beea27275f
commit 41a6591f8a
4 changed files with 20 additions and 20 deletions

View File

@ -279,7 +279,8 @@ protected virtual void SmoothFollowPhysicsCopy()
// smoothly interpolate to the target rotation.
// Quaternion.RotateTowards doesn't seem to work at all, so let's use SLerp.
Quaternion newRotation = Quaternion.Slerp(currentRotation, physicsRotation, rotationInterpolationSpeed * deltaTime);
// Quaternions always need to be normalized in order to be a valid rotation after operations
Quaternion newRotation = Quaternion.Slerp(currentRotation, physicsRotation, rotationInterpolationSpeed * deltaTime).normalized;
// assign position and rotation together. faster than accessing manually.
tf.SetPositionAndRotation(newPosition, newRotation);
@ -438,13 +439,14 @@ void RecordState()
Vector3 positionDelta = Vector3.zero;
Vector3 velocityDelta = Vector3.zero;
Vector3 angularVelocityDelta = Vector3.zero;
// Quaternion rotationDelta = Quaternion.identity; // currently unused
Quaternion rotationDelta = Quaternion.identity;
if (stateHistory.Count > 0)
{
RigidbodyState last = stateHistory.Values[stateHistory.Count - 1];
positionDelta = currentPosition - last.position;
velocityDelta = currentVelocity - last.velocity;
// rotationDelta = currentRotation * Quaternion.Inverse(last.rotation); // this is how you calculate a quaternion delta (currently unused, don't do the computation)
// Quaternions always need to be normalized in order to be valid rotations after operations
rotationDelta = (currentRotation * Quaternion.Inverse(last.rotation)).normalized;
angularVelocityDelta = currentAngularVelocity - last.angularVelocity;
// debug draw the recorded state
@ -456,7 +458,7 @@ void RecordState()
predictedTime,
positionDelta,
currentPosition,
// rotationDelta, // currently unused
rotationDelta,
currentRotation,
velocityDelta,
currentVelocity,
@ -509,7 +511,7 @@ void ApplyState(double timestamp, Vector3 position, Quaternion rotation, Vector3
timestamp,
Vector3.zero,
position,
// Quaternion.identity, // rotationDelta: currently unused
Quaternion.identity,
rotation,
Vector3.zero,
velocity,
@ -738,7 +740,7 @@ public override void OnDeserialize(NetworkReader reader, bool initialState)
Vector3 angularVelocity = reader.ReadVector3();
// process received state
OnReceivedState(timestamp, new RigidbodyState(timestamp, Vector3.zero, position, /*Quaternion.identity,*/ rotation, Vector3.zero, velocity, Vector3.zero, angularVelocity));
OnReceivedState(timestamp, new RigidbodyState(timestamp, Vector3.zero, position, Quaternion.identity, rotation, Vector3.zero, velocity, Vector3.zero, angularVelocity));
}
protected override void OnValidate()

View File

@ -12,7 +12,7 @@ public struct RigidbodyState : PredictedState
public Vector3 positionDelta { get; set; } // delta to get from last to this position
public Vector3 position { get; set; }
// public Quaternion rotationDelta { get; set; } // delta to get from last to this rotation
public Quaternion rotationDelta { get; set; } // delta to get from last to this rotation
public Quaternion rotation { get; set; }
public Vector3 velocityDelta { get; set; } // delta to get from last to this velocity
@ -25,7 +25,7 @@ public RigidbodyState(
double timestamp,
Vector3 positionDelta,
Vector3 position,
// Quaternion rotationDelta, // currently unused
Quaternion rotationDelta,
Quaternion rotation,
Vector3 velocityDelta,
Vector3 velocity,
@ -35,7 +35,7 @@ public RigidbodyState(
this.timestamp = timestamp;
this.positionDelta = positionDelta;
this.position = position;
// this.rotationDelta = rotationDelta;
this.rotationDelta = rotationDelta;
this.rotation = rotation;
this.velocityDelta = velocityDelta;
this.velocity = velocity;
@ -48,7 +48,8 @@ public static RigidbodyState Interpolate(RigidbodyState a, RigidbodyState b, flo
return new RigidbodyState
{
position = Vector3.Lerp(a.position, b.position, t),
rotation = Quaternion.Slerp(a.rotation, b.rotation, t),
// Quaternions always need to be normalized in order to be a valid rotation after operations
rotation = Quaternion.Slerp(a.rotation, b.rotation, t).normalized,
velocity = Vector3.Lerp(a.velocity, b.velocity, t),
angularVelocity = Vector3.Lerp(a.angularVelocity, b.angularVelocity, t)
};

View File

@ -15,7 +15,7 @@ public interface PredictedState
Vector3 positionDelta { get; set; }
Quaternion rotation { get; set; }
// Quaternion rotationDelta { get; set; } // currently unused
Quaternion rotationDelta { get; set; }
Vector3 velocity { get; set; }
Vector3 velocityDelta { get; set; }
@ -142,9 +142,8 @@ public static T CorrectHistory<T>(
after.positionDelta = Vector3.Lerp(Vector3.zero, after.positionDelta, (float)multiplier);
after.velocityDelta = Vector3.Lerp(Vector3.zero, after.velocityDelta, (float)multiplier);
after.angularVelocityDelta = Vector3.Lerp(Vector3.zero, after.angularVelocityDelta, (float)multiplier);
// rotation deltas aren't working yet. instead, we apply the corrected rotation to all entries after the correction below.
// this at least syncs the rotations and looks quite decent, compared to not syncing!
// after.rotationDelta = Quaternion.Slerp(Quaternion.identity, after.rotationDelta, (float)multiplier);
// Quaternions always need to be normalized in order to be a valid rotation after operations
after.rotationDelta = Quaternion.Slerp(Quaternion.identity, after.rotationDelta, (float)multiplier).normalized;
// changes aren't saved until we overwrite them in the history
stateHistory[after.timestamp] = after;
@ -160,10 +159,8 @@ public static T CorrectHistory<T>(
entry.position = last.position + entry.positionDelta;
entry.velocity = last.velocity + entry.velocityDelta;
entry.angularVelocity = last.angularVelocity + entry.angularVelocityDelta;
// rotation deltas aren't working yet. instead, we apply the corrected rotation to all entries after the correction.
// this at least syncs the rotations and looks quite decent, compared to not syncing!
// entry.rotation = entry.rotationDelta * last.rotation; // quaternions add delta by multiplying in this order
entry.rotation = corrected.rotation;
// Quaternions always need to be normalized in order to be a valid rotation after operations
entry.rotation = (entry.rotationDelta * last.rotation).normalized; // quaternions add delta by multiplying in this order
// save the corrected entry into history.
stateHistory[key] = entry;

View File

@ -14,7 +14,7 @@ struct TestState : PredictedState
public Vector3 positionDelta { get; set; }
public Quaternion rotation { get; set; }
// public Quaternion rotationDelta { get; set; } // currently unused
public Quaternion rotationDelta { get; set; }
public Vector3 velocity { get; set; }
public Vector3 velocityDelta { get; set; }
@ -28,7 +28,7 @@ public TestState(double timestamp, Vector3 position, Vector3 positionDelta, Vect
this.position = position;
this.positionDelta = positionDelta;
this.rotation = Quaternion.identity;
// this.rotationDelta = Quaternion.identity;
this.rotationDelta = Quaternion.identity;
this.velocity = velocity;
this.velocityDelta = velocityDelta;
this.angularVelocity = angularVelocity;