一、向量
1.概念
在3D笛卡尔坐标系,基本上一个顶点就是XYZ坐标空间上的一个位置,而在空间中给定的一个位置,恰恰是由一个单独的XYZ定义的,而这样的XYZ就是向量;
在X轴上的向量(1,0,0),向量长度为1,我们称为长度为1的向量为单位向量。
向量⻓度(向量的模)计算公式:
如果⼀个向量不是单位向量, ⽽我们把它缩放到1,这个过程叫做标准化。将⼀个向量进⾏标准化就是将它的缩为1; 也叫做单位化向量;

2.OpenGL中如何定义向量(math3d库)
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};
//声明⼀个三分量顶点数组,例如⽣成⼀个三⻆形
//M3DVector3f vVerts[] = {
-0.5f,0.0f,0.0f,
0.5f,0.0f,0.0f,
0.0f,0.5f,0.0f
};
3.向量点乘
向量可以进⾏ 加法,减法计算. 但是向量⾥有⼀个在开发中使⽤价值⾮常⾼的操作,叫做
“点乘(dot product)” .点乘只能发⽣在2个向量之间进⾏;
2个(三维向量)单元向量 之间进⾏点乘运算将得到⼀个标量(不是三维向量,是⼀个标量).
它表示两个向量之间的夹⻆;
前提条件: 2个向量必须为单位向量;
动作: 2个三维向量之间进⾏点乘
结构: 返回⼀个[-1,1]范围的值. 这个值其实就是 夹⻆的cos值(余弦值)
如何单位化向量?
(x/|xyz|, y/|xyz|, z/|xyz|);
使⽤⼀个⾮零向量除以它的模(向量的⻓度), 就可以得到⽅向相同的单位向量;

math3d 库中提供了关于点乘的API
//1.m3dDotProduct3 函数获得2个向量之间的点乘结果;
float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
//2.m3dGetAngleBetweenVector3 即可获取2个向量之间夹⻆的弧度值;
float m3dGetAngleBetweenVector3(const M3DVector3f u,const
M3DVector3f v);
4.向量叉乘
math3d 库中提供了关于叉乘的API
//1.m3dCrossProduct3 函数获得2个向量之间的叉乘结果得到⼀个新的向量
void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const
M3DVector3f v);
二、矩阵
1.概念
假设, 在空间有⼀个点.使⽤ xyz 描述它的位置. 此时让其围绕任意位置旋转⼀定⻆度
后. 我们需要知道这个点的新的位置. 此时需要通过矩阵进⾏计算;
为什么?
因为新的位置的x 不单纯与原来的x还和旋转的参数有关. 甚⾄于y和z坐标有关;

矩阵只有⼀⾏或者⼀列都是合理的. 只有⼀⾏或者⼀列数字可以称为向量. 也可以称为矩阵;
2.代码参考
//三维矩阵/四维矩阵的声明
typedef float M3DMatrix33f[9];
typedef float M3DMatrix44f[16];
在其他编程标准中, 许多矩阵库定义⼀个矩阵时,使⽤⼆维数组;
OpenGL的约定⾥,更多倾向使⽤ ⼀维数组; 这样做的原因是: OpenGL 使⽤的是Column-Major(以列为主)矩阵排序的约定;
⼀个4*4矩阵是如何在3D空间中表示⼀个位置和⽅向的
列向量进⾏了特别的标注:矩阵的最后⼀⾏都为0,只有最后⼀个元素为1
如果将⼀个对象所有的顶点向量 乘以这个矩阵,就能让整个
对象变换到空间中给定的位置和⽅向;
3.单元矩阵
将⼀个向量 ✖ 单元矩阵 ,就相当于⼀个向量✖1. 不会发⽣任何改变;
3.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);
3.2单元矩阵(线性代数角度)
在线性代数数学的维度,为了便于书写. 所以坐标计算. 都是从左往右顺序,进⾏计算. 如下
列公式:
变换后顶点向量 = V_local * M_model * M_view * M_pro
变换后顶点向量 = 顶点 ✖ 模型矩阵 ✖ 观察矩阵 ✖ 投影矩阵;
3.3单元矩阵(OpenGL角度)
在OpenGL 的维度. 如下列公式:
变换顶点向量 = M_pro * M_view * M_model * V_local
变换顶点向量 = 投影矩阵 ✖ 视图变换矩阵 ✖ 模型矩阵 ✖ 顶点
3.4矩阵左乘

1. 从栈顶获取栈顶矩阵 复制到 mTemp
2. 将栈顶矩阵 mTemp 左乘 mMatrix
3. 将结果放回栈顶空间⾥;
3.5代码段

代码段-顶点着色器(glsl)

三、变换
1.视图变换
视图变换是应⽤到场景中的第⼀种变换, 它⽤来确定场景中的有利位置,在默认情况下, 透视
投影中位于原点(0,0,0),并沿着 z 轴负⽅向进⾏观察(向显示器内部”看过去”).
当观察者点位于原点(0,0,0) 时,就像在透视投影中⼀样.
视图变换将观察者放在你希望的任何位置.并允许在任何⽅向上观察场景, 确定视图变换就像
在场景中放置观察者并让它指向某⼀个⽅向;
从⼤局上考虑, 在应⽤任何其他模型变换之前, 必须先应⽤视图变换. 这样做是因为, 对于
视觉坐标系⽽⾔, 视图变换移动了当前的⼯作的坐标系; 后续的变化都会基于新调整的坐标
系进⾏.
2.模型变换
2.1概念
模型变换: ⽤于操纵模型与其中某特定变换. 这些变换将对象移动到需要的位置. 通过旋
转,缩放,平移.



2.2代码段
平移
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);
3.投影变换

透视投影 正投影
4.仿射变换
4.1概念
仿射变换可以通过一系列的原子变换的复合来实现,包括:平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和剪切(Shear)。
4.2代码段
//Rotate 函数angle参数是传递的度数,⽽不是弧度
void MatrixStack::Rotate(GLfloat angle,GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Translate(GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Scale(GLfloat x,GLfloat y,GLfloat z);
网友评论