OpenGL Rotation About Arbitrary Axis
Related Topics: OpenGL Matrix, Quaternion to Matrix, Angles To Axes, Lookat To Axes
Download: rotate.zip
Derive Rodrigues' Formula
The 4x4 transformation matrix for rotating about an arbitrary axis in OpenGL is defined as;
This page explains how to derive this rotation matrix from Rodrigues' rotation formula. Suppose a 3D point P is rotating to Q by an angle along a unit vector . The vector form of P is broken down the sum of and , and Q is the sum of and respectively;
,
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 = (px, py, pz) 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;
Example: Rodrigues' Rotation Formula
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);