- Game Physics Cookbook
- Gabor Szauer
- 591字
- 2021-04-02 20:27:32
Axis angle rotation
As discussed earlier, we can combine yaw, pitch, and roll using matrix multiplication to create a complete rotation matrix. Creating a rotation matrix by performing each rotation sequentially introduces the possibility of a Gimbal Lock.
We can avoid that Gimbal Lock if we change how a rotation is represented. Instead of using three Euler angles to represent a rotation, we can use an arbitrary axis, and some angle to rotate around that axis.
Given axis , we can define a matrix that will rotate some angle
around that axis:

Where and XYZ = Arbitrary Axis (unit length). We will explore how this matrix is derived in the How it works… section.
Getting ready
Like before, we are going to implement two versions of this function. One version will return a 4 X 4 matrix; the other will return a 3 X 3 matrix. To avoid having to constantly calculate sin
and cos
, we're going to create local variables for c
, s
, and t
. The axis being passed in does not have to be normalized. Because of this we have to check the length of the vector, and possibly normalize it.
How to do it…
Follow these steps to create a rotation matrix around an arbitrary axis:
- Add the declaration of the
AxisAngle
functions tomatrices.h
:mat4 AxisAngle(const vec3& axis, float angle); mat3 AxisAngle3x3(const vec3& axis, float angle);
- Implement the
AxisAngle
function inmatrices.cpp
:mat4 AxisAngle(const vec3& axis, float angle) { angle = DEG2RAD(angle); float c = cosf(angle); float s = sinf(angle); float t = 1.0f - cosf(angle); float x = axis.x; float y = axis.y; float z = axis.z; if (!CMP(MagnitudeSq(axis), 1.0f)) { floatinv_len = 1.0f / Magnitude(axis); x *= inv_len; // Normalize x y *= inv_len; // Normalize y z *= inv_len; // Normalize z } // x, y, and z are a normalized vector return mat4( t*(x*x) + c, t*x*y + s*z, t*x*z - s*y, 0.0f, t*x*y - s*z, t*(y*y) + c, t*y*z + s*x, 0.0f, t*x*z + s*y, t*y*z - s*x, t*(z*z) + c, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ); }
- Implement the
AxisAngle3x3
function inmatrices.cpp
:mat3 AxisAngle3x3(const vec3& axis, float angle) { angle = DEG2RAD(angle); float c = cosf(angle); float s = sinf(angle); float t = 1.0f - cosf(angle); float x = axis.x; float y = axis.y; float z =axis.z; if (!CMP(MagnitudeSq(axis), 1.0f)) { float inv_len = 1.0f / Magnitude(axis); x *= inv_len; y *= inv_len; z *= inv_len; } return mat3( t * (x * x) + c,t * x * y + s * z,t * x * z - s * y, t * x * y - s * z,t * (y * y) + c,t * y * z + s * x, t * x * z + s * y,t * y * z - s * x,t * (z * z) + c ); }
How it works…
Instead of rotating one axis at a time, then combining the rotation, axis angle rotation rotates by some angle around an arbitrary axis. This final rotation matrix is actually the sum of three other matrices:
- The identity matrix
- Multiplied by c, the cosine of theta
- A matrix that is symmetrical about the main diagonal
- Multiplied by t, 1 - the cosine of theta
- A matrix that is anti-symmetrical about the main diagonal
- Multiplied by s, the sine of theta
These matrices combine to form the final Axis-Angle rotation matrix:


The concept of symmetrical and anti-symmetrical matrices is outside the scope of this book. I recommend the following resources on both topics:
- Java多線程編程實戰指南:設計模式篇(第2版)
- 從零開始:數字圖像處理的編程基礎與應用
- Unity Virtual Reality Projects
- TypeScript項目開發實戰
- HDInsight Essentials(Second Edition)
- JavaScript:Moving to ES2015
- 數據結構案例教程(C/C++版)
- Julia高性能科學計算(第2版)
- Java語言程序設計教程
- Microsoft 365 Certified Fundamentals MS-900 Exam Guide
- PHP與MySQL權威指南
- Java 從入門到項目實踐(超值版)
- 跟戴銘學iOS編程:理順核心知識點
- Learning ECMAScript 6
- Splunk Essentials