Motivation: 三维空间的变化是许多涉及三维展示引擎的核心组件之一. 三维的平移旋转缩放是最常见的三维变化. 其中旋转是最复杂的变换. 利用普通的欧拉角等进行旋转非常直观, 但是会存在死锁等潜在问题. 而四元数可以非常好地应用于三维旋转中.

复数

介绍四元数之前先了解复数 Complex Number. 负数\(z\)的定义是:
$$z = a+ b \textbf{i}, 其中\textbf{i}^2 = -1$$
我们可以将其看做一个基为\((1, \textbf{i})\)的线性组合, 其对应的坐标是\((a, b)\)
复数运算满足分配率. 加入\(z_1 = a+ b \textbf{i}\), \(z_2 = c+ d \textbf{i}\), 那么
$$z_1z_2 = (a+ b \textbf{i})(c+ d \textbf{i}) = ac + ad\textbf{i} + bc\textbf{i} - bd = (ac-bd) + (ad+bc)\textbf{i} $$
如果我们表达成矩阵形式, 则是:
$$\begin{bmatrix}
a & -b \\
b & a \\
\end{bmatrix}
\begin{bmatrix}
c \\
d
\end{bmatrix} \tag{1} $$

或者:
$$\begin{bmatrix}
c & -d \\
d & c \\
\end{bmatrix}
\begin{bmatrix}
a \\
b
\end{bmatrix} \tag{2} $$

我们随便看一个, 例如看第一个, 右边的向量就是\(z_2\)的向量, 而左边的矩阵可以看做某种变换(矩阵形式), 也就是说, 两个复数相乘相当于对其中一个复数进行了某种变换. 当我们将两个复数向量都变成矩阵形式时, 可得:
$$z_1z_2=
\begin{bmatrix}
a & -b \\
b & a \\
\end{bmatrix}
\begin{bmatrix}
c & -d \\
d & c \\
\end{bmatrix} =
\begin{bmatrix}
ac-bd & -(ad+bc) \\
ad+bc & ac-bd \\
\end{bmatrix}$$
很容易就可以计算得到.\(z_1z_2=z_2z_1\)

复数相乘和2D旋转

我们已经知道复数相乘代表一个矩阵形式作出的变换
$$\begin{bmatrix}
a & -b \\
b & a \\
\end{bmatrix} $$
, 那么这个矩阵变换代表着什么呢? 我们将其作用于模长, 即可很容易看出来:

"采样重建"

Fig.1: 复数的矩阵形式的意义

没错, 这实际上相当于:
$$\begin{bmatrix}
a & -b \\
b & a \\
\end{bmatrix} = ||z||
\begin{bmatrix}
cos\theta & -sin\theta \\
sin\theta & cos\theta \\
\end{bmatrix}$$
所以, 复数相乘实际上就是旋转与缩放变换的组合. 缩放因子是\(|z|\), 旋转角度是\(\theta = atan2(b, a)\).
所以2D旋转公式是:
$$\vec{v}’ = \begin{bmatrix}
cos\theta & -sin\theta \\
sin\theta & cos\theta \\
\end{bmatrix} \vec{v} = (cos\theta + \textbf{i}sin\theta) \vec{v}$$

欧拉公式和极坐标

接下来就是伟大的欧拉公式了!
$$(cos\theta + \textbf{i}sin\theta) = e^{\textbf{i}\theta}$$

三维空间旋转

我们假设旋转轴\(\vec{u}\)是单位向量, 某个向量\(\vec{v}\)绕着其旋转\(\theta\)角度变换到\(\vec{v}\), 如何变换呢?
我们将\(\vec{v}\)分解成平行和垂直于旋转轴的两个向量\(\vec{v}_{\parallel}\) 和 \(\vec{v} _{\perp}\). 由于旋转轴是单位向量, 可以得到
$$\vec{v}_\parallel = (\vec{u}\cdot\vec{v})\vec{u}$$
可以很清楚看到平行方面投影的向量不变, 唯一改变的是垂直方向的.

"采样重建"

Fig.2: 平行投影和垂直投影

我们很容易就可以得到: $$ \vec{w} = \vec{u} \times \vec{v}_\perp$$ 将垂直方向投影表达成新的投影组合: $$\vec{v}'_\perp = cos\theta \cdot {\vec{v}_\perp} + sin\theta \cdot \vec{w} $$

