搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
菜鸟追梦旅行
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
Selenium元素定位方法:class_name定位_selenium class_name
2
【Rust日报】2020-07-16 j4rs,一个在 Rust 中调用 Java 代码的 Crate
3
RPA的基本概念,RPA介绍及作用,RPA是干什么的_通俗介绍rpa
4
程序员笔试题收集汇总(三)_中等程序员笔试题
5
解决:pip is configured with locations that require TLS/SSL, howeve......_linux warning: pip is configured with locations th
6
rustc cargo Rust 版本 Cargo 更改源_rustc 版本
7
pytorch中模型训练的学习率动态调整
8
阿里云:访问公网IP地址需要在实例安全组白名单中增加Workbench的服务器白名单_访问公网ip地址需要在实例安全组白名单中增加 workbench的服务器白名单
9
VC++六种Runtime Library
10
Github Actions实现CI/CD(golang项目)
当前位置:
article
> 正文
第4章 学习Shader所需的数学基础(中)(矩阵)_矢量用矩阵表示
作者:菜鸟追梦旅行 | 2024-04-26 19:45:55
赞
踩
矢量用矩阵表示
4.4 矩阵
不幸的是,没有人能告诉你母体( matrix)究竟是什么。你需要自己去发现它。
一一电影《黑客帝国》(英文名: The Matrix )
矩阵,英文名是matrix 。如果你用翻译软件去查matrix 这个单词的翻译,就会发现它还有一个意思就是母体。事实上,很多人都不知道,那部具有跨时代意义的电影《黑客帝国》的英文名就是《The Matrix ))。在电影《黑客帝国》中,母体是一个庞大的虚拟系统,它看似虚无续纱,但又连接万物。这一点和矩阵有异曲同工之妙。
没有人敢否认矩阵在三维数学中的重要性,事实上矩阵在整个线性代数的世界中都扮演了举足轻重的角色。在三维数学中,我们通常会使用矩阵来进行变换。一个矩阵可以把一个矢量从一个坐标空间转换到另一个坐标空间。在第2 章渲染流水线中,我们就看到了很多坐标变换,例如在顶点着色器中我们需要把顶点坐标从模型空间变换到齐次裁剪坐标系中。而在这一章中,我们先来认识一下矩阵这个概念。
那么,现在我们就来看一下,这些放在一个小括号里的数字怎么就这么重要呢?为什么数学家们都喜欢用这个小东西来搞出这么多名堂呢?
4.4.1 矩阵的定义
相信很多读者都见过矩阵的真容,例如像下面这个样子:
从它的外观上来看,就是一个长方形的网格,每个格子里放了一个数字。的确,矩阵就是这么简单:它是由m × n 个标量组成的长方形数组。在上面的式子中,我们是用方括号来围住矩阵中的数字,而一些其他的资料可能会使用圆括号或花括号来表示,这都是等价的。
既然是网格结构,就意味着矩阵有行( row ) 列( column)之分。例如上面的例子就是一个3 × 4的矩阵,它有三行四列。据此,我们可以给出矩阵的一般表达式。以3 × 3 的矩阵为例,它可以写成:
mij 表明了这个元素在矩阵M 的第i 行、第j 列。
这样看起来矩阵也没什么神秘的嘛。但是,越简单的东西往往越厉害,这也是数学的魅力所在。
4.4.2 和矢量联系起来
前面说到,矢量其实就是一个数组,而矩阵也是一个数组。既然都是数组,那就是一家人了!
我们很容易想到,我们可以用矩阵来表示矢量。实际上,矢量可以看成是nx 1 的列矩阵( column matrix ) 或1x n 的行矩阵(row matrix ),其中n 对应了矢量的维度。例如,矢量v=(3, 8,6)可以写成行矩阵[3 8 6]
或列矩阵(竖着写);
为什么我们要把矢量和矩阵联系在一起呢?这是为了可以让矢量像一个矩阵一样一起参与矩阵运算。这在空间变换中将非常有用。
到现在,使用行矩阵还是列矩阵来表示矢量看起来是没什么分别的。的确,我们可以根据自己的喜好来选择表示方法,但是, 如果要和矩阵一起参与乘法运算时,这种选择会影响我们的书写顺序和结果。这正是我们下面要讲到的。
4.4.3 矩阵运算
矩阵这个家伙看起来比矢量要庞大很多,那么它的运算是不是很复杂呢?答案是肯定的。但是,幸运的是在写Shader 的过程中,我们只需要和很简单的一部分运算打交道。
1. 矩阵和标量的乘法
和矢量类似,矩阵也可以和标量相乘,它的结果仍然是一个相同维度的矩阵。它们之间的乘法非常简单,就是矩阵的每个元素和该标量相乘。以3 ×3 的矩阵为例,其公式如下:
2. 矩阵和矩阵的乘法
两个矩阵的乘法也很简单,它们的结果会是一个新的矩阵,并且这个矩阵的维度和两个原矩阵的维度都有关系。
一个r × n 的矩阵A 和一个n × c 的矩阵B 相乘,它们的结果AB 将会是一个r × c 大小的矩阵。
请读者注意它们的行列关系,第一个矩阵的列数必须和第二个矩阵的行数相同,它们相乘得到的矩阵的行数是第一个矩阵的行数,而列数是第二个矩阵的列数。例如,如果矩阵A 的维度是4 × 3,矩阵B 的维度是3 × 6,那么AB 的维度就是4 × 6。
如果两个矩阵的行列不满足上面的规定怎么办?那么很抱歉,这两个矩阵就不能相乘, 因为它们之间的乘法是没有被定义的。那么为什么会有上面的规定呢?等我们理解了矩阵乘法的操作过程自然就会明白。
我们先给出看起来很复杂难懂( 当给出直观的表式后读者会发现其实它没那么难懂)的数学表达式: 设有r × n 的矩阵A 和一个nxc 的矩阵B,它们相乘会得到一个r× c 的矩阵C=AB 。那么, C中的每一个元素Cij等于A 的第i 行所对应的矢量和B 的第 j 列所对应的矢量进行矢量点乘的结果,即
看起来很复杂对吗?但是,我们可以用一个更简单的方式来解释:对于每个元素cij,我们找到A 中的第i 行和B 中的第j 列,然后把它们的对应元素相乘后再加起来,这个和就是Cij。
一种更直观的方式如图4.30 所示。假设A 的大小是4 x 2, B 的大小是2x4,那么如果要计算C 的元素C23 的话,先找到对应的行矩阵和列矩阵,即A 中的第2 行和B 中的第3 列,把它们进行矢量点积后就可以得到结果值。因此, c23=a21*b13+a22*b23.
在Shader 的计算中,我们更多的是使用4 × 4 矩阵来运算的。
矩阵乘法满足一些性质。
性质一: 矩阵乘法并不满足交换律。
也就是说,通常情况下:
AB≠BA
性质二: 矩阵乘法满足结合律。
也就是说,
(AB)C=A(BC)
矩阵乘法的结合律可以扩展到更多矩阵的相乘。例如,
ABCDE=((A(BC))D)E=(AB)(CD)E
读者可根据矩阵乘法的定义很轻松地验证上述结论。
4.4.4 特殊的矩阵
有一些特殊的矩阵类型在Shader 中经常见到。这些特殊的矩阵往往具有一些重要的性质。
1. 方块矩阵
方块矩阵( square matrix )
,简称方阵,是指那些行和列数目相等的矩阵。在三维渲染里,最常使用的就是3 × 3 和4 × 4 的方阵。
方阵之所以值得单独拿出来讲,是因为矩阵的一些运算和性质是只有方阵才具有的。例如,对角元素( diagonal elements )。方阵的对角元素指的是行号和列号相等的元素,例如m11 、m22 、m33 等。如果把方阵看成一个正方形的话,这些元素排列在正方形的对角线上,这也是它们名字的由来。如果一个矩阵除了对角元素外的所有元素都为0 , 那么这个矩阵就叫做
对角矩阵( diagonal
matrix )
. 例如,下面就是一个4 × 4 的对角矩阵:
2. 单位矩阵
一个特殊的对角矩阵是
单位矩阵( identity matrix )
,用In来表示。一个3x3的单位矩阵如下:
为什么要为这种矩阵单独起一个名字呢?这是因为,任何矩阵和它相乘的结果还是原来的矩
阵。也就是说:
MI=IM=M
这就跟标量中的数字1一样!
3. 转置矩阵
转置矩阵( transposed matrix )
实际是对原矩阵的一种运算,即转置运算。给定一个r × c 的矩阵M,它的转置可以表示成MT,这是一个cxr 的矩阵。转置矩阵的计算非常简单,我们只需要把原矩阵翻转一下即可。也就是说,原矩阵的第i 行变成了第i 列,而第j列变成了第j 行。数学公式是:
对于行矩阵和列矩阵来说,我们可以使用转置操作来转换行列矩阵:
转置矩阵也有一些常用的性质。
4. 逆矩阵
逆矩阵(inverse matrix )
大概是本书讲到的关于矩阵最复杂的一种操作了。不是所有的矩阵都有逆矩阵,第一个前提就是,该矩阵必须是一个方阵。给定一个方阵M, 它的逆矩阵用M-1 来表示。逆矩阵最重要的性质就是, 如果我们把M 和M-1 相乘,那么它们的结果将会是一个单位矩阵。也就是说,
前面说了,并非所有的方阵都有对应的逆矩阵。一个明显的例子就是一个所有元素都为0 的
矩阵, 很显然,任何矩阵和它相乘都会得到一个零矩阵,即所有的元素仍然都是0 。如果一个矩
阵有对应的逆矩阵,我们就说这个矩阵是可逆的( inver“hie ) 或者说是非奇异的( nonsingular) ;
相反的,如果一个矩阵没有对应的逆矩阵,我们就说它是不可逆的( noninver位hie ) 或者说是奇
异的(singular ) 。
那么如何判断一个矩阵是否是可逆的呢?简单来说, 如果一个矩阵的行列式(determinant)不为0,那么它就是可逆的。关于矩阵的行列式是什么以及如何求解一个矩阵的逆矩阵, 可以参见本章的扩展阅读部分。由于这部分内容涉及较多计算和其他定义,本书不再赘述。在写Shader的过程中, 这些矩阵通常可以通过调用第三方库(如C++数学库Eigen)来直接求得,不需要开发者手动计算。在Unity 中,重要变换矩阵的逆矩阵Unity 也提供了相应的变量供我们使用。关于这些Unity 内置的矩阵, 读者可以在本章的
3.8 节找到更详细的解释。
逆矩阵是具有几何意义的。我们知道一个矩阵可以表示一个变换(详见4.5 节〉,而逆矩阵允
许我们还原这个变换,或者说是计算这个变换的反向变换。因此,如果我们使用变换矩阵M对矢
量v 进行了一改变换,然后再使用它的逆矩阵M-1 进行另一次变换,那么我们会得到原来的矢量。
这个性质可以使用矩阵乘法的结合律很容易地进行证明:
5. 正交矩阵
另一个特殊的方阵是正交矩阵(orthogonal matrix )。正交是矩阵的一种属性。如果一个方阵M 和它的转置矩阵的乘积是单位矩阵的话,我们就说这个矩阵是正交的( orthogonal )。反过来也是成立的。也就是说,矩阵M 是正交的等价于:
这个式子非常有用,因为在三维变换中我们经常会需要使用逆矩阵来求解反向的变换。而逆矩阵的求解往往计算量很大,但转置矩阵却非常容易求解: 我们只需要把矩阵翻转一下就可以了。
那么,我们如何提前判断一个矩阵是否是正交矩阵呢?读者可能会说, 判断MMT=I 是否成立就可以了嘛!但是,求解这样一个表达式无疑是需要一定计算量的,这些计算量可能和直接求解逆矩阵无异。而且,如果我们判断出来这不是一个正交矩阵,那么这些花在验证是否是正交矩阵上的计算就浪费了。因此,我们更想不需要计算,而仅仅根据一个矩阵的构造过程来判断这个矩阵是否是正交矩阵。为此, 我们需要来了解正交矩阵的几何意义。
我们来看一下对于3 × 3 的正交矩阵有什么特点。根据正交矩阵的定义,我们有:
这样,我们就有了9 个等式:
我们可以得到以下结论:
矩阵的每一行,即c1、c2和c3 是单位矢量,因为只有这样它们与自己的点积才能是1;
矩阵的每一行,即c1、c2 和c3 之间互相垂直,因为只有这样它们之间的点积才能是0 。
上述两条结论对矩阵的每一列同样适用,因为如果M是正交矩阵的话, MT 也会是正交矩阵。
也就是说,如果一个矩阵满足上面的条件,那么它就是一个正交矩阵。读者可以注意到, 一组标准正交基(定义详见4.2.2 节〉可以精确地满足上述条件。在4.6.2 节中,我们会使用坐标空间的基矢量来构建用于空间变换的矩阵。因此,如果这些基矢量是一组标准正交基的话(例如只存在旋转变换),那么我们就可以直接使用转置矩阵来求得该变换的逆变换。
读者: 我被标准正交、正交这些概念搞混了,可以再说明一下是什么意思吗?
我们:读者应该已经知道, 一个坐标空间需要指定一组基矢量,也就是我们理解的坐标轴。
如果这些基矢量之间是互相垂直的,那么我们就把它们称为是一组正交基( orthogonal basis ) .但是,它们的长度并不要求一定是1 。如果它们的长度的确是1 的话,我们就说它们是一组标准正交基( orthonormal basis )。因此,一个正交矩阵的行和列之间分别构成了一组标准正交基。但是, 如果我们使用一组正交基来构建一个矩阵的话,这个矩阵可能就不是一个正交矩阵,因为这些基矢量的长度可能不为1 ,也就是说它们不是标准正交基。
4.4.5 行矩阵还是列矩阵
我们己经了解了足够多的数学概念,但在学习矩阵的几何意义之前,我们有必要说明一下行矩阵和列矩阵的问题。
在前面的章节中我们讲到,可以把一个矢量转换成一个行矩阵或是列矩阵。它们本身是没有区别的,但是,当我们需要把它和另一个矩阵相乘时,就会出现一些差异。
读者认真对比就会发现,结果矩阵除了行列矩阵的区别外,里面的元素也是不一样的。这就意味着, 在和矩阵相乘时选择行矩阵还是列矩阵来表示矢量是非常重要的,因为这决定了矩阵乘法的书写次序和结果值。
在Unity 中,常规做法是把矢量放在矩阵的右侧, 即把矢量转换成列矩阵来进行运算。因此,在本书后面的内容中, 如无特殊情况, 我们都将使用列矩阵。这意味着, 我们的矩阵乘法通常都是右乘, 例如:
如果你还是不能明白上面的含义,可以参见练习题3 。
(给定一个矢量v, 分别把它当成行矩阵和列矩阵与矩阵M相乘,得到的结果是不一致的;为了得到一致的结果,我们可以对矩阵进行转置,
即
Mv
=
v
乘以
M
的转置)
4.4.6 练习题
4.5 矩阵的几何意义:变换
关于矩阵,很多困扰初学者的问题都是类似的:
点和矢量都可以在图像中画出来,那么矩阵可以吗?
我听说矩阵和线性变换、仿射变换有关,这些变换到底是什么意思呢? . 我总是听到齐次坐标这个名词,它是什么意思呢?
变换和矩阵的关系又是什么呢?或者说,给定一个变换,我如何得到它对应的矩阵呢?
在学习完本节后,希望读者们能够回答出这些问题。
对于第一个问题,在三维渲染中矩阵可以可视化吗? 幸运的是,答案是肯定的,这个可视化的结果就是变换。因此,如果读者在后面的内容中看到了一个矩阵,那么你可以认为自己看到的就是一个变换(当然,在线性代数中矩阵的用处不仅是用于变换,但本书的讨论范围仅在于此)。
在游戏的世界中,这些变换一般包含了旋转、缩放和平移。游戏开发人员希望给定一个点或矢量,再给定一个变换〈例如把点平移到另一个位置,把矢量的方向旋转30度等〉,就可以通过某个数学运算来求得新的点和矢量。聪明的先人们发现,可以使用矩阵来完美地解决这个问题。那么问题就变成了,我们如何使用矩阵来表示这些变换?
4.5.1 什么是变换
变换( transform )
, 指的是我们把一些数据,如点、方向矢量甚至是颜色等,通过某种方式进行转换的过程。在计算机图形学领域,变换非常重要。尽管通过变换我们能够进行的操作是有限的,但这些操作已经足够奠定变换在图形学领域举足轻重的地位了。
我们先来看一个非常常见的变换类型一一
线性变换(linear transform )
. 线性变换指的是那些可以保留矢量加和标量乘的变换。用数学公式来表示这两个条件就是:
上面的式子看起来很抽象。
缩放( scale )
就是一种线性变换。例如, f(x)=2x,可以表示一个大小为2 的统一缩放,即经过变换后矢量x 的模将被放大两倍。可以发现, f(x)=2x 是满足上面的两个条件的。同样,
旋转( rotation )
也是一种线性变换。对于线性变换来说,如果我们要对一个三维的矢量进行变换,那么仅仅使用3 × 3 的矩阵就可以表示所有的线性变换。
线性变换除了包括旋转和缩放外,还包括错切( shear ) 、镜像( mirroring,也被称为reflection ) 、正交投影( orthographic projection ) 等,但本书着重讲述旋转和缩放变换。
但是,仅有线性变换是不够的。我们来考虑平移变换,例如f(x)=x+(1 ,2,3) 。这个变换就不是一个线性变换,它满足标量乘法,但不满足矢量加法。如果我们令x=(1, 1, 1 ),那么:
可见,两个运算得到的结果是不一样的。因此,我们不能用一个3 × 3 的矩阵来表示一个平移变换。这是我们不希望看到的,毕竟平移变换是非常常见的一种变换。
这样,就有了
仿射变换(affine transform )
。仿射变换就是合并线性变换和平移变换的变换类型。仿射变换可以使用一个4x4 的矩阵来表示,为此,我们需要把矢量扩展到四维空间下,这就是
齐次坐标空间( homogeneous space )
。
表4.1 给出了图形学中常见变换矩阵的名称和它们的特性。
在下面的内容中,我们将学习其中一些基本的变换类型: 旋转,缩放和平移。对于正交投影和透视投影, 我们将在4.6.7 节中给出它们的表示方法。而对于其他变换类型, 本书不再具体讨论,读者可以在本章的扩展阅读中找到更多内容。
4.5.2 齐次坐标
我们知道,由于3 × 3 矩阵不能表示平移操作,我们就把其扩展到了4 × 4 的矩阵(是的,只要多一个维度就可以实现对平移的表示〉。为此,我们还需要把原来的三维矢量转换成四维矢量,也就是我们所说的
齐次坐标( homogeneous coordinate)
(事实上齐次坐标的维度可以超过四维,但本书中所说的齐次坐标将泛指四维齐次坐标〉。我们可以发现,齐次坐标并没有神秘的地方,它
只是为了方便计算而使用的一种表示方式而己。
如上所说,齐次坐标是一个四维矢量。那么,我们如何把三维矢量转换成齐次坐标呢?对于一个点,从三维坐标转换成齐次坐标是把其w 分量设为1 ,而对于方向矢量来说,需要把其w 分量设为0。这样的设置会导致,当用一个4x4 矩阵对一个点进行变换时,平移、旋转、缩放都会施加于该点。但是如果是用于变换一个方向矢量,平移的效果就会被忽略。我们可以从下面的内容中理解,这些差异的原因。
4.5.3 分解基础变换矩阵
我们已经知道,可以使用一个4x4的矩阵来表示平移、旋转和缩放。我们把表示纯平移、纯旋转和纯缩放的变换矩阵叫做基础变换矩阵。这些矩阵具有一些共同点,我们可以把一个基础变换矩阵分解成4 个组成部分:
其中, 左上角的矩阵M
3 x 3
用于表示旋转和缩放, t
3x1
用于表示平移,0
1x3
是零矩阵, 即0
1 x 3
=[0, 0, 0],右下角的元素就是标量 1。
接下来,我们来具体学习如何用这样一个4 × 4 的矩阵来表示平移、旋转和缩放。
4.5.4 平移矩阵
我们可以使用矩阵乘法来表示对一个点进行平移变换:
从结果来看我们可以很容易看出为什么这个矩阵有平移的效果: 点的x、y、z 分量分别增加了一个位置偏移。在3D 中的可视化效果是,把点(x,y,z)在空间中平移了(tx, ty, tz)个单位。
有趣的是,如果我们对一个方向矢量进行平移变换,结果如下:
可以发现,平移变换不会对方向矢量产生任何影响。这点很容易理解,我们在学习矢量的时候就说过了,矢量没有位置属性,也就是说它可以位于空间中的任意一点,因此对位置的改变(即平移)不应该对四维矢量产生影响。
现在, 读者应该明白当给定一个平移操作时如何构建一个平移矩阵:基础变换矩阵中的t
3x1
矢量对应了平移矢量,左上角的矩阵
M3 x3 为单位矩阵
I
3
。
平移矩阵的逆矩阵就是反向平移得到的矩阵,即
可以看出,平移矩阵并不是一个正交矩阵。
4.5.5 缩放矩阵
我们可以对一个模型沿空间的x 轴、y 轴和z 轴进行缩放。同样,我们可以使用矩阵乘法来表示一个缩放变换:
对方向矢量可以使用同样的矩阵进行缩放:
如果缩放系
数kx=ky=kz,我们把这样的缩放称为
统一缩放( uniform scale )
, 否则称为
非统一
缩放( nonuniform scale )
。
从外观上看,统一缩放是扩大整个模型,而非统一缩放会拉伸或挤压模
型。更重要的是,统一缩放不会改变角度和比例信息,而非统一缩放会改变与模型相关的角度
和比例。例如在对法线进行变换时,如果存在非统一缩放,直接使用用于变换顶点的变换矩阵的
话,就会得到错误的结果。正确的变换方法可参见4 .7 节。
缩放矩阵的逆矩阵是使用原缩放系数的倒数来对点或方向矢量进行缩放,即
缩放矩阵一般不是正交矩阵。
上面的矩阵只适用于沿坐标轴方向进行缩放。如果我们希望在任意方向上进行缩放,就需要使用一个复合变换。其中一种方法的主要思想就是,先将缩放轴变换成标准坐标轴,然后进行沿坐标轴的缩放,再使用逆变换得到原来的缩放轴朝向。
4.5.6 旋转矩阵
旋转是三种常见的变换矩阵中最复杂的一种。我们知道,旋转操作需要指定一个旋转轴,这个旋转轴不一定是空间中的坐标轴,但本节所讲的旋转就是指绕着空间中的x 轴, y 轴或z 轴进行旋转。
如果我们需要把点绕着x 轴旋转θ度,可以使用下面的矩阵:
旋转矩阵的逆矩阵是旋转相反角度得到的变换矩阵。旋转矩阵是正交矩阵,而且多个旋转矩阵之间的串联同样是正交的。
4.5.7 复合变换
我们可以把平移、旋转和缩放组合起来,来形成一个复杂的变换过程。例如,可以对一个模型先进行大小为(2, 2, 2)的缩放,再绕y 轴旋转30。,最后向z 轴平移4 个单位。复合变换可以通过矩阵的串联来实现。上面的变换过程可以使用下面的公式来计算:
由于上面我们使用的是列矩阵,因此阅读顺序是从右到左,即先进行缩放变换,再进行旋转变换,最后进行平移变换。需要注意的是,变换的结果是依赖于变换顺序的,由于矩阵乘法不满足交换律,因此矩阵的乘法顺序很重要。也就是说,不同的变换顺序得到的结果可能是一样的。
想象一下,如果让读者向前一步然后左转,记住此时的位置。然后回到原位,这次先左转再向前走一步,得到的位置和上一次是不一样的。究其本质,是因为矩阵的乘法不满足交换律,因此不同的乘法顺序得到的结果是不一样的。
在绝大多数情况下,我们约定变换的顺序就是先缩放,再旋转,最后平移。
读者:为什么要约定这样的顺序,而不是其他顺序呢?
我们:因为这样的变换顺序是我们需要的。想象我们对奶牛妞妞进行一个复合变换。如果我们按先平移、再缩放的顺序进行变换,假设初始情况下妞妞位于原点,我们先按(0, 0, 5)平移它,现在它距离原点5 个单位。然后再将它放大2 倍,这样所有的坐标都变成了原来的2倍,而这意味着妞妞现在的位置是(0, 0, 10),这不是我们希望的。正确的做法是,先缩放再平移。也就是说,我们先在原点对妞妞进行2 倍的缩放,再进行平移,这样妞妞的大小正确了,位置也正确了。
为了从数学公式上理解变换顺序的本质,我们可以对比不同变换顺序产生的变换矩阵的表达式。如果我们只考虑对y 轴的旋转的话,按先缩放、再旋转、最后平移这样的顺序组合3 种变换得到的变换矩阵是:
而如果我们使用了其他变换顺序,例如先平移,再缩放,最后旋转,那么得到的变换矩阵是:
从两个结果可以看出,得到的变换矩阵是不一样的。
除了需要注意不同类型的变换顺序外,我们有时还需要小心旋转的变换顺序。在4.5.6 节中,我们给出了分别绕x 轴、y 轴和z 轴旋转的变换矩阵。一个问题是,如果我们需要同时绕着3 个轴进行旋转,是先绕x 轴、再绕y 轴最后绕z 轴旋转还是按其他的旋转顺序呢?
当我们直接给出( θx, θy, θz)这样的旋转角度时,需要定义一个旋转顺序。在Unity 中,这个旋转顺序是zxy,这在旋转相关的API 文档中都有说明。这意味着,当给定(θx, θy, θz)这样的旋转角度时,得到的组合旋转变换矩阵是:
一些读者会有疑问:上面的公式书写顺序是不是反了?不是说列矩阵要从右往左读吗?这样
一来顺序不就颠倒了吗?实际上,有一个非常重要的东西我们没有说明白,那就是旋转时使用的
坐标系。给定一个旋转顺序(例如这里的zxy ),以及它们对应的旋转角度(θx, θy, θz),有两种坐标
系可以选择。
绕坐标系E下的z 轴旋转θz,绕坐标系E 下的y 轴旋转θy,绕坐标系E 下的x 轴旋转θx,即进行一次旋转时不一起旋转当前坐标系。
绕坐标系E下的z 轴旋转θz,在坐标系E 下在绕z 轴旋转θz 后的新坐标系E’下的y 轴旋转θy , 在坐标系E’下再绕y 轴旋转θy 后的新坐标系E”下的x 轴旋转θx,即在旋转时,把坐标系一起转动。
很容易知道,这两种选择的结果是不一样的。但如果把它们的旋转顺序颠倒一下,它们得到的结果就会是一样的!说得明白点,在第一种情况下,按zxy 顺序旋转和在第二种情况下,按yxz顺序旋转是一样的。而Unity 文档中说明的旋转顺序指的是在第一种情况下的顺序。
和上面不同类型的变换顺序导致的问题类似,不同的旋转顺序得到的结果也可能是不一样的。我们同样可以通过对比不同旋转顺序得到的变换矩阵来理解为什么会出现这样的不同。而这个验证过程留给读者作为练习。
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/492791
推荐阅读
article
质量
基础设施
服务平台
建设
,
NQI
一站式系统开发方案_
质量
控制
硬件平台
建设
...
质量
基础设施
服务平台
建设
,
NQI
一站式系统开发方案
质量
基础设施
服务平台
,切实为市场主体提供了计量、标准、认证认可、检验检...
赞
踩
article
List
&Array
List
&Linked
List
类
API
_
arraylist
和
linklist
a...
Array
List
与Linked
List
的区别数据存储结构:Array
List
是可变数组Linked
List
是链表(双向...
赞
踩
article
在
本
地跑一个大
语言
模型
(3) - 让
模型
自主使用
工具
_
本
机能跑
的
语言
模型
...
根据OpenAI官方文档,是使得大型
语言
模型
具备可以连接到外部
工具
的
能力。简而言之,开发者事先给
模型
提供了若干
工具
(函数...
赞
踩
article
【分享】
PostgreSQL
创建
自增
序列
、
查询
序列
、使用
序列
_
postgresql
查询
序列
...
【代码】【分享】
PostgreSQL
创建
自增
序列
、
查询
序列
、使用
序列
。
_
postgresql
查询
序列
postgresq...
赞
踩
article
SQLITE3
添加
加密功能SqlCipher的编译和使用_
sqlite
.
exe
打开加密的
sqlite
...
几千个错误,什么未定义呀,什么的,然后根据内容
添加
了头文件,好了没有未定义了,提示什么winbase.h啥的文件内部有莫...
赞
踩
article
Java
随机数
之
System
/
Random
/Secure
Random
详解_securerandomn...
我们在解决实际问题时,除了经常需要对数字、日期、时间进行操作之外,有时候还需要对系统进行设置,另外还需要生成一些
随机数
字...
赞
踩
article
IDEA
从
Gitee
拉取
代码
,推送
代码
教程_
idea
拉取
gitee
代码
...
使用
IDEA
工具
拉取
推送远程仓库
代码
_
idea
拉取
gitee
代码
idea
拉取
gitee
代码
...
赞
踩
article
Pos
t
greSQL
wi
t
h
子句 递归_
pgsql
wi
t
h
t
as...
在
Pos
t
greSQL
里,
wi
t
h
子句提供了一种方法写一个大的查询中使用的辅助报表与查询。它有助于打破复杂和大型查询简单...
赞
踩
article
iOS/
Android
SQLite
全文检索
——FTS (
Full
Text Search)_sq...
前言我们的APP部分功能为了满足用户离线使用搜索的场景,使用了内置
SQLite
数据库的方式,随着内容的日益丰富,数据库记...
赞
踩
article
常见
的
网络安全
架构
有哪些_
网络安全
产品
的
部署
架构
有哪些...
其次,无法防范绕过边界防御
的
攻击。边界防御是单一
的
、静态
的
安全防护技术,只要携带病毒
的
文件通过某种手段绕过边界防御
的
检测...
赞
踩
article
大
数据
趋势
分析
:如何利用AI提高
预测
准确率
...
1.背景介绍
大
数据
是指由于互联网、移动互联网、物联网等信息技术革命的产生,
数据
量
大
、增长迅速、多样化、实时性强的
数据
集。...
赞
踩
article
信息系统
项目
管理
师
与
系统集成
项目
管理
工程
师
5大区别_
系统集成
项目
管理
和
信息系统
管理
...
虽说
信息系统
项目
管理
师
考试难度要大一点,但
信息系统
项目
管理
师
可能比
系统集成
项目
管理
工程
师
更容易通过。
信息系统
项目
管理
师
与...
赞
踩
article
树莓
派
4B实现
和
电脑
之间的
UART
串口
通信
_
树莓
派
4b
和
电脑
端
串口
通信
...
树莓
派
4B通过
UART
实现与
电脑
通信
,包括接线
和
代码示例,实现数据收发无误。
树莓
派
4b
和
电脑
端
串口
通信
...
赞
踩
article
tf2保存加载模型_
saving
the
model
to
hdf5
format
requires
...
第一 官方可以直接保存整个模型,将模型保存为HDF5文件# 创建模型实例
model
= create_
model
()# ...
赞
踩
article
Git
安全
远程
访问:
SSH
密钥
对
生成、添加和连接步骤解析_
ssh
密钥
对
4096...
为了方便其他设备和平台的小伙伴观看往期文章:,关注后即可获取最新文章推送。_
ssh
密钥
对
4096
ssh
密钥
对
4096...
赞
踩
article
C++
:
模版
初阶 |
STL
简介_
stl
风格
...
大家都知道,瓦特改良蒸汽机,人类开始了工业革命,解放了生产力。机器生产淘汰掉了很多手工产品。本质是什么,重复的工作交给了...
赞
踩
article
明明
是
工作经验
越久越
吃香
,
为什么
程序员
却不
是
?
,
2024年最新再
不刷题
就晚
了
...
网络安全行业产业以来
,
随即新增加
了
几十个网络安全行业岗位︰网络安全专家、网络安全分析师、安全咨询师、网络安全工程师、安全...
赞
踩
article
【花雕动手做】
ASRPRO
-
Plus
语音
识别(04)---
控制
点亮与闪烁
板
载
LED
_
asrpro
核心...
1个电源
LED
,一个可
控制
LED
(与KEY3共用引脚PA4)。实验之一:通过
语音
控制
,点亮
板
载
LED
灯。电原理图(红点处...
赞
踩
article
【
毕业
季】
图匮于
丰
,
防俭于
逸;
治不忘乱
,
安不忘危
。...
【
毕业
季】进取人生
,
展望未来。【
毕业
季】
图匮于
丰
,
防俭于
逸;
治不忘乱
,
安不忘危
。 活动地址:毕...
赞
踩
article
【云上
ELK
系列】
Logstash
迁移
Elasticsearch
数据
方法
解读...
摘要: 用
Logstash
实现
Elasticsearch
集群快速
迁移
,解读
Logstash
中metadata的功效,避免...
赞
踩
相关标签
大数据
java
语言模型
人工智能
自然语言处理
postgresql
数据库
sql
sqlite
jvm
开发语言
intellij-idea
gitee
全文检索
fts
fts4
ios
web安全
架构
网络
linux
tensorflow
python
深度学习