矩阵基础
矩阵基础
我们在学习OpenGL中,总是要对各种坐标变换进行计算。计算的部分当然是和计算机最搭配,但我们也需要了解些简单的基础知识,知道怎么让计算机完成那部分计算,才能有效的完成开发需求。OpenGL库中有个Math3d的组件就可以帮助我们做到这些。
向量
三维空间中的一个点
,也是一个向量
。例如:(x, y, z)
- 表示一个顶点的位置(
点
); - 还表示了两个重要的值(
向量
):- 一个方向(坐标原点到这个点坐标的一条带方向的箭头线段);
- 一个数量(坐标原点到这个点坐标的长度);

单位向量(unit vector):长度为1的向量叫单位向量。
表准化(normalization):如果一个向量的长度不是单位向量,而我们将它缩放到1,就叫做标准化。
在math3d
库中,使用M3DVector3f
表示一个三维向量(x, y, z)
,使用M3DVector4f
表示一个四维向量(x, y, z, w)
。典型情况下w
坐标设为1.0
。x
、y
和z
值通过除以w来进行缩放,而除以1.0
则本质上不改变xyz的值。
点乘
向量可以通过加减运算来进行缩放,也可以对xyz分量单独进行缩放。
两个(三分量)单位向量之间的点乘运算将得到一个标量(普通的单独数据,用来表示大小和特定量),它表示两个向量之间的夹
角。要进行这种运算,这两个向量必须为单位长度,而返回的结果将在-1.0到+1.0范围之内。这个数字实际上就是这两个向量之间夹角的余弦值。

我们可以使用math3d库中的函数来进行计算:
//获得两个向量之间的点乘结果
float m3dDotProduct3(const M3DVector3f u, const M3DVector3f v);
//获得这个角的弧度值
float m3dGetAngleBetweenVectors3(const M3DVector3f u,const M3DVector3f v);
实际点乘结果是一个在-1和+1之间的值,它代表这两个单位向量之间夹角的余弦值。通过它可以知道两个向量的相似性,利用点乘可判断一个多边形是面向摄像机还是背向摄像机。向量的点乘与它们夹角的余弦成正比,因此在聚光灯的效果计算中,可以根据点积来得到光照效果,如果点积越大,说明夹角越小,则物体离光照的轴线越近,光照越强。
叉乘
两个向量之间的叉乘结果是另外一个向量。这个向量与原来两个向量定义的平面垂直。要进行叉乘,这两个向量都不必是单元向量。

math3d库中的叉乘函数:
void m3dCrossProduct3 (M3DVector3f result,
const M3DVector3f u,
const M3DVector3f v);
叉乘是不满足交换律的。计算是要注意顺序,V3是V2和V1叉乘的结果,如果反过来,V1和V2进行叉乘,那么V3会指向之前相反的方向。
矩阵
矩阵就是一组排列在同一行和列中的数字。一个矩阵不必是正方形的,但是矩阵中每一行(或每一列) 的元素数都必须和其他行(或列)的元素数相同。

矩阵之间可以进行乘法和加法运算。也能与向量或标量相乘。
逐行遍历时叫行优先排序,逐列遍历时为列优先排序。这两种矩阵互为转置矩阵。行优先排序主要为了与编程语言契合,因为C、C++中的矩阵是按行优先进行存储的。而采用列优先排序则是与数学上大多数人的向量使用习惯保持一致, 因为在大多数数学的学科中都是使用列向量,行向量则是以列向量的转置的方式实现的,也就是说在应用上与用户保持一致。

矩阵的前3列的前3个元素分别表示在XYZ轴上的方向。矩阵的最后一行都为0,只有最后一个元素为1表示为列矩阵,0表示为行矩阵。

单元矩阵
一个向量乘以一个单位矩阵结果还是这个向量。就相当于乘以1一样,没有什么变化。

math3d库中的创建单位矩阵的函数:
void m3dLoadIdentity44(M3DMatrix44f m);
矩阵变换
-
平移(让顶点沿着某个轴或者多个轴进行平移。)
void m3dT ranslationMatrix44(M3DMatrix44f m, float x, float y, float z);
-
旋转
m3dRotationMatrix44(M3DMatrix44f m, float angle, float x, float y, float z);
-
缩放
M3DMatrix44f m; void m3dScaleMatrix44(M3DMatrix44f m, float xScale, float yScale, float zScale);
-
综合多种效果需要用到矩阵相乘
void m3dMatrixMultiply44(M3DMatrix44f product, const M3DMatrix44f a, const M3DMatrix44f b);