Length, Normal and Dot Product

The dot product, length and normalization operations are going to look very familiar. These operations are performed the same way on quaternions as they are on 4 component vectors.

Dot Product

Much like the dot product of vectors, the dot product of quaternions measures how similar two quaternions are. Also like vectors, there is a relation between the angle of the two quaternions and the dot product.

float Dot(Quaternion left, Quaternion right) {
    return left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w;
}

Similar to vectors, the dot product can be used to find the angular difference between two quaternions. But this angular difference isn't as useful for quaternions as it is for vectors.

$$ cos(\theta) = \frac{q_1 \cdot q2}{|q_1||q_2|} $$

Since quaternions in games are unit length, this often simlifies to

$$ cos(\theta) = q_1 \cdot q_2 $$

Length / Magnitude

Just like with vectors, the magnitude of a quaternion is the same as taking the dot product of the vector with its-self. In turn, the length is the square root of this number. Unlike vectors, the length of a quaternion isn't really too useful. Length squared is mainly used to check when a quaternion is no longer of unit length, at which point the quaternion is usually re-normalized.

float LengthSq(Quaternion quat) {
    return quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;
}

float Length(Quaternion quat) {
    float lengthSq = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;
    return sqrt(lengthSq);
}

Normalize

Normalizing a quaternion follows the same process as normalizing a four component vector. To normalize just divide each component by the length of the quaternion. In games almost all quaternions are expected to be unit length, the Normalize function is very important!

float Normalize(Quaternion quat) {
    float lengthSq = quat.x * quat.x + quat.y * quat.y + quat.z * quat.z + quat.w * quat.w;
    assert(lengthAq != 0);
    float invLen = 1.0f / sqrt(lengthSq);

    return Quaternion(
        quat.x * invLen,
        quat.y * invLen,
        quat.z * invLen,
        quat.w * intLen
    )
}