1、笛卡尔坐标
上学的时候我们都学过二维坐标系,其实就是二维笛卡尔坐标系,所以没啥好说的,只是有一点要注意,OpenGL也就是Unity默认的坐标系是以左下角为原点,DirectX是以左上角为原点。如下图:
我们重点要面对的是三维笛卡尔坐标系,如下图:
3个坐标轴被称为该坐标系的基矢量,3个坐标轴互相垂直,长度为1,这样的基矢量被称为标准正交基,如果长度不为1,被称为正交基。当然,坐标轴方向也不是固定的,涉及到z轴向里为正还是向外为正,也就有了大家熟知的左手坐标系和右手坐标系。
虽然对开发者来说,左手和右手坐标系没有优劣之分,但我们要清楚当前平台的坐标系准则,不然空间运算就可能是错的,OpenGL是右手坐标系,DirectX是左手坐标系,而对于Unity,模型空间和世界空间是左手坐标系,向里为z轴正向,而观察空间,也就是以摄像机为原点的空间,用的是右手坐标系,摄像机前向是z轴负方向,注意观察空间是看不到的,只有计算中才能遇到。
2、点和矢量
点(point)是一个位置,没有大小的概念。二维坐标P = (X, Y),三维坐标P = (X, Y, Z)。
矢量(vector),也被称为向量,是空间中包含了模(magnitude)和方向(direction)的有向线段,比如速度。与之相对的是标量,只有模,没有方向,比如距离。
矢量的运算,假设矢量v = (x, y, z),各种运算如下:
1)矢量和标量的乘除
2)矢量的加减
它们的几何意义如图:
3)矢量的模
4)单位矢量
很多情况下,我们只关心矢量的方向而不是模。比如光照模型中,往往需要知道法线方向和光源方向,这种情况下我们不关心矢量有多长,这样就需要计算单位矢量。单位矢量指的是模为1的矢量,也被称为被归一化的矢量(normalized vector),而把非零矢量转换为单位矢量的过程被称为归一化。计算单位矢量公式如下:
5)矢量的点积
代码中用dot(a, b)来表示。
点积的几何意义
点积几乎用到了图形学的各个方面,其中一个就是投影。有一个单位矢量a和长度不限的矢量b。那么a与b的点积就是b在a方向上的有符号的投影。投影的结果是有符号的,如下图:
如果a不是单位矢量,那么a与b的点积等同于b在a上的投影,再乘以a的长度。
点积的几种数学公式:
下面要重点介绍点积的另一种表达式:
推导很容易,这里不加介绍。从这个公式可以看出两个向量的夹角对于点积结果的影响,小于90度为正,等于90度为0,大于90度为负。还可以用反余弦求出两个向量的夹角。
6)矢量的叉积
相信上学时都学过,这里直接上公式:
注意:
叉积的几何意义:
两个矢量叉积会得到一个同时垂直于这两个矢量的新矢量
我们知道两个方向互不平行的矢量可以确定一个平面,所以叉积最常见的应用就是计算垂直于一个平面的矢量,我们后面会在顶点法线,切线那里用到。
3、矩阵
如果还没把上学学的东西都还给老师的话,就跟我回忆一下吧。
矢量可以看成是nx1的列矩阵或1xn的行矩阵,其中n对应了矢量的维度。把矢量和矩阵联系在一起是为了让矢量像矩阵一样一起参与矩阵运算。这在空间变换中非常有用。
1)矩阵的运算
矩阵和标量的乘法:
矩阵和矩阵的乘法:
假设矩阵A的大小是4x2,B的大小是2x4,计算C = A x B,则C的大小是4x4。
其中:
也就是对应的行乘以对应的列。
矩阵乘法的一些表达式:
2)特殊矩阵
a、方块矩阵
简称方阵,就是行和列相等的矩阵。如果在方阵中除了对角线上的元素其他元素都是0,则成为对角矩阵。
b、单位矩阵
对角线元素都是1的对角矩阵就是单位矩阵。用 I 来表示。例如3x3的单位矩阵如下:
MI = IM = M
c、转置矩阵
d、逆矩阵
不是所有的矩阵都有逆矩阵,比如零矩阵,首先该矩阵必须是个方阵。M的逆矩阵表示为
,它们满足一个公式:
如果一个矩阵有逆矩阵,我们就说它是可逆的或者非奇异的,相反则是不可逆的或奇异的。
逆矩阵的公式:
这里有个逆矩阵的几何意义,矩阵是可以表示变换的,逆矩阵则可以还原这个变换。比如用矩阵M对向量v进行了一次变换,如果我们想还原回v,只需要对变换结果乘以M的逆矩阵,公式如下:
f、正交矩阵
如果矩阵M和它的转置矩阵的乘积是单位矩阵的话,矩阵M就是正交的,公式为:
所以和上面的逆矩阵相比,我们发现:
这个公式很有用,因为求解一个矩阵的逆矩阵计算量很大,但转置矩阵很容易,所以如果我们知道该矩阵是正交矩阵,那用转置矩阵就可以当逆矩阵了。那如何判断一个矩阵是正交矩阵呢。用计算公式求解当然可以,但同样很麻烦,让我们看看它的几何意义。根据正交矩阵的定义,我们有:
我们可以把(
)当成M每一行和M转置每一列的向量,所以就有了等式:
我们从上面的等式中发现了些规律:
一、
和自己点积的时候都为1,还记得向量和自己点积等于其模的平方的公式吧,不记得就再看看上面,模的平方为1,那模就是1,所以它们都是单位矩阵。
二、它们之间两两点积都得0,说明它们互相都垂直。
而这两个规律对每一列同样适用,因为M是正交矩阵,其转置也是正交矩阵。这两个规律说明什么,又是单位向量,又是彼此垂直,这不就是我上面提到的标准正交基吗。所以我们得出结论,正交矩阵的行与行之间,列与列之间分别构成了一组标准正交基。
这在空间转换中很有用,如果这些基矢量是一组标准正交基的话,那我们就可以直接用其转置矩阵来得到其逆矩阵了。
3)行矩阵还是列矩阵
我们都知道,向量是可以作为行矩阵或列矩阵的,本身没有区别,但和矩阵相乘就有区别了,因为我们要用到各种空间转换会用到向量与矩阵相乘。比如v代表的1x3的向量和M代表的3x3的矩阵相乘,如果vM那结果是1x3的矩阵,如果Mv(v变成列矩阵),那结果就是3x3的矩阵。我们往往需要的是后者,所以在Unity中,常规做法是把矢量放在矩阵的右边,即Mv。例如:
CBAv = (C(B(Av)))
表示先对v使用A变换,再用B变换,再用C变换,是从右往左的顺序。所以如无特殊情况,我们往往使用向量的列矩阵表达式。