三维变换矩阵深度理解之变换矩阵分解_三维矩阵分解 元素为向量
概述
三维变换矩阵在几何核心库、渲染引擎、游戏开发等多个方面都有广泛的应用。在实际应用中,我们有时候需要单独使用三维变化的平移、旋转或缩放解决业务问题。本文将详细讲解将三维变换矩阵拆分为平移、旋转、缩放的分解算法,同时也作为对前一篇文章的理解加强。
了解了原理,一定会发现这个看似麻烦的问题解决起来非常简单。作者的写作目标就是把复杂抽象的数学问题和实际工作相结合,通俗易懂的介绍给大家。
如果没有读过前一篇文章的建议先读一下,链接如下
一文彻底弄懂三维变换矩阵
本文以后用“上篇文章”代替该文章。
用平移、旋转、缩放表示原矩阵
假设我们要分解的三维变化矩阵如下
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]
还是那句话,真正理解了原理,真的很简单。祝大家打好基础,技术突飞猛进。