The weblog of Nicholas Chapman Fast rotation of a vector by a quaternionPosted 18 Jul 2018There is a fast way to compute the rotation of a vector by a quaternion, apparently noted first by Fabian Giesen. See this blog post. Since the original description/derivation seems to have been lost in the sands of time (pages 404), I thought I would re-derive it. In the derivation below, I will follow the notation of Ken Shoemake in Quaternions. Suppose we have a unit quaternion $$q = [\mathbf{v}, w]$$ The rotation of a vector, $$\mathbf{p}$$ by the quaternion $$q$$ is given by $$p' = q p q^*$$ where p is treated as the quaternion $$[(p_x, p_y, p_z), 0] = [\mathbf{p}, 0]$$ e.g. as a quaternion with the w coord zero. Expanding out $$q p q^*$$ using the definition of quaternion multiplication gives $$p' = q p q^* = ([\mathbf{v}, w][\mathbf{p}, 0])[-\mathbf{v}, w]$$ $$p' = ([\mathbf{v}0 + \mathbf{p}w + \mathbf{v} \times \mathbf{p}, w 0 - \mathbf{v}.\mathbf{p}])[-\mathbf{v}, w]$$ $$p' = ([\mathbf{p}w + \mathbf{v} \times \mathbf{p}, - \mathbf{v}.\mathbf{p}]) [-\mathbf{v}, w]$$ $$p' = [(\mathbf{p}w + \mathbf{v} \times \mathbf{p})w + (-\mathbf{v})(- \mathbf{v}.\mathbf{p}) + (\mathbf{p}w + \mathbf{v} \times \mathbf{p}) \times -\mathbf{v}), (- \mathbf{v}.\mathbf{p})w - (\mathbf{p}w + \mathbf{v} \times \mathbf{p}).(-\mathbf{v})]$$ Lets treat the w component of this first: $$p'_w = - \mathbf{v}.\mathbf{p}w - (\mathbf{p}w).(-\mathbf{v}) + (\mathbf{v} \times \mathbf{p}).(-\mathbf{v})$$ $$p'_w = - w\mathbf{v}.\mathbf{p} + w\mathbf{p}.\mathbf{v} - (\mathbf{v} \times \mathbf{p}).\mathbf{v}$$ We know $$\mathbf{v} \times \mathbf{p}$$ is orthogonal to $$\mathbf{v}$$, so $$(\mathbf{v} \times \mathbf{p}).\mathbf{v} = 0$$ Therefore $$p'_w = 0$$ Giving a resulting vector with zero w coordinate like we expected. Continuing with the vector part of $$p'$$: $$\mathbf{p'} = (\mathbf{p}w + \mathbf{v} \times \mathbf{p})w + (-\mathbf{v})(- \mathbf{v}.\mathbf{p}) + (\mathbf{p}w \times -\mathbf{v}) + ((\mathbf{v} \times \mathbf{p}) \times -\mathbf{v})$$ $$\mathbf{p'} = (\mathbf{p}w + \mathbf{v} \times \mathbf{p})w + \mathbf{v}( \mathbf{v}.\mathbf{p}) + (\mathbf{v} \times \mathbf{p})w + (\mathbf{v} \times (\mathbf{v} \times \mathbf{p}))$$ $$\mathbf{p'} = \mathbf{p}w^2 + (\mathbf{v} \times \mathbf{p})w + \mathbf{v}( \mathbf{v}.\mathbf{p}) + (\mathbf{v} \times \mathbf{p})w + (\mathbf{v} \times (\mathbf{v} \times \mathbf{p}))$$ $$\mathbf{p'} = \mathbf{p}w^2 + 2(\mathbf{v} \times \mathbf{p})w + \mathbf{v}( \mathbf{v}.\mathbf{p}) + (\mathbf{v} \times (\mathbf{v} \times \mathbf{p}))$$ Remember that for a unit quaternion, $$\mathbf{v}$$ is a (non-unit) vector around which the quaternion gives a rotation, in particular $$||\mathbf{v}|| = \sin(\Omega)$$ Where $$\Omega$$ is half the angle of the quaternion rotation, e.g. $$||\mathbf{v}|| = \sin(\Omega) = \sin(\theta/2)$$ So now we decompose the vector $$\mathbf{p}$$ into the vector projection and vector rejection (see wikipedia) components with respect to the unit vector $$\hat{\mathbf{v}} = \mathbf{v}/||\mathbf{v}||$$, giving $$\mathbf{p} = \hat{\mathbf{v}}(\hat{\mathbf{v}}.\mathbf{p}) + (-\hat{\mathbf{v}} \times (\hat{\mathbf{v}} \times \mathbf{p}))$$ Substituting in $$\hat{\mathbf{v}} = \mathbf{v}/||\mathbf{v}|| = { \mathbf{v} \over \sin(\theta/2) }$$ gives $$\mathbf{p} = ({ \mathbf{v} \over \sin(\theta/2) })(({ \mathbf{v} \over \sin(\theta/2) }).\mathbf{p}) - (({ \mathbf{v} \over \sin(\theta/2) }) \times (({ \mathbf{v} \over \sin(\theta/2) }) \times \mathbf{p}))$$ $$\mathbf{p} = { \mathbf{v}(\mathbf{v}.\mathbf{p}) \over \sin^2(\theta/2) } - { \mathbf{v} \times (\mathbf{v} \times \mathbf{p}) \over \sin^2(\theta/2) }$$ $$\mathbf{p} = { \mathbf{v}(\mathbf{v}.\mathbf{p}) - \mathbf{v} \times (\mathbf{v} \times \mathbf{p}) \over \sin^2(\theta/2) }$$ or $$\mathbf{v}(\mathbf{v}.\mathbf{p}) = \sin^2(\theta/2)\mathbf{p} + \mathbf{v} \times (\mathbf{v} \times \mathbf{p})$$ Going back to our expression for $$\mathbf{p'}$$: $$\mathbf{p'} = \mathbf{p}w^2 + 2(\mathbf{v} \times \mathbf{p})w + \mathbf{v}( \mathbf{v}.\mathbf{p}) + (\mathbf{v} \times (\mathbf{v} \times \mathbf{p}))$$ Substituting in our expression for $$\mathbf{v}(\mathbf{v}.\mathbf{p})$$ gives $$\mathbf{p'} = \mathbf{p}w^2 + 2(\mathbf{v} \times \mathbf{p})w + (\sin^2(\theta/2)\mathbf{p} + \mathbf{v} \times (\mathbf{v} \times \mathbf{p})) + (\mathbf{v} \times (\mathbf{v} \times \mathbf{p}))$$ $$\mathbf{p'} = \mathbf{p}(w^2 + \sin^2(\theta/2)) + 2(\mathbf{v} \times \mathbf{p})w + 2(\mathbf{v} \times (\mathbf{v} \times \mathbf{p}))$$ But for unit quaternions, the relationship between the w component and the rotation angle $$\theta$$ is given by $$w = \cos(\Omega) = \cos(\theta/2)$$ so $$\mathbf{p'} = \mathbf{p}(\cos^2(\theta/2) + \sin^2(\theta/2)) + (\mathbf{v} \times \mathbf{p})w + \mathbf{v} \times (\mathbf{v} \times \mathbf{p})$$ And of course $$\cos^2(\theta/2) + \sin^2(\theta/2) = 1$$ so $$\mathbf{p'} = \mathbf{p} + 2w(\mathbf{v} \times \mathbf{p}) + 2(\mathbf{v} \times (\mathbf{v} \times \mathbf{p}))$$ which is the simple, fast expression that we are after. You can also derive this from Rodrigues' rotation formula with some funky trig identities. Do you have a comment or feedback about this blog post? Please email me.< Back All content by Nicholas Chapman. Static Pages on this website Our software Indigo Renderer Chaotica Substrata Winter