学习目标:
- 向量、矩阵和基础变化(了解)
- 使用矩阵/向量移动几何图形(实践)
- 矩阵堆栈(理解)
1. 向量与矩阵
- 向量:向量是研究2D、3D数学的标准工具。向量V是一个既有大小又有方向的量(联系位移和速度的概念)。在数学上,常用一条有方向的线段来表示向量。
- 理解向量把握:
- 1.向量的大小就是向量的长度(模)。向量的长度非负。
- 2.向量的方向描述了向量的指向。
- 3.向量是没有位置的,与点是不同的。
- 4.向量与标量不同,标量是只有大小而没有方向的量,例如位移是向量,而距离是标量。
- OpenGL中向量的使用:
math3d中,有两个数据类型,能够表示三维或四维。M3DVector3f
可以表示一个三维向量(x,y,z),而M3DVector4f
则可以表示一个四维向量(x,y,z,w),w称为缩放因子。在典型情况下,w坐标设为1.0。x,y,z值通过除以w,来进⾏行缩放。⽽除以1.0则本质上不改变x,y,z值。
//声明一个三分量顶点数组,例如生成一个三角形
M3DVector3f vVerts[] = {
-0.5f,0.0f,0.0f,
0.5f,0.0f,0.0f,
0.0f,0.5f,0.0f
};
- 向量点乘和叉乘
- 点乘
//实现点乘方法: //⽅法1:返回的是-1,1之间的值。它代表这2个向量的余弦值。 float m3dDotProduct3(const M3DVector3f u,const M3DVector3f v); //⽅法2:返回2个向量之间的弧度值。 float m3dGetAngleBetweenVector3(const M3DVector3f u,const M3DVector3f v);
- 叉乘
//result 为法向量 void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v);
-
矩阵:从形式上就是一个数字表,以行和列的形式呈现,简单的矩阵如下图所示:
矩阵.png- 定义矩阵
//定义4*4矩阵 M3DMatrix44f mCamera;
-
OpenGL中的基础变化:
OpenGL变换术语概况.png
2. 使用矩阵/向量移动几何图形
- 核心:
- 平移之后的坐标,该函数主动赋值到参数1中
//参数1:平移之后的坐标,该函数主动赋值到参数1中 //参数2:平移的x //参数3:平移的y //参数4:平移的z m3dTranslationMatrix44(translationMatrix, xPos, yPos, 0);
- 旋转换后的坐标,该函数主动赋值到参数1中
//参数1:旋转换后的坐标,该函数主动赋值到参数1中 //参数2:旋转的角度 需要把弧度转化为角度 //参数3/4/5:围绕哪个轴旋转 static float yRot = 0.0f; yRot += 5.0f; m3dRotationMatrix44(rotationMatrix, m3dDegToRad(yRot), 0, 0, 1);
- 把平移和旋转合并(乘)起来
//把平移和旋转合并(乘)起来 //参数1:合并后的坐标 //参数2/3:需要合并的两个坐标 m3dMatrixMultiply44(finalTransform, translationMatrix, rotationMatrix);
//召唤场景 void renderScene(void){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); M3DMatrix44f rotationMatrix,translationMatrix,finalTransform; //参数1:平移之后的坐标,该函数主动赋值到参数1中 //参数2:平移的x //参数3:平移的y //参数4:平移的z m3dTranslationMatrix44(translationMatrix, xPos, yPos, 0); //参数1:旋转换后的坐标,该函数主动赋值到参数1中 //参数2:旋转的角度 需要把弧度转化为角度 //参数3/4/5:围绕哪个轴旋转 static float yRot = 0.0f; yRot += 5.0f; m3dRotationMatrix44(rotationMatrix, m3dDegToRad(yRot), 0, 0, 1); //把平移和旋转合并(乘)起来 //参数1:合并后的坐标 //参数2/3:需要合并的两个坐标 m3dMatrixMultiply44(finalTransform, translationMatrix, rotationMatrix); GLfloat vColor[] = { 1.0f, 0.8f, 0.9f, 1.0f }; shaderManaget.UseStockShader(GLT_SHADER_FLAT,finalTransform,vColor); squareBatch.Draw(); glutSwapBuffers(); }
- 平移之后的坐标,该函数主动赋值到参数1中
3.矩阵堆栈
- 使用矩阵堆栈的原因:我们在使用矩阵对渲染的视图做图形变换(如平移、旋转、缩放)时,需要对矩阵进行点乘或者叉乘计算,将计算的结果使用GLMatrixStack存储,保证了每一次的变换都是独立进行的。
- 模型矩阵:将顶点由局部坐标系转换到世界坐标系;
- 视图矩阵:将顶点由世界坐标系转换到视图坐标系;
- 投影矩阵:将顶点由视图坐标系转换到屏幕中。
- 模型视图投影矩阵 = 投影矩阵 * 模型视图矩阵(注意这里不能写成 模型视图矩阵 * 投影矩阵,矩阵乘法不满足交换)。
- 使用方法:
- 初始化矩阵堆栈:通过看他具体实现我们可以看到,它会创建一个栈结构的存储控件,iStackDepth表示该栈空间的深度为64,就是说我们可以对它进行64次的push操作,同时会在栈顶添加一个单元矩阵.
GLMatrixStack::GLMatrixStack(int iStackDepth = 64)
//创建一个矩阵堆栈,初始化时会在创建时在栈顶加入一个单元矩阵 (FILO:先进后出) GLMatrixStack modelViewMatrix; //在栈顶载入一个单元矩阵 modelViewMatrix.LoadIdentity(); //在栈顶载入任何矩阵,参数:4*4矩阵 modelViewMatrix.LoadMatrix(<#const float *mMatrix#>) //矩阵乘以矩阵堆栈顶部矩阵,相乘结果存储到堆栈的顶部 modelViewMatrix.MultMatrix(const M3DMatrix44f); //将指定矩阵压入矩阵堆栈 modelViewMatrix.PushMatrix(<#const float *mMatrix#>) //将当前矩阵压入矩阵堆栈,就是将当前矩阵堆栈的顶部矩阵copy一份 加到矩阵堆栈的顶部 modelViewMatrix.PushMatrix(); //将M3DMatrix44f 矩阵对象压入当前矩阵堆栈 modelViewMatrix.PushMatrix(<#GLFrame &frame#>) //出栈 modelViewMatrix.PopMatrix(); //获取矩阵栈顶的值 modelViewMatrix.GetMatrix();
- 初始化矩阵堆栈:通过看他具体实现我们可以看到,它会创建一个栈结构的存储控件,iStackDepth表示该栈空间的深度为64,就是说我们可以对它进行64次的push操作,同时会在栈顶添加一个单元矩阵.
网友评论