Slerp demystified

I don’t think there’s any problem with me posting the C++ snippet for Unity implementation, just don’t ask me or blame me for it, I didn’t write it :wink: :

Quaternionf Slerp(const Quaternionf& q1, const Quaternionf& q2, float t)
{
    float dot = Dot(q1, q2);

    // dot = cos(theta)
    // if (dot < 0), q1 and q2 are more than 90 degrees apart,
    // so we can invert one to reduce spinning
    Quaternionf tmpQuat;
    if (dot < 0.0f)
    {
        dot = -dot;
        tmpQuat.Set(-q2.x,
            -q2.y,
            -q2.z,
            -q2.w);
    }
    else
        tmpQuat = q2;

    if (dot < 0.95f)
    {
        float angle = acos(dot);
        float sinadiv, sinat, sinaomt;
        sinadiv = 1.0f / sin(angle);
        sinat   = sin(angle * t);
        sinaomt = sin(angle * (1.0f - t));
        tmpQuat.Set((q1.x * sinaomt + tmpQuat.x * sinat) * sinadiv,
            (q1.y * sinaomt + tmpQuat.y * sinat) * sinadiv,
            (q1.z * sinaomt + tmpQuat.z * sinat) * sinadiv,
            (q1.w * sinaomt + tmpQuat.w * sinat) * sinadiv);
        return tmpQuat;
    }
    // if the angle is small, use linear interpolation
    else
    {
        return Lerp(q1, tmpQuat, t);
    }
}
3 Likes