概述
三维变换矩阵在几何核心库、渲染引擎、游戏开发等多个方面都有广泛的应用。在实际应用中,我们有时候需要单独使用三维变化的平移、旋转或缩放解决业务问题。本文将详细讲解将三维变换矩阵拆分为平移、旋转、缩放的分解算法,同时也作为对前一篇文章的理解加强。
了解了原理,一定会发现这个看似麻烦的问题解决起来非常简单。作者的写作目标就是把复杂抽象的数学问题和实际工作相结合,通俗易懂的介绍给大家。
如果没有读过前一篇文章的建议先读一下,链接如下
本文以后用“上篇文章”代替该文章。
用平移、旋转、缩放表示原矩阵
假设我们要分解的三维变化矩阵如下
M = [ a 00 a 01 a 02 a 03 a 10 a 11 a 12 a 13 a 20 a 21 a 22 a 23 0 0 0 1 ] ( 公式 1 ) M=\begin{bmatrix} a_{00} & a_{01} & a_{02} & a_{03} \\ a_{10} & a_{11} & a_{12} & a_{13} \\ a_{20} & a_{21} & a_{22} & a_{23} \\ 0 & 0 & 0 & 1 \end{bmatrix} \space \space \space \space \space \space (公式1) M= a00a10a200a01a11a210a02a12a220a03a13a231 (公式1)
利用上篇文章介绍的公式
P ′ = ( P x ⋅ s x ⋅ e 0 , P y ⋅ s y ⋅ e 1 , P z ⋅ s z ⋅ e 2 ) + P T P^{'}=(P_x \cdot s_x \cdot e0,\space\space P_y \cdot s_y \cdot e1,\space\space P_z \cdot s_z\cdot e2) + P_T P′=(Px⋅sx⋅e0, Py⋅sy⋅e1, Pz⋅sz⋅e2)+PT
我们可以将M表示成如下形式
M = [ s x ⋅ e 0 s y ⋅ e 1 s z ⋅ e 2 P T 0 0 0 1 ] ( 公式 2 ) M=\begin{bmatrix} s_x \cdot e0 & s_y \cdot e1 & s_z \cdot e2 & P_T \\ 0 & 0 & 0 & 1 \end{bmatrix} \space \space \space \space \space \space (公式2) M=[sx⋅e00sy⋅e10sz⋅e20PT1] (公式2)
计算平移向量
平移向量是最好计算的,对比公式1和公式2可知,平移向量
P T = [ a 03 a 13 a 23 ] P_T = \begin{bmatrix} a_{03} \\ a_{13} \\ a_{23} \end{bmatrix} PT= a03a13a23
计算缩放向量的绝对值
根据上篇文章,我们知道旋转矩阵的e0、e1和e2是单位向量,基于这个特性,我们可以计算缩放系数的绝对值
∣ s x ∣ = ∣ s x ∣ ⋅ ∣ e 0 ∣ = ∣ s x ⋅ e 0 ∣ = a 00 2 + a 10 2 + a 20 2 ∣ s y ∣ = ∣ s y ∣ ⋅ ∣ e 1 ∣ = ∣ s y ⋅ e 1 ∣ = a 01 2 + a 11 2 + a 21 2 ∣ s z ∣ = ∣ s z ∣ ⋅ ∣ e 2 ∣ = ∣ s z ⋅ e 2 ∣ = a 02 2 + a 12 2 + a 22 2 |s_x| = |s_x|\cdot|e0|=|s_x \cdot e0| = \sqrt{a_{00}^2+a_{10}^2+a_{20}^2} \\[4px] |s_y| = |s_y|\cdot|e1|=|s_y \cdot e1| = \sqrt{a_{01}^2+a_{11}^2+a_{21}^2} \\[4px] |s_z| = |s_z|\cdot|e2|=|s_z \cdot e2| = \sqrt{a_{02}^2+a_{12}^2+a_{22}^2} ∣sx∣=∣sx∣⋅∣e0∣=∣sx⋅e0∣=a002+a102+a202∣sy∣=∣sy∣⋅∣e1∣=∣sy⋅e1∣=a012+a112+a212∣sz∣=∣sz∣⋅∣e2∣=∣sz⋅e2∣=a022+a122+a222
计算旋转矩阵和缩放系数的符号
理论上,这个问题存在多组解,例如做一个旋转,和镜像两次之后做旋转,能得到同样的变换结果。实际应用中,我们一般情况下只需找到一组结果即可(其他结果,可以参考同样的方法找到)。
我们先假设不存在镜像,也就是假设三个维度的缩放系数都为正,即
s x = a 00 2 + a 10 2 + a 20 2 s y = a 01 2 + a 11 2 + a 21 2 s z = a 02 2 + a 12 2 + a 22 2 s_x = \sqrt{a_{00}^2+a_{10}^2+a_{20}^2} \\[4px] s_y = \sqrt{a_{01}^2+a_{11}^2+a_{21}^2} \\[4px] s_z = \sqrt{a_{02}^2+a_{12}^2+a_{22}^2} sx=a002+a102+a202sy=a012+a112+a212sz=a022+a122+a222
那么
e 0 = [ a 00 s x a 10 s x a 20 s x ] e 1 = [ a 01 s y a 11 s y a 21 s y ] e 2 = [ a 02 s z a 12 s z a 22 s z ] e0=\begin{bmatrix} \dfrac{a_{00}}{s_x} \\[16px] \dfrac{a_{10}}{s_x} \\[16px] \dfrac{a_{20}}{s_x} \end{bmatrix} \\[16px] e1=\begin{bmatrix} \dfrac{a_{01}}{s_y} \\[16px] \dfrac{a_{11}}{s_y} \\[16px] \dfrac{a_{21}}{s_y} \end{bmatrix} \\[16px] e2=\begin{bmatrix} \dfrac{a_{02}}{s_z} \\[16px] \dfrac{a_{12}}{s_z} \\[16px] \dfrac{a_{22}}{s_z} \end{bmatrix} \\[16px] e0= sxa00sxa10sxa20 e1= sya01sya11sya21 e2= sza02sza12sza22
根据上篇文章的讲解,我们知道e0、e1和e2是正交坐标系的三个轴,根据坐标系轴的正交特性可知,如果
( e 0 × e 1 ) ⋅ e 2 < 0 (e0 × e1) \cdot e2 < 0 (e0×e1)⋅e2<0
说明有一个坐标轴需要反向,即存在镜像。
假设将x轴反向,则
s x = − s x e 0 = − e 0 s_x = -s_x \\[2px] e0 = -e0 sx=−sxe0=−e0
到这里,我们就得到了缩放系数
[ s x s y s z ] \begin{bmatrix} s_x \\ s_y \\ s_z \end{bmatrix} sxsysz
旋转矩阵
[ e 0 e 1 e 2 ] \begin{bmatrix} e0 & e1 & e2 \end{bmatrix} [e0e1e2]
还是那句话,真正理解了原理,真的很简单。祝大家打好基础,技术突飞猛进。