Your browser does not support the HTML5 canvas tag.

Drag inside the circle (top-left) to rotate the object with your mouse — an arcball, exactly how quaternions are used in practice. The amber line is the rotation axis (arrow = right-hand-rule direction); the purple arc sweeps the angle θ from the faded rest pose to the current orientation.

Controls

1, 0, 0, 0 1.000 - 0.0° 0.00 0.0 °/s 0.0 °/s

Representing rotations with quaternions

As noted in the Rigid Body Collision example, a single angle $\alpha$ is enough to describe a 2D rotation, but 3D rotations need more: a $3\times 3$ rotation matrix (9 numbers, 6 of them redundant), Euler angles (only 3 numbers, but they can hit a gimbal lock singularity and their composition order is confusing), or a quaternion — just 4 numbers, no singularities, and, as this example shows, unusually simple to compose and interpolate.

Definition

A quaternion is $q = w + x\mathbf i + y\mathbf j + z\mathbf k$, with $\mathbf i^2=\mathbf j^2=\mathbf k^2=\mathbf{ijk}=-1$. A rotation by angle $\theta$ around a unit axis $\hat{\mathbf n}$ is encoded as $$q = \left(\cos\frac{\theta}{2},\ \sin\frac{\theta}{2}\,\hat{\mathbf n}\right), \qquad \Vert q \Vert = 1.$$ Only unit quaternions represent rotations, which is exactly why $\Vert q\Vert$ is tracked live in the panel — it should stay at $1$ at all times (up to floating-point round-off) while you drag the object.

Seeing $\hat{\mathbf n}$ and $\theta$ directly

The "Axis" and "Angle" statistics are exactly $\hat{\mathbf n}$ and $\theta$ recovered from the current $q$ (inverting the definition above: $\theta = 2\arccos w$, $\hat{\mathbf n} = (x,y,z)/\sin(\theta/2)$), and the "Show axis & angle" overlay draws them as actual geometry rather than just numbers:

One subtlety this view also resolves: since $q$ and $-q$ are the same rotation (see below), a raw $\theta=2\arccos w$ could come out anywhere up to $360°$ depending on an arbitrary sign. The angle shown here is always canonicalized to the shorter one, in $[0°,180°]$, by first flipping to whichever of $q,-q$ has $w\ge 0$ — so the arc you see is always the minimal sweep, never "the long way around".

Rotating a vector

Treating a vector $\mathbf v$ as a "pure" quaternion $(0,\mathbf v)$, a unit quaternion $q$ rotates it via the sandwich product $$(0,\mathbf v') = q\,(0,\mathbf v)\,q^{-1}, \qquad q^{-1}=q^{*}=(w,-x,-y,-z) \text{ for a unit } q,$$ using the Hamilton product for quaternion multiplication. This is exactly how every corner of the wireframe object is transformed every frame in this example, and also how the mouse drag itself is turned into a rotation: dragging maps two points on the surface of the drawn circle (an arcball, a virtual trackball) to two 3D points on a unit hemisphere, and the quaternion that rotates one onto the other is applied on top of whatever orientation the object already had.

Two quaternions for every rotation

Because $\theta$ and $\theta+2\pi$ (equivalently, negating both $\cos(\theta/2)$ and the axis term) describe the same physical rotation, $q$ and $-q$ always represent an identical orientation — this is called the double cover of $SO(3)$ by unit quaternions. Press "Negate q" to see this directly: every component of $q$ flips sign, yet the object does not move at all.

Composing rotations

Applying rotation $q_1$ and then rotation $q_2$ corresponds to the single quaternion $q_2 q_1$ (Hamilton product, $q_1$ on the right since it acts on the vector first) — and just like matrix multiplication, this product is generally not commutative. "Apply $R_x(90°)$ then $R_y(90°)$" computes $R_y R_x$, while "Apply $R_y(90°)$ then $R_x(90°)$" computes $R_x R_y$; press both buttons in turn and compare the two resulting orientations — they are different, even though the same two rotations were used both times.

Interpolating rotations: SLERP vs. naive LERP

Drag the object into two different orientations, pressing "Set keyframe A" and "Set keyframe B" to remember them, then "Play interpolation" to animate between them two different ways at once:

The "Angular speed" statistics measure exactly this, frame to frame, for both mini-views at the bottom of the canvas: SLERP's stays flat throughout the animation, while naive LERP's rises and falls — more noticeably the farther apart $q_A$ and $q_B$ are.

From quaternion to matrix

Whenever a quaternion needs to be handed to code that expects a rotation matrix (a renderer, say), it converts directly, with no trigonometry required: $$R(q) = \begin{pmatrix} 1-2(y^2+z^2) & 2(xy-zw) & 2(xz+yw) \\ 2(xy+zw) & 1-2(x^2+z^2) & 2(yz-xw) \\ 2(xz-yw) & 2(yz+xw) & 1-2(x^2+y^2) \end{pmatrix}.$$

References