向量
在3D笛卡尔坐标系中,⼀个顶点就是XYZ坐标空间上的⼀个位置。⽽在空间中给定的⼀个位置,恰恰是由⼀个单独的XYZ 定义的,⽽这样的XYZ 就是向量(在数学思维中,⼀个顶点也就是⼀个向量)。

单位向量
在X轴上的向量 (1,0,0),向量⻓度为1,我们称⻓度为1的向量为单位向量。
向量⻓度(也叫向量的模)的计算公式如下所示:

如果⼀个向量不是单位向量,⽽我们把它缩放到1, 这个过程叫做标准化。将⼀个向量进⾏标准化就是将它的长度缩为1,也叫做单位化向量。
OpenGL中的向量定义(math3d库)
math3d库中,有两种数据类型能够表示一个三维或四维向量:
- M3DVector3f:表示⼀个三维向量(x,y,z);
- M3DVector4f:表示一个四维向量(x,y,z,w);
在典型情况下,w(缩放因子)坐标设为1.0。x,y,z值通过除以w,来进⾏缩放。⽽除以1.0在本质上不改变x,y,z值。
//三维向量/四维向量的声明
typedef float M3DVector3f[3];
typedef float M3DVector4f[4];
//声明⼀个三维向量 M3DVector3f:类型 vVector:变量名
M3DVector3f vVector;
//声明⼀个四维向量并初始化⼀个四维向量
M3DVector4f vVertex = {0,0,1,1};
//声明⼀个三分量顶点数组,例如⽣成⼀个三⻆形
M3DVector3f vVerts[] = {
-0.5f,0.0f,0.0f,
0.5f,0.0f,0.0f,
0.0f,0.5f,0.0f
};
向量点乘(dot product)
向量可以进⾏加法、减法计算,但是向量⾥有⼀个在开发中使⽤价值⾮常⾼的操作,叫做点乘。点乘只能发⽣在2个向量之间进⾏,2个(三维向量)单位向量之间进⾏点乘运算将得到⼀个标量(不是三维向量,是⼀个标量)。它表示两个向量之间的夹⻆。
- 前提条件:2个向量必须为单位向量;
- 动作:2个三维向量之间进⾏点乘;
- 结构:返回⼀个[-1,1]范围的值,这个值其实就是夹⻆的cos值(余弦值);

//math3d 库中提供了关于点乘的API
//1.m3dDotProduct3 函数获得2个向量之间的点乘结果;
float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
//2.m3dGetAngleBetweenVector3 即可获取2个向量之间夹⻆的弧度值;
float m3dGetAngleBetweenVector3(const M3DVector3f u,const M3DVector3f v);
如何单位化向量?
- (x/|xyz|, y/|xyz|, z/|xyz|);
使⽤⼀个⾮零向量除以它的模(向量的⻓度),就可以得到⽅向相同的单位向量。
向量叉乘(cross product)
两个个向量之间叉乘可以得到另外⼀个向量,新的向量(法向量)会与原来2个向量定义的平⾯垂直。同时进⾏叉乘,不必为单位向量。
- 前提:两个普通向量;
- 动作:向量与向量叉乘;
- 结果:向量(垂直于原来2个向量定义的平⾯的向量);

//math3d 库中提供了关于叉乘的API
//1.m3dCrossProduct3 函数获得2个向量之间的叉乘结果得到⼀个新的向量
void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v);
矩阵(Matrix)
矩阵只有⼀⾏或者⼀列都是合理的,只有⼀⾏或者⼀列数字可以称为向量,也可以称为矩阵。
//三维矩阵/四维矩阵的声明
typedef float M3DMatrix33f[9];
typedef float M3DMatrix44f[16];

- 在其他编程标准中,许多矩阵库定义⼀个矩阵时,使⽤⼆维数组;
- OpenGL的约定⾥,更多倾向于使⽤⼀维数组。 这样做的原因是:OpenGL 使⽤的是Column-Major(以列矩阵为主)矩阵排序的约定;

如上图所示,就可以知道一个4*4矩阵是如何在3D空间中表示一个位置和方向的。如果将⼀个对象所有的顶点向量乘以这个矩阵,就能让整个对象变换到空间中给定的位置和⽅向.
列向量
矩阵的最后⼀⾏都为0,只有最后⼀个元素为1。
单元矩阵
//单元矩阵初始化⽅式①
GLFloat m[] = {
1,0,0,0, //X Column
0,1,0,0, //Y Column
0,0,1,0, //Z Column
0,0,0,1 // Translation
}
// 单元矩阵初始化⽅式 ②
M3DMatrix44f m = {
1,0,0,0, //X Column
0,1,0,0, //Y Column
0,0,1,0, //Z Column
0,0,0,1 // Translation
}
//单元矩阵初始化⽅式③
void m3dLoadIdentity44f(M3DMatrix44f m);
将⼀个向量 ✖ 单元矩阵,就相当于⼀个向量✖1, 不会发⽣任何改变。

线性代数中的单元矩阵
在线性代数数学的维度,为了便于书写,所以坐标计算都是从左往右顺序进⾏计算,如下列公式:
变换后顶点向量 = V_local(顶点) * M_model(矩阵模型) * M_view(矩阵模型) * M_pro(投影矩阵);

OpenGL中的单元矩阵
在OpenGL 的维度,如下列公式:

矩阵左乘
//1. 从栈顶获取栈顶矩阵 复制到 mTemp
//2. 将栈顶矩阵mTemp左乘 mMatrix
//3. 将结果放回栈顶空间⾥;
inline void MultMatrix(const M3DMatrix44f mMatrix) {
M3DMatrix44f mTemp;
m3dCopyMatrix44(mTemp, pStack[stackPointer]);
m3dMatrixMultiply44(pStack[stackPointer], mTemp, mMatrix);
}
网友评论