我们将上面组合起来即可得到最终\(\vec{v}\)的旋转\(\vec{v}’\)
$$\vec{v}’ = \vec{v}’_\parallel + \vec{v}’_\perp = \vec{v}_\parallel + cos\theta \cdot {\vec{v}_\perp} + sin\theta \cdot \vec{w}
= \vec{v}_\parallel + cos\theta \cdot {\vec{v}_\perp} + sin\theta \cdot (\vec{u} \times \vec{v}_\perp) \tag{1} $$
可以得到
$$(\vec{u} \times \vec{v}_\perp) =\vec{u} \times (\vec{v} - \vec{v}_\parallel) = \vec{u} \times \vec{v} $$
$$\vec{v}_\perp = \vec{v} - \vec{v}_\parallel = \vec{v} - (\vec{u}\cdot\vec{v})\vec{u}$$
将相关值带入(1)公式, 最终我们可以得到:
$$\vec{v}’ = (\vec{u}\cdot\vec{v})\vec{u} + cos\theta \cdot (\vec{v} - (\vec{u}\cdot\vec{v})\vec{u}) + sin\theta \cdot (\vec{u} \times \vec{v}) \tag{2}$$

四元数

上面的式子看起来很复杂, 其实不然. 四元数的定义和复数非常接近, 唯一区别是四元数一共有三个虚部, 而复数只有一个. 所有的四元数\(q \in \mathbb{H}\)都可以写成下面格式:
$$q = a +b\textbf{i} + c\textbf{j} + d\textbf{k}, 其中a, b, c, d \in \mathbb{R}\ 并且\textbf{i}^2 = \textbf{j}^2 = \textbf{k}^2 = \textbf{i}\textbf{j}\textbf{k} = -1$$
四元数还有一种将实部和虚部分开的表示方法, 用三维向量表示虚部
$$q = [s, \vec{v}] , 其中\vec{v} =
\begin{bmatrix}
x \\
y \\
z
\end{bmatrix}, 并且s, x, y, z \in \mathbb{R}$$

四元数和复数不同的一点是, 其不满足交换律, 即\(q_1q_2 \ne q_2q_1\), 前者称为\({“q_2左乘以q_1”}\). 假设\(q_1 = a +b\textbf{i} + c\textbf{j} + d\textbf{k}\), \(q_2 = e +f\textbf{i} + g\textbf{j} + h\textbf{k}\), 则他们的乘积化简可得:
$$q_1q_2 = (ae-bf-cg-dh) + (be+af-dg+ch)\textbf{i} + (ce+df+ag-bh)\textbf{j} + (de-cf+bg+ah)\textbf{k}$$

"采样重建"

Fig.3: 不满足交换律

我们将其表示成矩阵形式, 就会发现其实四元数相乘也是一个线性组合:

$$q_1q_2 =
\begin{bmatrix}
a & -b & -c & -d \\
b & a & -d & c \\
c & d & a & -b \\
d & -c & b & a
\end{bmatrix}
\begin{bmatrix}
e\\
f \\
g \\
h
\end{bmatrix} $$
类似的过程,右乘\(q_1\)会得到:

$$q_2q_1 =
\begin{bmatrix}
a & -b & -c & -d \\
b & a & d & -c \\
c & -d & a & b \\
d & c & -b & a
\end{bmatrix}
\begin{bmatrix}
e\\
f \\
g \\
h
\end{bmatrix} $$
现在我们令\(\vec{v} = \begin{bmatrix}
b \\
c \\
d
\end{bmatrix}\), 令\(\vec{u} = \begin{bmatrix}
f \\
g \\
h
\end{bmatrix}\), 则最终我们可以用二者的点乘和叉乘来表示四元数的乘积:
$$q_1q_2 = [ae - \vec{v}\vec{u}, a\vec{u}+e\vec{v} + \vec{v} \times \vec{u}$$
这个结果也叫作\(\textbf{GraBmann积}\)
下面介绍纯四元数,即实部为0.纯四元数的虚部可以和三维向量一一对应,并且假设\(\textbf{v} = [0, \vec{v}]\),\(\textbf{u} = [0, \vec{u}]\),那么
$$\textbf{v}\textbf{v} = [ -\vec{v}\cdot \vec{u}, \vec{v} \times \vec{u} ]$$

四元数和3D旋转

我们知道了3D旋转的表达,也知道了纯四元数可以和三维相对对应,所以可以用四元数来表达3D旋转.

$$ \vec{v} = [0, \textbf{v}], \vec{v}’ = [0, \textbf{v}’] \\
\vec{v}_{\perp} = [0, \textbf {v} _{\perp}], \vec{v}’ _{\perp} = [0, \textbf {v}’ _{\perp}]
$$

$$ \vec{v}_{\parallel} = [0, \textbf {v} _{\parallel}], \vec{v}’ _{\parallel} = [0, \textbf {v}’ _{\parallel}] \\
\vec{u} = [0, \textbf{u}]
$$