OpenGL--向量、矩阵、基础变换与矩阵堆栈

2020-07-17  本文已影响0人  HardCabbage

一、 向量

1.1 什么是向量

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

1.2什么是单位向量
在 X轴上的向量 (1,0,0),向量⻓度为1. 我们称为⻓度为1的向量为单位向量。 向量长度计算公式

如果⼀个向量不是单位向量,⽽我们把它缩放到1,这个过程叫做标准化。将⼀个向量进⾏标准化,也就是将它的长度缩为1,这个过程也叫做单位化向量;

1.3那么在OpenGL中是如何定义向量的呢?
//三维向量/四维向量的声明
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
};
向量的点乘
//1.m3dDotProduct3 函数获得2个向量之间的点乘结果;
float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
//2.m3dGetAngleBetweenVector3 即可获取2个向量之间夹⻆的弧度值;
 float m3dGetAngleBetweenVector3(const M3DVector3f u,const 
M3DVector3f v);
向量的叉乘
//1.m3dCrossProduct3 函数获得2个向量之间的叉乘结果得到⼀个新的向量
void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v); 

二、矩阵Matrix

2.1为什么需要矩阵

假设在空间有⼀个点,这个点使⽤x、y、z 描述它的位置,此时让其围绕任意位置旋转⼀定⻆度后,我们需要知道这个点的新的位置,此时我们就需要通过矩阵进⾏计算了。
为什么需要新的点位置就需要矩阵计算呢?
因为新的位置的x不单纯与原来的x有关系,而且还和旋转的参数有关,甚⾄于y和z坐标有关;矩阵只有⼀⾏或者⼀列都是合理的,只有⼀⾏或者⼀列数字可以称为向量,也可以称为矩阵;
-在其他的编程标准中,其他的矩阵库东哟时候使用的是二维数组,而OpenGL的约定里,更多倾向的是使用一维数组,这样做的主要原因是因为OpenGL使用的是Column-Major(以列为主)矩阵排序的约定(数学上叫做转置矩阵)。


截屏2020-07-17 17.08.26.png 截屏2020-07-17 17.08.30.png
//三维矩阵/四维矩阵的声明
typedef float M3DMatrix33f[9];
typedef float M3DMatrix44f[16];
2.2⼀个4*4矩阵是如何在3D空间中表示⼀个位置和⽅向的
截屏2020-07-17 17.11.18.png
2.3单元矩阵 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); 
  1. 从栈顶获取栈顶矩阵复制到 mTemp
  2. 将栈顶矩阵mTemp左乘mMatrix
  3. 将结果放回栈顶空间⾥;
    源代码
    inline void MultMatrix(const M3DMatrix44f mMatrix) {
            M3DMatrix44f mTemp;
            m3dCopyMatrix44(mTemp, pStack[stackPointer]);
            m3dMatrixMultiply44(pStack[stackPointer], mTemp, mMatrix);
            }

三、基础变换

3.1视图变换:指定观察者位置
3.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.3投影变换:改变视影体的大小和设置它的投影方式

四、矩阵堆栈

GLMatrixStack::GLMatrixStack(int iStackDepth = 64); 

//在堆栈顶部载⼊⼀个单元矩阵
void GLMatrixStack::LoadIdentity(void); 

//在堆栈顶部载⼊任何矩阵
//参数:4*4矩阵
void GLMatrixStack::LoadMatrix(const M3DMatrix44f m); 

//矩阵乘以矩阵堆栈顶部矩阵,相乘结果存储到堆栈的顶部
void GLMatrixStack::MultMatrix(const M3DMatrix44f); 

//获取矩阵堆栈顶部的值 GetMatrix 函数
//为了适应GLShaderMananger的使⽤,或者获取顶部矩阵的副本
const M3DMatrix44f & GLMatrixStack::GetMatrix(void); 

void GLMatrixStack::GetMatrix(M3DMatrix44f mMatrix);

//将当前矩阵压⼊堆栈(栈顶矩阵copy ⼀份到栈顶) 
void GLMatrixStack::PushMatrix(void); 

//将M3DMatrix44f 矩阵对象压⼊当前矩阵堆栈
void PushMatrix(const M3DMatrix44f mMatrix); 

//将GLFame 对象压⼊矩阵对象
void PushMatrix(GLFame &frame); 

//出栈(出栈指的是移除顶部的矩阵对象)
void GLMatrixStack::PopMatrix(void);
仿射变换
//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);
上一篇 下一篇

猜你喜欢

热点阅读