3D数学基础
要在计算机中模拟三维空间,就需要一些数学工具的支持,他们是进行计算机三维模拟的基础。一般情况下,为产生动画效果,需要记录空间中物体的位置,旋转,以及缩放信息,并不断改变这些值来实现此效果。
1.矢量
首先,需要一种能够存储空间位置信息的数据结构。本系统使用的是笛卡尔坐标系,即可以使用三个浮点数来表示空间中任意一点的位置,因此我选择使用三维矢量(Vector)来存储位置信息。矢量标量相乘,其效果是保留矢量的方向,同时缩放矢量的模。而三个轴上的缩放因子也可以不同,其称之为非统一缩放(nonuniform scaling)。
两个矢量a,b相加后会产生一个新的矢量,新矢量的每个分量为a与b中每个对应分量的和。用图形表示此运算的话,就是把a矢量的头连接至b矢量的尾,所得到的一个由a的尾延伸至b的头的矢量。矢量的减法等同于a与-b相加,也就是a与反转的b相加得到的结果。
矢量的模(公式4.1)是一个标量,表示矢量在空间中的长度,可以使用勾股定理计算矢量的模。
(4.1)
单位矢量标是长度为1的矢量,我们常用单位矢量表示模型表面的法线信息。
使用矢量的点积(公式4.2)可以判断两个矢量是否共线或垂直,或测试两个矢量是否大致方向相同或相反。
(4.2)
两个矢量的叉积(公式4.3)会产生一个垂直于原来两个矢量的新矢量。
(4.3)
在三维模拟程序中,常常需要实现平滑的动画效果,而游戏的模拟速度和渲染速度通常是分离的,所以在模拟时假设我们要从点A移动到点B,在fps为60的情况下,就需要计算两点间的60个中间点来渲染,才能得出平滑的动画效果,具体实现如公式4.4所示。
(4.4)
2.四元数
3x3矩阵是可以存储旋转数据的,但是其体积庞大(四元数4个浮点数,3x3矩阵9个浮点数),而且矩阵的插值计算是非常昂贵的。因为单位四元数可以存储三维空间的旋转操作,加上其相比与欧拉角及矩阵表达方式的优势,是本系统用于存储旋转信息的首选数据结构。
通常使用4个浮点数表示四元数。
若四元数p与q,分别存储了旋转P与Q,则p x q就表示了先旋转P在旋转Q。这里讲的乘法是与三维旋转应用有关的乘法,格拉斯曼积(Grassmann product),见公式4.5。
(4.5)
共轭四元数(公式4.6)通常写成q*,定义为矢量部分求反,标量部分不变。
(4.6)
由于表示三维旋转的四元数都是单位长度的,所以这种情况下,四元数的共轭与逆是相等的,所以说逆四元数(公式4.7)的计算比3x3矩阵的逆快了很多。
(4.7)
将矢量表示为四元数形式,即对于矢量,则为。因为旋转四元数都是单位长度的,因此可以使用共轭来代替逆四元数,如公式4.8所示。
(4.8)
若对旋转动画使用线性插值方法进行插值,则旋转动画不会以恒定的角速度进行的。因为其未考虑到四元数其实是四维超球上的点,所以需要使用球面线性插值(spherical linear interpolation)来得到平滑的结果,见公式4.9。
(4.9)
球面线性插值使用正弦与余弦在四维超球面的大圆上进行插值,所以插值的结果会以常数速率变化,符合系统的要求。
3.矩阵
矩阵是一种由M x N个标量组成的长方形数组。4x4矩阵可以同时表示旋转,平移,和缩放信息,是模拟程序表达物体变换数据的理想选择。下文中的矩阵都是列矩阵[13](column-major),下面的公式展示了一个3x3的列矩阵。
(4.10)
矩阵A与B的乘法表示为P=A x B,如公式4.11,若AB为变换矩阵,则P也是变换矩阵。使用P对某一点进行变换操作,等同于先用A变换,再用B变换的结果。注意矩阵的乘法不符合交换律,而且两个矩阵的内维相等时他们才可以相乘,即4x3矩阵不能相乘因为他们的内维3不等于4。
(4.11)
单位矩阵(公式4.12)与任何矩阵相乘,结果都和相乘矩阵相等,而且单位矩阵是方阵,即行和列数相等。
(4.12)
逆矩阵可以还原原始矩阵的变换,因为一个矩阵与它的逆相乘,结果必然是单位矩阵。公式4.13详细描述了逆矩阵的计算方法,此方法使用伴随矩阵辅助逆矩阵的计算。
(4.13)
转置矩阵(公式4.14)是把原来的矩阵以对角线为轴做进行反射操作,即原矩阵的行变成了列。
(4.14)
当点或矢量从三维延伸到四维,通常称之为齐次坐标[9]。在模拟程序中,会使用4x4矩阵作为基础数据结构,因为它可以同时存储位置(公式4.15),旋转(公式4.16),缩放(公式4.17)信息。在齐次坐标系中,表示位置时,通常把位置矢量的分量w设为1,而方向矢量的w设为0,因为方向矢量无需做平移操作,所以当其w为0时,会抵消4x4矩阵里存储的位置变换。
(4.15)
(4.16)
(4.17)