Unity3D C#数学系列之矩阵基础
Posted WangShade
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity3D C#数学系列之矩阵基础相关的知识,希望对你有一定的参考价值。
目录
1 引言
大学学线性代数的时候简直是一头雾水,觉得太抽象了,数学家们怎么整出这么难以理解的东西。一学期学完,考试考完,然后就彻底把线性代数给遗忘了。但是现在在做Unity3D嘛,不可避免的要和矩阵打交道。由于每次用到一些矩阵的性质时,自己都得去翻翻书,为了节省时间,这里把自己容易遗忘的知识点给记录一下并且把之前没有彻底理解的问题给梳理一下。
2 矩阵的作用
我所理解的矩阵其实就是一个工具,用矩阵这个工具可以求解线性方程组、将一个点从一个坐标系变换到另一个坐标系或者移动到另外一个位置。但是我们为什么需要用到这个工具?因为它特别方便,比如我们再三维空间中,只需要一个4×4的矩阵,就可以把缩放、旋转、平移这些变换全部表示完。如果不使用矩阵(也不使用四元数),要完成这些变换该有多难,可以说是简直无从下手。
3 矩阵的乘法
3.1 矩阵与标量的乘法
矩阵与标量相乘就是将矩阵中的各个元素与标量相乘即可。举个例子:
3.2 矩阵与矩阵的乘法
需要注意并不是任何两个矩阵都可以相乘。第一个矩阵的列数必须要等于第二个矩阵的行数,这两个矩阵才能相乘。
比如有矩阵
A
\\textbfA
An×m、
B
\\textbfB
Bm×r、
C
\\textbfC
Cn×k,则只有
A
\\textbfA
A与
B
\\textbfB
B才可以相乘,
A
\\textbfA
A与
C
\\textbfC
C是不可以相乘的。
A
\\textbfA
A与
B
\\textbfB
B相乘后会得到一个新的矩阵
M
\\textbfM
Mn×r。
新矩阵
M
\\textbfM
Mn×r中的各个元素的值是多少呢?
第i行第j列的元素
M
\\textbfM
Mij=
A
\\textbfA
A的第i行与
B
\\textbfB
B的第j列的点积。
如
M
\\textbfM
M11的计算方式如下:
通用的计算公式如下:
矩阵与矩阵的乘法有以下两个性质:
①一般情况下,矩阵的乘法不满足交换律。
(下面会看到单位矩阵与其他矩阵的乘法和矩阵与其逆矩阵的乘法是满足交换律的)
①矩阵的乘法满足结合律。
结合律可以推导到更多矩阵的相乘,如:
矩阵与矩阵的乘法有什么用?用处非常多,不过在Unity3D开发中只用到它变换的功能。
我们常常将一个向量或者一个点(齐次坐标下)与一个4×4的矩阵相乘,从而得到经过各种变换(平移、旋转、缩放等)后的向量或点。比如一个点乘以平移矩阵就得到平移后的点,乘以一个旋转矩阵就得到旋转后的点。
4 特殊矩阵
4.1 方块矩阵
简称方阵,也即行数=列数的矩阵。
比如3×3的矩阵、4×4的矩阵。我们在编程过程中,用得最多的也是这两个矩阵。
4.1.1 对角矩阵
对角矩阵是方阵中的一种特殊的矩阵。它的特点是除了对角元素外的所有元素都为0。举个例子:
4.1.2 单位矩阵
单位矩阵又是对角矩阵中的一种特殊矩阵,其特点是对角元素全部为1。
英文为identity matrix。所以一般用字母
I
\\textbfI
I表示。
举个例子:
为什么单独把单位矩阵提出来,因为它有个特殊的性质,就是任何矩阵和它相乘的结果都还是原来的矩阵,并且与单位矩阵的相乘是满足交换律的(注意:普通的矩阵相乘是不满足的)。
4.2 转置矩阵
把一个矩阵
M
\\textbfM
M进行转置操作就得到了该矩阵的转置矩阵,记作
M
\\textbfM
MT(转置的英文为transpose,所以转置一般用T来表示)。
什么是转置操作呢?其实就是把原矩阵的行变为列。
举个例子:
转置矩阵的性质有两个:
①转置矩阵的转置等于原矩阵。
②
AB
\\textbfAB
AB的转置矩阵等于
B
\\textbfB
B的转置矩阵与
A
\\textbfA
A的转置矩阵的积。
4.3 逆矩阵
我们把矩阵
M
\\textbfM
M的逆矩阵记做
M
\\textbfM
M-1。
两者满足条件:矩阵
M
\\textbfM
M与其逆矩阵
M
\\textbfM
M-1的乘积为单位矩阵。
需要注意的:不是所有矩阵都有逆矩阵。只有方阵才有逆矩阵。一个矩阵拥有逆矩阵的充要条件是其行列式不等于0。
如果一个矩阵有逆矩阵,我们就说这个矩阵是可逆的或者是非奇异的;如果一个矩阵没有逆矩阵,我们就说此矩阵是不可逆的。
逆矩阵有几个重要的性质:
①逆矩阵的逆矩阵是原矩阵本身。
(这一点和转置矩阵相同)
②单位矩阵的逆矩阵是其本身。
③转置矩阵的逆矩阵等于逆矩阵的转置。
④
AB
\\textbfAB
AB的逆矩阵等于
B
\\textbfB
B的逆矩阵与
A
\\textbfA
A的逆矩阵的积。
(这一点也与转置矩阵是相同的)
逆矩阵有什么用?在坐标变换过程中中,我们可以用它来还原我们所作的变换。
比如我们已知局部坐标上的一个点A,并且已知该局部坐标到世界坐标的变换矩阵
M
\\textbfM
Mlocal2world,那么我们可以算出点A在世界坐标系中的表示为
B
\\textbfB
B=
M
\\textbfM
Mlocal2world
A
\\textbfA
A(需要注意的是Unity中向量或点与变换矩阵相乘时,一般将向量或点放在矩阵的右侧,也即将向量或点写做列向量的形式,后面会专门阐述这一点)。
现在,我们把条件改一下,只知道点A在世界坐标系中的表示为
B
\\textbfB
B,以及局部坐标到世界坐标的变换矩阵
M
\\textbfM
Mlocal2world,那么如何求到局部坐标系中点A的值呢?见下图。
根据上面的推导,我们可以看出逆矩阵的作用其实就是还原变换或者说反变换。
但是上面的推导还有个问题,一个矩阵的逆矩阵该怎么求?逆矩阵的求解是非常非常复杂的过程,矩阵的维数越高,求解难度和运算量越大(所以在Unity开发过程中,我们一般不会直接求解逆矩阵,而是通过构建下一节将讲到的正交矩阵来间接求到逆矩阵)。所以具体怎么求逆矩阵这里就不再说了,感兴趣的同学可以去查一查。庆幸的是Unity已经帮我们封装好求解逆矩阵的方法。
比如我们常用的Matrix4×4矩阵,直接使用它的inverse属性就可以得到其逆矩阵。
Matrix4x4 matrixLocal2World = transform.localToWorldMatrix;
// 下面这句等价于matrixWorld2Local = transform.worldToLocalMatrix
Matrix4x4 matrixWorld2Local = matrixLocal2World.inverse;
4.4 正交矩阵
正交矩阵是一种非常非常特殊的矩阵,它的定义如下:
用文字描述就是,一个矩阵与它的转置矩阵的积为单位矩阵,我们就说这个矩阵是正交矩阵。
再结合逆矩阵的定义:
我们可以得出一个非常非常重要的性质,即正交矩阵的逆矩阵其实就是它的转置矩阵。
我们上一节说过,一个矩阵的逆矩阵非常难求、计算量特别大。但如果一个变换矩阵恰好是正交矩阵,那它的逆矩阵直接使用其转置矩阵即可,计算转置矩阵的速度比计算逆矩阵的速度可快多了。
那么,怎么判断一个矩阵是否是正交矩阵呢?
根据定义,我们可以知道正交矩阵一定是一个方阵。
那么我们假设
M
\\textbfM
M是一个3×3的矩阵,推导过程如下图:
上面这个推导过程可以推导到更多维的正交矩阵。
也就是说,一个矩阵是正交矩阵的充要条件是首先它是一个方阵并且它的每一行均为单位向量,且各行互相垂直(点积为0)。
我们为什么要专门讨论正交矩阵?上面已经说了,正交矩阵可以非常快速的求到它的逆矩阵。后面的部分我们将会看到旋转矩阵其实就是一个正交矩阵,所以求旋转的逆变换过程是非常非常快速的。
根据上面的结论,我们很容易就能知道由标准正交基(长度为1的坐标系的x、y、z轴向量)构成的矩阵其实就是正交矩阵,我们后面在将一个坐标系中的点变换到另一个坐标系的时候,将会使用到这个知识点。
4.4 列矩阵
我们知道一个向量或者一个点写作矩阵可以有两种方式,一种是行矩阵,一种是列矩阵,如下:
对于同样一个3×3的变换矩阵
M
\\textbfM
M3×3,将向量或点写作行矩阵或者列矩阵得到的结果将会是完全不同的。
举个例子:
可以看到,向量或点写成行矩阵变换后的结果与写成列矩阵变换后的结果相比,不仅仅是行列矩阵的的区别,更重要的是里面的元素也是完全不同的。所以选择那一种书写方式就特别重要了。
在Unity3D中,选择的是将向量或点写成列矩阵的形式。
也就是说,在对向量或点进行变换时,应该将向量或点写在变换矩阵的右边。
我们以后不论是在写业务逻辑或者写Shader的过程中,如果需要进行坐标变换,一定要记住是将向量或点写在变换矩阵的右边。
举个例子:
可以看到,将向量或点写在变换矩阵的左边时,直接编译都不允许。
有同学可能会有疑问,上面例子中的pos不是只有3个元素吗,怎么能够与一个4×4的矩阵相乘?
上面其实我们没有讲到齐次坐标系,齐次坐标系没什么特别的,就是比普通的xyz坐标系多了一个维度w(因为3×3的矩阵无法表示平移变换,而4×4的变换矩阵可以表示所有变换,所以我们一般使用4×4的变换矩阵,为此我们也需要将向量或点扩充到4维)。
当一个向量写成齐次坐标时,其w分量=0;当一个点写成齐次坐标时,其w分量=1。
上面的代码中,Unity内部自动将我们的pos转换为齐次坐标了,最后一个元素强制设置为了0(所以需要注意的是,上面的代码其实是将pos当成一个向量而不是点来计算的)。
本来我想把矩阵的东西放在同一篇文章的,但是后来发现有点多,所以还是拆分成几篇文章了。下一篇我们讲讲平移、旋转、缩放矩阵是怎么推导出来的。
以上是关于Unity3D C#数学系列之矩阵基础的主要内容,如果未能解决你的问题,请参考以下文章
机器学习|数学基础Mathematics for Machine Learning系列之矩阵理论(16):向量和矩阵的极限
机器学习|数学基础Mathematics for Machine Learning系列之线性代数:矩阵的运算
机器学习|数学基础Mathematics for Machine Learning系列之矩阵理论(20):方阵函数
机器学习|数学基础Mathematics for Machine Learning系列之矩阵理论(20):方阵函数
机器学习|数学基础Mathematics for Machine Learning系列之矩阵理论(17):函数矩阵的微分和积分