美文网首页
OpenGL 矩阵操作

OpenGL 矩阵操作

作者: 君幸食j | 来源:发表于2020-08-21 17:23 被阅读0次

向量

1.png

(x,y,z) 既能表示坐标空间中的一个位置,还能表示一个向量。3个值 (x,y,z)组合起来表示两个重要的值,方向和数量。例如,x轴就是向量 (1,0,0),在x方向为+1,而在y方向和z方向则为0。

math3d库有两个数据类型,能够表示⼀个三维或者四维向量。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;

//声明并初始化一个四分量向量
M3DVector4f vVertex = {0.0f,0.0f,1.0f,1.0f};

//声明一个三分量顶点数组,例如生成一个三角形
M3DVector3f vVerts[] = {-0.5f,0.0f,0.0f,                  
                         0.5f,0.0f,0.0f,                                                     
                         0.0f,0.5f,0.0f};

点乘 2.png

  • 实现点乘⽅法:点乘运算返回2个向量之间的夹⻆
  • ⽅法1:返回的是-1,1之间的值。它代表这个2个向量的余弦值。
float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v);
  • ⽅法2:返回2个向量之间的弧度值。
float m3dGetAngleBetweenVector3(const M3DVector3f u,const M3DVector3f v);

叉乘

3.png

叉乘运算结果返回⼀个新的向量,这个新的向量与原来的2个向量垂直

void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v);

矩阵

矩阵是一组排列在统一的行和列中的数字,用程序设计语言来说就一个二维数组,矩阵中的每一行(或每一列)的元素都必须和其他行(或列)的元素数相同。 4.png

矩阵之间可以进行乘法和加法,也能与向量或者标量相乘。标量就是一个普通的单独数据,用来表示大小和特定量。

typedef float M3DMatrix33f[9];
typedef float M3DMatrix44f[16];

理解变换

把3D数据“压扁”成2D数据的处理过程叫做投影,投影中出现的透视变换就是OpenGL中的一种变换。变换还允许我们旋转、移动、伸展、收缩或扭曲对象。一般渲染一个3D图形,会发生3种类型的几何变换。

变换 应用
视图 指定观察者或照相机的位置
模型 在场景中移动物体
模型视图 描述视图和模型变换的二元性
投影 改变视景体的大小和设置它的投影方式
视口 这是一种伪变换,只是对窗口上的最终输出进行缩放

视觉坐标

视觉坐标是一个虚拟的固定坐标系,通常作为参考坐标系使用。视觉坐标是相对于观察者的视角而言的,可以视为“绝对的”屏幕坐标。 5.png

视图变换

视图变换允许我们把观察点放在任何位置,并允许在任何方向上观察场景。确定视图变换就像在场景中放置照相机并让它指向某个方向。在应用其他模型变换前,必须先应用视图变换。

模型变换

模型变换用于操纵模型和其中的特定对象,平移、旋转或缩放对象。


6.png
7.png

模型视图的二元性

将对象向后移动和将参考坐标系向前移动在视觉上没有区别,视图变换和模型变换一般是结合在一起的。把这两种变换在变换管线中进行组合,成为一个单独的矩阵,即模型视图矩阵。 8.png

投影变换

投影变换将在模型视图变换之后应用到顶点上。这种投影实际上定义了视景体并创建了裁剪平面。分为正投影(或平行投影)和透视投影,正投影大多绘制2D图形,透视投影都应用在3D图形。 9.png

视口变换

把一个场景的二维投影映射到物理窗口称为视口变换,视口变换会将”规范化“设备坐标重新映射到窗口坐标上。

模型视图矩阵

模型视图矩阵是一个 4 x 4 矩阵,它表示一个变换后的坐标系,我们可以用来放置对象和确定对象的方向。可以将单个顶点数据乘以模型视图矩阵得到新的视觉坐标。 10.png

矩阵分为行矩阵和列矩阵。

  • 转置矩阵:将⾏矩阵A的换成同序列列得到的矩阵,叫做A的转换矩阵。计为AT。

  • 矩阵转置,其实就是⾏列互换。有很多地⽅都⽤到。⽐如数学、程序语⾔、计算机数据结构中 11.png
  • ⼀个4*4矩阵是如何在3D空间中表示⼀个位置和⽅向的

  • 列向量进⾏了特别的标注:矩阵的最后⼀⾏都为0,只有最后⼀个元素为1 12.png

平移

平移矩阵将顶点沿着3个坐标轴中的一个或多个进行平移。 13.png

在math3d库调用函数如下:

void m3dTranslationMatrix44(M3DMatrix44f m, float x, float y, float z);

旋转

旋转矩阵将一个对象沿着3个坐标轴中的一个或者任意向量进行旋转。 14.png

在math3d库调用函数如下:

