Multiplying Quaternions implies a rotation of a vector in 3D space and it is commonly used in 3D computer graphics algorithms because it is simpler and cheaper than the matrix multiplication. This page is focused on how to convert a Quaternion rotation to a 4x4 rotation matrix form using Quaternion algebra. Note that OpenGL accepts only 4x4 matrix to transform vertices.
Suppose there is a 3D vector, and rotate it along an arbitrary axis (unit vector) by angle .
The vector can be converted as Quaternion form;
(We only use x, y and z components for .)
And, the Quaternion representation for the rotation axis vector and the half rotation angle can be written as;
(Note that we only uses half angle to define the rotation quaternion q because we are going to multiply q twice.)
To rotate the quaternion p, we simply multiply the quaternion q. However, the length of p is changed during multiplication, so we multiply q* (conjugate of q) again at the back of p in order to cancel out the length changes. Since we multiply q twice, front and back, we only need a half rotation angle for q. Therefore, the final equation for the rotation in Quaternion becomes .
This special double multiplication is called "conjugation by q". Here explains why this double multiplication is required and the proof of the length conservation.
In this section, we calculate from arbitrary Quaternions, p and q. Let's say p and q are defined as below, and q is normalized ();
For a typical usage, rotating a 3D vector, we can set the scalar component to 0 for p. It makes the multiplication simpler, but here we use a generic 4-component quaternion for p.
First we multiply p by q (applying q on p);
The above equation is simplified by Quaternion quadrantal (perpendicular) vectors property.
Let's set each component of to , , and respectively.
Then, multiply the conjugate of q at the back of the previous multiplication.
Since the equation becomes too long, we compute each term and component independently and combine them later. This page provides the complete computation of . You may skip to the final result of below.
The scalar component of ;
The x component of ;
The y component of ;
The z component of ;
Finally, combine s, x, y and z components into the rotation quaternion, ;
Since q is a unit quaternion, substitute the followings to the above equation to simplify it a little further.
The final simplified rotation quaternion becomes;
Now, we only take the x, y and z compoments (without i, j and k), and convert it to a matrix form. It becomes multiplying a 3x3 matrix to a 3D vector to transform.
The 3x3 matrix itself is the rotation matrix equivalent to the quaternion rotation;
Or, as 4x4 matrix;
This example provides C++ Quaternion class and tests rotating a vertex, (1, 2, 3) along a rotation axis, (0.57735, 0.57735, 0.57735) by 45 degree. We need to convert the vertex and rotation axis to quaternion forms first, then rotate it with quaternion multiplication, . The Quaternion class provides getMatrix() to convert the rotation quaternion to 4x4 matrix. It verifies the rotation result by comparing with rotation matrix.
Vector3 v(1, 2, 3); // 3D vertex to rotate Vector3 r(0.57735f, 0.57735f, 0.57735f); // rotation axis (unit vector) float a = 45.0f; // rotation angle in degree // convert to quaternions Quaternion p = Quaternion(0, v.x, v.y, v.z); // quaternion form of v Quaternion q = Quaternion(r, a * 0.5f * D2R); // rotation quaternion with half-angle Quaternion c = q; // copy of q c.conjugate(); // q* (conjugate of q) // rotate p by multiplying qpq* Quaternion p2 = q * p * c; // vector part of p2 contains the rotated 3D vertex Vector3 v2(p2.x, p2.y, p2.z); // quaternion to vector std::cout << "v2: " << v2 << std::endl; // print the result // OR, convert quaternion to 4x4 roatation matrix Matrix4 m = q.getMatrix(); v2 = m * v; // rotation using matrix instead // OR, use matrix rotation directly Matrix4 m m.rotate(a, r); // rotate A degree along R axis v2 = m * v; // rotation using matrix instead
If there is a sequence of multiple rotations, we can simply multiply the quaternions one after another, similar to matrix transformations. Multiplication of 2 quaternions requires 16 products and 12 additions. On the contrary, multiplying two 4x4 matrices needs 64 products and 48 additions.
// 3 rotations in quaternion form Quaternion qx = Quaternion(Vector3(1, 0, 0), 22.5f * D2R); // 45 degree about x-axis Quaternion qy = Quaternion(Vector3(0, 1, 0), 22.5f * D2R); // 45 degree about y-axis Quaternion qz = Quaternion(Vector3(0, 0, 1), 22.5f * D2R); // 45 degree about z-axis // compose multiple rotations, order is qz -> qy -> qx Quaternion q = qx * qy * qz; std::cout << "q: " << q << std::endl; // print the result