Extrapolating Quaternion Rotation

Hi,

I writing a multi-player game and am having some trouble understanding how to extrapolate a quaternion during prediction on the client side.

For example, let us say I have a quaternion q1 at time t1 and quaternion q2 at time t2 and both are known values that have happened in the passed. On my client I am trying to predict what quaternion q3 will be at time t3 prior to the server providing me the real q3.

Note: t3 > t2 > t1

My quat math is pretty lousy and i’m guessing I can’t just slerp outside the 0 - 1 range.

I hope I have explained myself clearly enough any help would be greatly appreciated

Thx

I think this can be done using the following algorithm: find the rotation rot from q1 to q2 multiplying the inverse of q1 by q2 and calculate the “extrapolation factor” dt = (t3-t1)/(t2-1). dt will be a number > 1, where the integer part means full rot rotations from q1. Apply these full rotations while decrementing dt, and when it falls below 1 use Slerp (or Lerp) to apply the last and partial rotation:

var rot = Quaternion.Inverse(q1)*q2; // rot is the rotation occurred from t1 to t2
var dt = (t3 - t1)/(t2 - t1); // dt = extrapolation factor
var q4 = q2;
while (dt > 1){
    q3 = q4;       // q3 is the last full rotation
    q4 = rot * q4; // q4 is the next full rotation
    dt -= 1;
}
q3 = Quaternion.Slerp(q3, q4, dt);

I haven’t tested this; let me know if it has any error.

EDITED: I tested this algorithm, and found a jerky behaviour at certain angles. Then I studied the case a little more and found (after some Google search) a simpler way to do this. The idea is: a Quaternion is just a rotation of some angle around an arbitrary axis - the angle and axis returned by the function ToAngleAxis. Thus, to extrapolate a quaternion, all we have to do is to get the angle-axis representation, multiply the angle by the extrapolation factor, convert it back to quaternion with AngleAxis, then combine this rotation with the first one.

    var rot = q2*Quaternion.Inverse(q1); // rot is the rotation from t1 to t2
    var dt = (t3 - t1)/(t2 - t1); // dt = extrapolation factor
    var ang: float;
    var axis: Vector3;
    rot.ToAngleAxis(ang, axis); // find axis-angle representation
    if (ang > 180) ang -= 360;  // assume the shortest path
    ang = ang * dt % 360; // multiply angle by the factor
    q3 = Quaternion.AngleAxis(ang, axis) * q1; // combine with first rotation

I tested this approach, and it works perfectly - even for t3 < t2! - without the strange hickups of the previous method.

Here is the same thing in C#:

Quaternion rot = q2 * Quaternion.Inverse( q1 );

double dt = ( t3 - t1 ) / ( t2 - t1 );

float ang = 0.0f;

Vector3 axis = Vector3.zero;

rot.ToAngleAxis(out ang , out axis );

if( ang > 180 )
{
   ang -= 360;
}

ang = ang * (float)dt % 360;

q3 = Quaternion.AngleAxis( ang , axis ) * q1;