一.向量
如图:
3D笛卡尔坐标系在3D笛卡尔坐标系中,A点在XYZ轴上对应的位置分别为OC,OD,OB,在X轴上,我们用X(蓝色部分)(1,0,0)表示长度为1的向量为单位向量(Y轴,Z轴以此类推,如图蓝色部分)。OA的向量就可以表示为{x,y,z};
在3D坐标系中,我们求取OA的长度,三角形OAE是一个直角三角形,所以OA^2 = OE^2 +AE^2(勾股定理,不要问我什么是是勾股定理,要问去问你们初中的数学老师),AE的长度就是A点在Y轴上的坐标,即Y,OE的长度 OE^2 = OC^2 +CE^2,而OC的长度就是A点对应X的坐标,CE的长度就对应Z轴上的坐标,所以,联合起来,我们求取OA的长度公式就是:|OA| =
取模这一过程叫做取OA的模。如果⼀个向量不是单位向量, ⽽我们把它缩放到1. 这个过程叫做标准化. 将⼀个向量进⾏标准化就是将它的缩为1; 也叫做单位化向量。
OA的单位向量其中xyz为A点对应XYZ轴的坐标。
二.向量的点乘
点乘只能发生在两个向量之间,且点乘时,两向量必须是单位向量,如果不是,需要将向量进行单位化后,再点乘,所以我们在两个向量点乘的时候,如果不是单位向量,我们必须先转化为单位向量,转化过程如上.
两单位向量点乘,最后得到的结果是两个向量之间的夹角,即余弦(cos值)
两个向量OA,OB如果OA和OB不是单位向量,先转化为单位向量,然后点乘,得到
得到夹角math3d 库中提供了关于点乘的API:
//1.m3dDotProduct3 函数获得2个向量之间的点乘结果;
float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
//2.m3dGetAngleBetweenVector3 即可获取2个向量之间夹⻆的弧度值;
float m3dGetAngleBetweenVector3(const M3DVector3f u,const M3DVector3f v);
三.向量的叉乘
两个不是单位向量可以相乘,得到的结果是一个新的向量,且该向量垂直于两个向量所在的平面(两条线确定一个平面,得到的向量,垂直这个平面,即V3垂直于V1和V2确定的平面)。你也可以理解为这个平面的法线。
OpenGL中针对向量叉乘也提供了对应的API:
//1.m3dCrossProduct3 函数获得2个向量之间的叉乘结果得到⼀个新的向量
void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v);
math3d库,有2个数据类型,能够表示⼀个三维或者四维向量。
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};
四.矩阵
1.单元矩阵:
对角线为1特点:
1)主对角线上数据都是1,其余元素都是0,即为单元矩阵
2)单位矩阵相乘满足交换法则,即:向量 X 单元矩阵 = 向量 X 1,不会发生任何变化
3) 向量与单元矩阵相乘的前提是:向量的列数 == 单元矩阵的行数
在空间有⼀个点A.使⽤xyz 描述它的位置. 此时让其围绕任意位置旋转⼀定⻆度后. 我们需要知道这个点的新的位置. 此时需要通过矩阵进⾏计算.因为新的位置的x 不单纯与原来的x还和旋转的参数有关. 甚⾄于y和z坐标有关.矩阵只有⼀⾏或者⼀列都是合理的. 只有⼀⾏或者⼀列数字可以称为向量. 也可以称为矩阵;
矩阵的声明:
//三维矩阵/四维矩阵的声明
typedef float M3DMatrix33f[9];
typedef float M3DMatrix44f[16];
在其他编程标准中, 许多矩阵库定义⼀个矩阵时,使⽤⼆维数组;OpenGL的约定⾥,更多倾向使⽤ ⼀维数组; 这样做的原因是: OpenGL 使⽤的是Column-Major(以列为主)矩阵排序的约定;
列优先矩阵排序 ⾏优先矩阵排序说明:
行优先矩阵:一行一行读取
列优先矩阵:一列一列读取
矩阵的点乘:条件必须满足两个矩阵的行列数都相等。流程图:
点乘流程图图片来自于 https://www.jianshu.com/p/be18310ccfad
叉乘:A*B,A的列数==B的行数
叉乘流程图图片来自于 https://www.jianshu.com/p/be18310ccfad
单元矩阵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);
在线性代数数学的维度,为了便于书写. 所以坐标计算. 都是从左往右顺序,进⾏计算. 如下列公式:
变换后顶点向量= V_local * M_model * M_view * M_pro
变换后顶点向量= 顶点 ✖ 模型矩阵 ✖ 观察矩阵 ✖ 投影矩阵;
数学思维在OpenGL 的维度. 如下列公式:
变换顶点向量= M_pro * M_view * M_model * V_local
变换顶点向量= 投影矩阵 ✖ 视图变换矩阵 ✖ 模型矩阵 ✖ 顶点
OpenGL思维矩阵左乘
1.从栈顶获取栈顶矩阵 复制到mTemp
2. 将栈顶矩阵mTemp 左乘mMatrix
3. 将结果放回栈顶空间⾥
代码段:
五.OpenGL变换数据概览
变换 应用
1.视图 制定观察者或照相机的位置
2.模型 在场景中移动物体
3.模型视图 描述视图和模型变换的二元性
4.投影 改变视窗体 的大小或重新设置它的形状
5.视口 这是一种伪变换,只是对窗口上的最终输出进行缩放
视觉坐标
笛卡尔坐标系:从观察者的角度来看,x轴和y轴的正方向分别指向右方和上方。z轴的正方向从原点指向使用者,而z轴的负方向则从观察者指向屏幕内部。 当我们利用OpenGL进行3D绘制时,就会使用笛卡尔坐标系。如果不进行任何变换,那么使用的坐标系将与刚刚描述的视觉坐标系相同。
视图变换
视图变换允许我们把观察点放在所希望的任何位置,并允许在任何方向上观察场景。确定视图变换就像在场景中放置照相机并让它指向某个方向。
模型变换
模型变换用于操纵模型和其中的特定对象。这些变换将对象移动到需要的位置,然后再对它们进行旋转和缩放。
投影变换
投影变换将在模型视图变换之后应用到顶点上,它将指定一个完成的场景(所有模型变换都已完成)是如何投影到屏幕上的最终图像。
正投影:所有多边形都是精确地按照指定的相对大小来在屏幕上绘制的。
透视投影:透视投影的特点是透视缩短,这种特性使得远处的物体看起来比进出同样大小的物体更小一些。
视口变换
当所有变换完成后,就得到了一个场景的二维投影,它将被映射到屏幕上某处的窗口上。这种到物理创口标的映射是我们最后要做的变换,称为视口变换。
模型视图矩阵
模型视图矩阵是一个4X4矩阵,它表示一个变换后的坐标系,我们可以用来放置对象和确定对象的方向。一个包含单个顶点数据的矩阵乘以模型视图矩阵后得到新的视觉坐标。OpenGL并不是将一个4X4矩阵表示为一个浮点值的二维数组,而是将它表示为一个由16个浮点值组成的单个数组。
奥秘之处,在于这16 个值表示空间中⼀个特定的位置; 这4列中,每⼀列都是有4个元素组成的向量,如果将⼀个对象所有的顶点向量 乘以这个矩阵,就能让整个对象变换到空间中给定的位置和⽅向。
网友评论