Orientation — describes a state. Where is this object pointed right now? (Like a snapshot)
Angular Displacement — describes the difference between two orientations. How much and in what direction did it rotate?
This distinction matters when interpolating rotations. Interpolating between two orientations (e.g., for animation blending) is different from integrating an angular velocity (physics simulation). The math for each path has different requirements.
An orientation can be described as a rotation from some known reference orientation (usually the identity / "upright" space). The amount of that rotation is the angular displacement.
For local/object coordinate spaces, the basis vectors will always be [1,0,0], [0,1,0], [0,0,1] (upright space). An orientation describes how these axes relate to that reference.
2
Matrix Form
A 3×3 rotation matrix stores the basis vectors of the object's local space expressed in the parent coordinate space. Each row is a basis vector.
Direction Cosines Matrix
A special way to build the matrix: use the cosines of the angles between each pair of basis vectors. This is equivalent to the dot product between unit vectors:
┌ p·p' q·p' r·p' ┐
M = │ p·q' q·q' r·q' │
└ p·r' q·r' r·r' ┘
where p,q,r are basis vectors of the initial CS
and p',q',r' are basis vectors of the final CS
When the first coordinate space uses unit basis vectors, the matrix simplifies to just the dot products between the unit axes — which are exactly the direction cosines.
Advantages of Matrix Form
Rotating a vector is immediate (one matrix multiply)
Used directly by graphics APIs
Can concatenate multiple angular displacements
Matrix inversion (= transpose for ortho) is cheap
Disadvantages of Matrix Form
9 numbers to store (vs 3 for Euler, 4 for quaternion)
Difficult to read/author by hand
Can accumulate floating-point error → "matrix drift"
Must periodically re-orthogonalize
3
Euler Angles
Describes orientation as three successive rotations about three mutually perpendicular axes. Any three axes and any order will work — different books use different conventions. This text uses heading, pitch, bank (also called yaw, pitch, roll) in a left-handed system:
Start in identity orientation (object space = upright space)
Heading (H / yaw) — rotate about the object's Y axis. Clockwise is positive.
Pitch (P) — rotate about the object's X axis. Downward is positive.
Bank (B / roll) — rotate about the object's Z axis. Counter-clockwise is positive.
Fixed Axis vs Object Axis
Using a fixed axis means H, P, B are always measured from the upright/world axes (extrinsic rotations). The key insight:
Applying (H, P, B) with object axes in order == Applying (B, P, H) with fixed axes
Advantages
Easiest for humans to understand and author
Only 3 numbers — minimal memory
Any three numbers form a valid orientation
Handles data loss well (numbers are just angles)
Disadvantages
Representation is not unique (aliasing)
Susceptible to gimbal lock
Interpolation is problematic
Composing rotations is more complex
4
Gimbal Lock & Canonical Euler Angles
Canonical Euler Angle Set
-180° < h ≤ 180°
-90° ≤ p ≤ 90°
-180° < b ≤ 180°
Special case: p = ±90° → b = 0 (resolves aliasing at the poles)
Gimbal Lock
Gimbal lock occurs when p = ±90° (pitch straight up or straight down). At this angle, the heading and bank rotations become aligned — they both rotate about the same world-space axis, losing a degree of freedom. The "outer ring" and "inner ring" of the gimbal physically collapse onto the same axis.
Gimbal lock is a fundamental limitation of Euler angles — it's not a bug but a mathematical consequence of representing 3D orientation with three sequential single-axis rotations. Setting b = 0 when p = ±90° is a convention choice to avoid non-unique representations, but the loss of the third degree of freedom at those orientations is unavoidable with Euler angles alone.
Interpolation Problems
Even with canonical Euler angles, simple linear interpolation (lerp) can produce bad results:
Δθ = θ₁ - θ₀
θt = θ₀ + t·Δθ
The issue: interpolating from 170° to -170° would traverse 340° instead of the intended 20°. The fix is to wrap the delta into [−180°, 180°] using:
wrapPi(x) = x - 360° · floor((x + 180°) / 360°)
However, even with this fix, lerp can still suffer from gimbal lock. This is a fundamental problem when specifying orientation with only three values.
5
Axis-Angle & Exponential Map
Euler's Rotation Theorem
Any 3D angular displacement can be accomplished via a single rotation about a carefully chosen axis. This is the foundation of the axis-angle representation.
Axis-Angle
Axis-Angle: { n̂, θ }
n̂ = unit vector in the direction of the rotation axis (passes through origin)
θ = the rotation angle
Since n̂ is a unit vector, you can multiply it by θ without changing the encoded direction/angle data:
e = θ · n̂
Exponential Map
The exponential map encodes the axis-angle as a single 3D vector e whose direction matches n̂ and whose magnitude equals θ:
e = θ · n̂ (‖e‖ = θ)
Advantages
Better interpolation than Euler angles
Handles angular velocity naturally
Avoids gimbal lock at most orientations
Disadvantages
Still has aliasing (n̂, θ) == (-n̂, -θ)
Rotating a vector requires building a matrix first
Edge cases near 0° and 360°
6
Quaternions
Quaternions use four numbers to represent an orientation — a scalar w and a 3D vector component (x, y, z):
q = [ w (x y z) ]
= [ cos(θ/2) sin(θ/2)·n̂ ]
= [ cos(θ/2) sin(θ/2)·nx sin(θ/2)·ny sin(θ/2)·nz ]
The axis and angle are encoded into the four components by halving the angle. This half-angle encoding is what makes quaternions work mathematically.
What do the Numbers Mean?
Similar to axis-angle: n̂ is the unit axis of rotation and θ is the rotation amount. The difference is how they're encoded — both the angle and axis are "spread" across all four values through the half-angle trig functions.
Double Cover
Any orientation has exactly two quaternion representations: q and -q. They encode the same rotation (one goes "the short way around," the other "the long way"):
-q = [ -w (-x -y -z) ] describes the same orientation as q
This is called "double cover" — quaternions map the orientation sphere to itself twice. It's why quaternion interpolation must check which of the two aliases is closer before lerping, to avoid the 360° wrap-around problem.
Key Operations
Negation
-q = [-w (-x -y -z)] same angular displacement as q
q* = [w (-x -y -z)] conjugate (for unit quaternions, also the inverse)
q⁻¹ = q* / ‖q‖²
Advantages
Smooth interpolation (SLERP)
Only 4 numbers
Fast to concatenate and invert
No gimbal lock
Numerically stable
Disadvantages
Unintuitive to read or author directly
Double-cover aliasing
Rotating a vector still requires conversion or formula
7
Exercises
1. Euler → Matrix
Convert the orientation (h=90°, p=0°, b=0°) to the equivalent 3×3 rotation matrix. Which way does the object's forward vector point?
Heading 90° about Y (left-handed, clockwise from above). Ry(90°): forward was (0,0,1), after 90° CW it becomes (1,0,0). The object now faces the world +X axis.
2. Quaternion from Axis-Angle
Convert a 180° rotation about the Y axis to quaternion form.
w = cos(90°) = 0. x = sin(90°)·0 = 0. y = sin(90°)·1 = 1. z = 0.
q = [0, (0, 1, 0)]. Negation: -q = [0, (0, -1, 0)] — same rotation.
3. SLERP vs LERP
You need to smoothly interpolate a camera from orientation A to orientation B over 30 frames. Should you use LERP or SLERP on the quaternions? Why?
SLERP (spherical linear interpolation) — it interpolates at a constant angular velocity along the shortest arc on the 4D quaternion sphere. LERP produces non-constant angular speed (the camera accelerates/decelerates mid-path). For smooth camera animation, SLERP is correct. LERP + renormalize is an acceptable approximation when angles are small.
Interview Question
What is gimbal lock and how do quaternions avoid it?
Gimbal lock occurs in Euler angles when two rotation axes align (e.g., pitch = ±90°), collapsing three degrees of freedom to two. Quaternions avoid this because they represent rotation as a single 4D unit vector — there's no sequential axis dependency and no degenerate configuration where two axes collapse. Quaternion space is continuous and has no singularities (except the double-cover aliasing, which is a different issue).
Interview Question
When would you choose Euler angles over quaternions in a game engine?
Euler angles are preferred in editor UIs and animation tools where humans need to read and author values directly. Artists understand "rotate 45° in yaw" but not "quaternion [0.92, 0, 0.38, 0]." Euler angles are also good for displaying object rotation in inspector panels. Internally the engine converts to quaternions for interpolation, physics, and concatenation.
Interview Question
What does the W component of a quaternion represent?
W = cos(θ/2), where θ is the rotation angle. It encodes "how much of the rotation is the identity (no rotation)" — when W = 1, the quaternion is the identity (no rotation); when W = 0, it's a 180° rotation. Together with the XYZ vector components (which equal sin(θ/2)·n̂), W lets you recover both the rotation axis and angle: θ = 2·arccos(W), n̂ = xyz / sin(θ/2).