Propositions & Notation
We work in \(\mathbb{R}^3\) with the standard dot product \(\cdot\) and cross product \(\times\). Bold lowercase letters denote 3D vectors. A quaternion in vector form is written as
\[\mathbf{q} = (w,\ \mathbf{v})\]
The following identities and definitions will be used:
- Großmann Identity (vector triple product):
\[\mathbf{a}\times(\mathbf{b}\times\mathbf{c}) \;=\; (\mathbf{a}\cdot\mathbf{c})\,\mathbf{b} \;-\; (\mathbf{a}\cdot\mathbf{b})\,\mathbf{c}\]
- 3D vector cross-product is anti-commutative:
\[\mathbf{a}\times\mathbf{b} \;=\; -(\mathbf{b}\times\mathbf{a})\]
- Orthogonality to the normal (scalar triple product with a repeated vector is zero):
\[\mathbf{a}\cdot(\mathbf{b}\times\mathbf{a}) \;=\; 0\]
- Quaternion multiplication in vector form:
\[ \mathbf{q}_1\mathbf{q}_2 \;=\; \bigl(w_1w_2 - \mathbf{v}_1\cdot\mathbf{v}_2,\; w_1\mathbf{v}_2 + w_2\mathbf{v}_1 + \mathbf{v}_1\times\mathbf{v}_2 \bigr) \]
- Conjugate and norm:
\[\overline{\mathbf{q}}=(w,-\mathbf{v}),\qquad |\mathbf{q}|^2=w^2+\mathbf{v}\cdot\mathbf{v}\]
- For a rotation we use a unit quaternion (versor) \(|\mathbf{q}|=1\), hence
\[w^2 \;=\; 1 - \mathbf{v}\cdot\mathbf{v}\]
Quaternion Rotation: Classic Formulation
To rotate a vector \(\mathbf{u}\in\mathbb{R}^3\) by a unit quaternion \(\mathbf{q}=(w,\mathbf{v})\), embed \(\mathbf{u}\) as the pure quaternion
\[\mathbf{p}=(0,\mathbf{u})\]
and compute
\[\mathbf{p}'=(0,\mathbf{u}')=\mathbf{q}\,\mathbf{p}\,\overline{\mathbf{q}}\]
While correct, evaluating the full product directly can be more expensive than necessary. Below we factor the expression to obtain an equivalent but more efficient formula.
Efficient Vector Rotation
Compute the right product first:
\[\begin{array}{rl} \mathbf{p}\overline{\mathbf{q}} &= (0,\mathbf{u})(w, -\mathbf{v})\\ &= (\mathbf{u}\cdot\mathbf{v}, w\mathbf{u} - \mathbf{u}\times\mathbf{v}) \end{array}\]
Left-multiply by \(\mathbf{q}\):
\[\begin{array}{rl} \mathbf{q}\mathbf{p}\overline{\mathbf{q}} &= (w, \mathbf{v})(\mathbf{u}\cdot\mathbf{v}, w\mathbf{u} - \mathbf{u}\times\mathbf{v})\\ &= (w(\mathbf{u}\cdot\mathbf{v}) - \mathbf{v}\cdot(w\mathbf{u} - \mathbf{u}\times\mathbf{v}), w(w\mathbf{u} - \mathbf{u}\times\mathbf{v}) + (\mathbf{u}\cdot\mathbf{v})\mathbf{v}+ \mathbf{v}\times(w\mathbf{u} - \mathbf{u}\times\mathbf{v}) )\\ &= (0, w^2\mathbf{u} + w\mathbf{v}\times\mathbf{u}+(\mathbf{u}\cdot\mathbf{v})\mathbf{v} + w\mathbf{v}\times\mathbf{u} + \mathbf{v}\times(\mathbf{v}\times\mathbf{u}))\\ &= (0, \mathbf{u} - (\mathbf{v}\cdot\mathbf{v})\mathbf{u}+ 2w\mathbf{v}\times\mathbf{u}+(\mathbf{u}\cdot\mathbf{v})\mathbf{v}+(\mathbf{v}\cdot\mathbf{u})\mathbf{v} - (\mathbf{v}\cdot\mathbf{v})\mathbf{u}\\ &= (0, \mathbf{u} + 2w\mathbf{v}\times\mathbf{u}+2(\mathbf{u}\cdot\mathbf{v})\mathbf{v}-2(\mathbf{v}\cdot\mathbf{v})\mathbf{u})\\ &= (0, \mathbf{u} + 2w\mathbf{v}\times\mathbf{u} + 2\mathbf{v}\times(\mathbf{v}\times\mathbf{u}))\\ &= (0, \mathbf{u} + 2\mathbf{v}\times (w\mathbf{u} + \mathbf{v}\times\mathbf{u}))\\ \end{array}\]
Which is a pretty nice finding! We can then compute \(\mathbf{u}'\) from \(\mathbf{u}\) by
\[R(\mathbf{u}) = \mathbf{u} + 2\mathbf{v}\times (w\mathbf{u} + \mathbf{v}\times\mathbf{u})\]
Which can also be written as
\[\begin{array}{rl} \mathbf{t}&=2\mathbf{v}\times\mathbf{u}\\ R(\mathbf{u}) &= \mathbf{u} + w\mathbf{t} + \mathbf{v}\times\mathbf{t} \end{array}\]
Remarks
- Input requirements. \(\mathbf{q}=(w,\mathbf{v})\) must be unit-length. If you construct \(\mathbf{q}\) from an axis–angle pair \((\hat{\mathbf{n}},\theta)\), use \(w=\cos(\tfrac{\theta}{2}),\ \mathbf{v}=\hat{\mathbf{n}}\sin(\tfrac{\theta}{2})\), which automatically yields \(|\mathbf{q}|=1\).
- Numerical stability. When \(\theta\) is very small, the formula remains stable; however, if you normalize \(\mathbf{q}\) from arbitrary data, normalize once before applying the rotation.
- Cost profile. The two-step form \(\mathbf{t}=2\,\mathbf{v}\times\mathbf{u}\), \(R(\mathbf{u})=\mathbf{u}+w\mathbf{t}+\mathbf{v}\times\mathbf{t}\) minimizes dot products and avoids a full quaternion–quaternion product, which is often faster in tight loops.