**Related Topics:** OpenGL Matrix, Quaternion to Matrix, Angles To Axes, Lookat To Axes

**Download:** rotate.zip

The 4x4 transformation matrix for rotating about an arbitrary axis in OpenGL is defined as;

This page explains how to derive this rotation matrix using Rodrigues' formula. Suppose a 3D point *P* is rotating to Q by an angle along a unit vector . The vector form of P is broken up the sum of and , and Q is the sum of and respectively;

,

Therefore, we need to find and first in order to get Q. The vector can be aquired from , and comes from the circular plane, where the point Q lies on. is parallel to the unit vector , and its length can be computed by projecting to using inner product. So, it can be written;

can be determined by 2 basis vectors on the rotation plane. We use as the first basis vector, and the other basis vector is perpendicular to and has equal length because they are both the radius of the circluar plane. Therefore, can be computed by the cross product of 2 perpendicular vectors; and ;

Now, is represented with the composition of these basis vectors and trigonometric functions;

Finally, the rotated vector is written by the sum of and ;

This equation is called Rodrigues' rotation formula;

It can be represented by an equivalent matrix form. First, convert and components to 3x3 matrix forms for P = (p_{x}, p_{y}, p_{z}) and r = (x, y, z);

Finally, the equivalent matrix form by substituting the above matrix components is;

And, the 3x3 rotation matrix alone is

Or, as 4x4 matrix;

The following C++ code snippet is rotating a 3D point P to Q along the rotation axis using Rodrigues' formula. Download the complete implementation from rotate.zip.

```
// minimal implementation of Vector3
struct Vector3
{
float x, y, z;
// ctor
Vector3() : x(0), y(0), z(0) {}
// inner and cross products
float dot(Vector3& v) { return x*v.x + y*v.y + z*v.z; }
Vector3 cross(Vector3& v) { return Vector3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); }
// scalar product
friend Vector3 operator*(float s, Vector3 v) { return Vector3(s*v.x, s*v.y, s*v.z); }
Vector3& normalize() {
float invLength = 1.0f / sqrtf(x*x + y*y + z*z);
x *= invLength;
y *= invLength;
z *= invLength;
return *this;
}
}
...
// define the rotation vector r and angle
Vector3 r = Vector3(1, 1, 1).normalize(); // make unit length
float a = 30 / 180 * PI; // rotation angle as radian
// define a vector p to rotate
Vector3 p = Vector3(1, 2, 3);
// compute the rotated vector q using Rodrigues' formula
Vector3 q = (1 - cos(a)) * p.dot(r) * r + cos(a) * p + sin(a) * r.cross(p);
```