OpenGL的常用的库会封装了数学公式,
向量
在 3D 笛卡尔坐标系,⼀个顶点就是XYZ 坐标空间上的⼀个位置。⽽在空间中给定的⼀个位置恰恰是由⼀个单独的 XYZ 定义的. ⽽这样的 XYZ 就是向量。
在 X轴上的向量 (1,0,0). 向量⻓度为1,称为⻓度为1的向量为单位向量.
向量⻓度(向量的模)计算公式:
向量长度
如果⼀个向量不是单位向量, ⽽我们把它缩放到1。这个过程叫做标准化。将⼀个向量进⾏标准化就是将它的缩为1,也叫做单位化向量
OpenGL如何定义向量
- M3DVector3f表示⼀个三维向量(x,y,z)
- M3DVector4f表示⼀个四维向量(x,y,z,w)
一般w坐标设为1.0。x,y,z值通过除以w,来进⾏缩放。
//三维向量/四维向量的声明 , 本质是float类型的一唯数组
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
};
向量点乘
向量点乘表示两个向量相应元素的乘积的和
(x,y,z)* (a,b,c) = x * a + y * b + z * c
向量A(x,y,z)、B(a,b,c),向量A * 向量 B = |A||B|Cos(θ),|A|表示向量的模,θ表示向量A和向量B的夹角。
使⽤⼀个⾮零向量除以它的模(向量的⻓度), 就可以得到⽅向相同的单位向量。
math3d 库中提供了关于点乘的API
//1.m3dDotProduct3 函数获得2个向量之间的点乘结果;
float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
//2.m3dGetAngleBetweenVector3 即可获取2个向量之间夹⻆的弧度值;
float m3dGetAngleBetweenVector3(const M3DVector3f u,const
M3DVector3f v);
向量叉乘
2个向量之间叉乘就可以得到另外⼀个向量,新的向量会与原来2个向量定义的平⾯垂直。同时进⾏叉乘,不必为单位向量。
(x,y,z)* (a,b,c) = (x * a , y * b , z * c)
math3d 库中提供了关于叉乘的API
//1.m3dCrossProduct3 函数获得2个向量之间的叉乘结果得到⼀个新的向量
void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const
M3DVector3f v);
矩阵
空间中的正方形进行平移、旋转、缩放,需要对正方体中的每个顶点进行空间变化,通过矩阵可以很方便的进行计算。
opengl中使用列向量为主的排序
截屏2020-07-16 21.59.01.png
如果将图形中的顶点向量乘以这个矩阵,就能让整个图形变换到空间中给定的位置和⽅向。
单元矩阵 Matrix
//单元矩阵初始化⽅式①
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);
矩阵相乘不满足交换律,所有左乘和右乘是不同的。
OpengGL中,矩阵先进行平移、然后旋转与矩阵先旋转、然后平移得到最终的图形是不一样的。
截屏2020-07-16 22.08.39.png
opengl在进行投影变换时,要经过 model->view-> projection变换。
在线性代数中,顶点进行变换时。
截屏2020-07-16 22.27.35.png
但openGL是列矩阵为主的排序。所以实际上opengl是先将projection矩阵、view矩阵、model矩阵依次放入栈中。
变换顶点向量 = projection * view * model * local
变换顶点向量 = 投影矩阵 ✖ 视图变换矩阵 ✖ 模型矩阵 ✖ 顶点
截屏2020-07-16 22.11.15.png
OpenGL的GLMatrixStack矩阵堆栈有个MultMatrix方法,用于矩阵左侧
inline void MultMatrix(const M3DMatrix44f mMatrix) {
M3DMatrix44f mTemp;
m3dCopyMatrix44(mTemp, pStack[stackPointer]);
m3dMatrixMultiply44(pStack[stackPointer], mTemp, mMatrix);
}
- 从栈顶获取栈顶矩阵 复制到 mTemp
- 将栈顶矩阵 mTemp 左乘 mMatrix
- 将结果放回栈顶空间⾥;
视图变换
- 视图变换是应⽤到场景中的第⼀种变换, 它⽤来确定场景中的有利位置,在默认情况下, 透视投影中位于原点(0,0,0),并沿着 z 轴负⽅向进⾏观察 (向显示器内部”看过去”).
- 当观察者点位于原点(0,0,0) 时,就像在透视投影中⼀样.
- 视图变换将观察者放在你希望的任何位置.并允许在任何⽅向上观察场景, 确定视图变换就像在场景中放置观察者并让它指向某⼀个⽅向;
- 从⼤局上考虑, 在应⽤任何其他模型变换之前, 必须先应⽤视图变换. 这样做是因为, 对于视觉坐标系⽽⾔, 视图变换移动了当前的⼯作的坐标系; 后续的变化都会基于新调整的坐标系进⾏.
平移
void m3dTranslationMatrix44(M3DMatrix44f m, floata x, float y, float z);
旋转
m3dRotationMatrix44(m3dDegToRad(45.0), floata x, float y, float z);
缩放
void m3dScaleMatrix44(M3DMatrix44f m, floata xScale, float yScale, float zScale);
综合变换
void m3dMatrixMultiply44(M3DMatrix44f product, const M3DMatrix44f a, const M3DMatrix44f b);
网友评论