> 技术文档 > 三维变换矩阵深度理解之变换矩阵分解_三维矩阵分解 元素为向量

三维变换矩阵深度理解之变换矩阵分解_三维矩阵分解 元素为向量


概述

三维变换矩阵在几何核心库、渲染引擎、游戏开发等多个方面都有广泛的应用。在实际应用中,我们有时候需要单独使用三维变化的平移、旋转或缩放解决业务问题。本文将详细讲解将三维变换矩阵拆分为平移、旋转、缩放的分解算法,同时也作为对前一篇文章的理解加强。

了解了原理,一定会发现这个看似麻烦的问题解决起来非常简单。作者的写作目标就是把复杂抽象的数学问题和实际工作相结合,通俗易懂的介绍给大家

如果没有读过前一篇文章的建议先读一下,链接如下

       一文彻底弄懂三维变换矩阵

本文以后用“上篇文章”代替该文章。

用平移、旋转、缩放表示原矩阵

假设我们要分解的三维变化矩阵如下

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=(Pxsxe0,  Pysye1,  Pzsze2)+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=[sxe00sye10sze20PT1]      (公式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=sxe0∣=sxe0∣=a002+a102+a202 sy=sye1∣=sye1∣=a012+a112+a212 sz=sze2∣=sze2∣=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+a202 sy=a012+a112+a212 sz=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]

还是那句话,真正理解了原理,真的很简单。祝大家打好基础,技术突飞猛进。

三维变换矩阵深度理解之变换矩阵分解_三维矩阵分解 元素为向量