2020-07-15 OpenGL 行列矩阵/视图变换/矩阵堆栈

229 阅读4分钟

相关概念

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

  • 单位向量:向量长度为1 就是单位向量,如在X轴上的向量(1,0,0)

  • 单位向量化:如果一个向量不是单位向量,而我们把它缩放到1,这个过程就叫做标准化。将一个向量进行标准化就是将它缩为1,也叫做单位向量化

  • 向量点乘:点乘只能发生在两个向量之间,且点乘时,两向量必须是单位向量,如果不是,需要将向量进行单位化后,再点乘;点乘得到的是两个向量之间的夹角的余弦值 即 cosα,范围在[-1, 1]之间,是一个标量

  • 向量叉乘:两个向量之间叉乘得到结果同样是一个向量,且该向量垂直于两个向量所构成的平面;由于结果与两向量构成平面垂直,也可以理解为得到的结果是该平面的法线

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
};

向量与矩阵应用场景与相关方法介绍

  • 向量点乘
    float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
    
    返回的是[-1,1]之见的值,代表这两个向量的余弦值。
    float m3dGetAngleBetweenVector3(const M3DVector3f u,const M3DVector3f v);
    
    返回两个向量之间夹角的弧度值。
  • 向量叉乘
    void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v);
    
    

行矩阵/列矩阵

OpenGL矩阵定义

typedef float M3DMatrix33f[9];// 3x3矩阵
typedef float M3DMatrix44f[16];// 4x4矩阵

单元矩阵初始化

// 方式一:
GLFoat m[] = {
  1, 0, 0, 0,      // X 列
  0, 1, 0, 0,      // Y 列
  0, 0, 1, 0,      // Z 列
  0, 0, 0, 1,      // Translation
}
// 方式二:
M3DMatrix44f m = {
  1, 0, 0, 0,      // X 列
  0, 1, 0, 0,      // Y 列
  0, 0, 1, 0,      // Z 列
  0, 0, 0, 1,      // Translation
}
// 方式三:
void m3dLoadIdentity44f(M3DMatrix44f m);

OpenGL变换【视图变换,模型变换】

视图变换:指定观察者位置。 应用到场景中的第一种变换,默认情况下,透视投影中位于原点(0,0,0),并沿着 z 轴负方向进⾏观察 (向显示器内部“看过去”)。 视图变换将观察者放在你希望的任何位置。并允许在任何⽅向上观察场景,确定视图变换就像在场景中放置观察者并让它指向某一个方向。 从⼤局上考虑,在应⽤任何其他模型变换之前, 必须先应⽤视图变换。这样做是因为,对于视觉坐标系⽽言,视图变换移动了当前的工作的坐标系,后续的变化都会基于新调整的坐标系进⾏

案例 使用矩阵的方式实现正方形移动

//平移
inline void m3dTranslationMatrix44(M3DMatrix44f m, float x, float y, float z)
{ m3dLoadIdentity44(m); m[12] = x; m[13] = y; m[14] = z; }

//旋转
void m3dRotationMatrix44(M3DMatrix44f m, float angle, float x, float y, float z);

//缩放
inline void m3dScaleMatrix44(M3DMatrix44f m, float xScale, float yScale, float zScale)
    { m3dLoadIdentity44(m); m[0] = xScale; m[5] = yScale; m[10] = zScale; }

模型变换

矩阵堆栈 相关方法介绍

矩阵堆栈的使用

案例

// GLMatrixStack类 这个类的构造函数允许指定堆栈的最大深度,默认的堆栈深度为64.
// 同时这个矩阵堆栈在初始化时,已经在堆栈中包含了单位矩阵。
GLMatrixStack::GLMatrixStack(int iStackDepth = 64);

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

// 在堆栈顶部载入任何矩阵
void GLMatrixStack::LoadMatrix(const M3DMatrix44f m);

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

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