m3dRotationMatrix44(M3DMatrix44f m, float angle, float x, float y, float z);

缩放

缩放矩阵沿着3个坐标轴方向按照指定因子放大或缩小所有顶点,以改变对象的大小。 15.png

在math3d库调用函数如下:

void m3dScaleMatrix44(M3DMatrix44f m, float xScale, float yScale, float zScale);

综合变换

将以上变换结合,可以在math3d库调用以下函数将两个矩阵相乘。需要注意的是,矩阵相乘是有顺序的。例如,用一个旋转矩阵乘以一个平移矩阵,与用一个平移矩阵乘以一个旋转矩阵是不同的。

void m3dMatrixMultiply44(M3DMatrix44f product, const M3DMatrix44f a, const M3DMatrix44f b);

变换管线

16.png

首先,顶点将被视为一个 1x4 矩阵,其中前3个值为x,y和z坐标。第4个数字是一个缩放因子,可以手动进行设置。这就是w坐标,默认为1.0,一般很少去直接修改这个值。然后,顶点将乘以模型视图矩阵,生成变换的视觉坐标。随后,视觉坐标再乘以投影矩阵,生成裁剪坐标。裁剪坐标位于+/-1.0单位坐标系内。将有效地将所有位于这个裁剪空间之外的数据消除掉。裁剪坐标随后再除以w坐标,生成规范化的设备坐标。其中w值可能会被投影矩阵或模型视图矩阵修改,这取决于所发生的变换。透视除法将作为图元装配过程的一部分进行。最后,坐标三元组将通过视口变换被映射到2D平面上。这项操作也是由一个矩阵来表示的,但不能直接指定或者修改这个矩阵。OpenGL 将在内部根据指定的 glViewport 值来设置这个矩阵。

使⽤矩阵堆栈

//类型
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);
矩阵压栈出栈流程.png

仿射变换

GLMatriStack类也内建了对创建旋转、平移和缩放矩阵的支持。

//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);

使⽤照相机(摄像机) 和 ⻆⾊帧 进⾏移动

class GLFrame 
{ 
 protected: 
 M3DVector3f vOrigin; // Where am I? 
 M3DVector3f vForward; // Where am I going? 
 M3DVector3f vUp; // Which way is up?
} 
//将堆栈的顶部压⼊任何矩阵
void GLMatrixStack::LoadMatrix(GLFrame &frame); 

//矩阵乘以矩阵堆栈顶部的矩阵。相乘结果存储在堆栈的顶部
void GLMatrixStack::MultMatrix(GLFrame &frame); 

//将当前的矩阵压栈
void GLMatrixStack::PushMatrix(GLFrame &frame); 

相关文章

  • OpenGL 矩阵操作

    矩阵堆栈 //类型GLMatrixStack::GLMatrixStack(int iStackDepth = 6...

  • OpenGL 矩阵操作

    向量 (x,y,z) 既能表示坐标空间中的一个位置,还能表示一个向量。3个值 (x,y,z)组合起来表示两个重要的...

  • OpenGL学习 mvp矩阵

    在OpenGL中 对三围空间的物体进行平移、旋转、缩放需要借助于矩阵的操作。注意:矩阵的操作先后顺序对最后的结果可...

  • 3d开发之opengl着色语言

    opengl着色语言基于c++,又完美的支持向量和矩阵的各种操作,拥有大量的内置函数来提供丰富的功能,opengl...

  • OpenGL-矩阵压栈出栈浅析

    OpenGL绘制图形需要经过变化才能达到用户目的,而变换是通过矩阵进行操作的。 OpenGL一般通过视图变换、模型...

  • OpenGL-矩阵与向量

    OpenGL的矩阵操作 旋转 平移 缩放 压栈/出栈 单位向量-X轴-(1,0,0) 单位矩阵-X,Y,Z 三轴...

  • OpenGL 出栈压栈理解分析

    1.OpenGL压栈出栈作用概念 1.压栈出栈操作的是矩阵,一般分为模型视图矩阵和投影矩阵 2.出栈压栈是针对顶点...

  • OpenGL中矩阵的行主序与列主序

    行主序与列主序 OpenGL中使用的矩阵,都是数学意义上的标准矩阵。但是各个OpenGL应用在实现矩阵时,根据存储...

  • OpenGL:矩阵的计算(平移,缩放,旋转)

    OpenGL:矩阵的计算(平移,缩放,旋转)

  • 第八弹 OpenGL矩阵操作

    OpenGL 矩阵操作 本篇文章总体分为两个部分,第一部分是矩阵的相关概念。第二部分是案例编写和分析。因为案例中涉...

网友评论

      本文标题:OpenGL 矩阵操作

      本文链接:https://www.haomeiwen.com/subject/abfpjktx.html