Matrix operation in OpenGL ES Primer trip --OpenGL

This article is only for individuals in the process of learning OpenGL, the use of 3D mathematics, vectors and matrices in this to make a record.

The 1.OpenGL matrix, vector

In the three-dimensional coordinates of OpenGL, the three values ​​(x, y, z) are combined to represent two important values: the direction and amount -> vector.

There are a math3d in OpenGL library, math3d library has two types of data can be expressed ⼀ three dimensional or four-dimensional vectors. M3DVector3f ⼀ may represent a three-dimensional vector (x, y, z), and M3DVector4f it may represent a four-dimensional vector (x, y, z, w ). In a typical case, w coordinates set at 1.0. x, y, z values to be scaled by dividing by w. X is divided without changing the essence 1.0, y, z value.

typedef float M3DVector3f[3];
typedef float M3DVector4f[4];
声明⼀个三分量向量操作:
M3DVector3f vVector;
类似,声明⼀个四分量的操作:
M3DVector4f vVectro= {0.0f,0.0f,1.0f,1.0f};
声明一个三分量顶点数组,例如⽣成⼀个三⻆形
M3DVector3f vVerts[] = {
-1.0f,0.0f,0.0f,
0.5f,0.0f,0.0f,
0.0f,1.0f,0.0f
};
复制代码

2. dot:

Point multiplication to return the angle between the two vectors

//实现点乘方法: 
//⽅法1: 返回的是-1,1之间的值。它代表这个2个向量量的余弦值。
float m3dDotProduct3(const M3DVector3f u,const
M3DVector3f v);

//方法2:返回2个向量之间的弧度值。
float m3dGetAngleBetweenVector3(const M3DVector3f u,const M3DVector3f v);
复制代码

3. cross product:

Cross multiplication result returns a new vector, the new vector and the vector perpendicular to the original 2

void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v);
复制代码

4. The model transformation

First look at the transformation in OpenGL:

Convert application Description Comments
view Developing position of the observer or camera View transform allows us to observe any point in the desired position, and to allow viewing scenes in any direction. Determining the view transformation as a camera placed in the scene and point it in a certain direction.
model The moving object in the scene For manipulating model transformation model and specific objects therein. These transformations move the object to the desired location, and then they rotate and zoom.
View model Description duality of view and modeling transformations In fact, do not have to observe the object by moving the camera (view transform), but moving this object (model transformation), which can be two ways to achieve the same effect, sometimes using one of the conversion ratio using another transformation is much more convenient . This is also the view transform and model transformation are the reason for the unified model view matrix.
projection Changing the size of the viewing volume or resetting its shape, the three-dimensional coordinates of the projected two-dimensional screen coordinates, located outside the frustum what will be cropped After projective transformation will be applied to the model view transform vertices, it will complete a specified scene (converting all models have been completed) is projected to how the final image on the screen. Orthographic: All polygons are drawn exactly on the screen according to the relative size specified. Perspective projection: perspective projection is foreshortening characteristics, such characteristics such that distant objects appear smaller than the number of objects out of the same size.
Viewport This is a pseudo-conversion, but the final output of the zoom window After completion of all transform, you get a two-dimensional projection of the scene, it will be mapped to the window somewhere on the screen. This map is subject to a physical wound last thing we transform, called the viewport transformation.

5. Matrix

Statement Matrix

声明一个三维矩阵:
typedef float M3DMatrix33f[9];
声明一个四维矩阵:
typedef float M3DMatrix44f[16];
复制代码

OpenGL is not a 4X4 matrix is ​​represented as a two-dimensional array of floating point values, but it is represented as a single array of floating point values ​​of 16.

The first three columns correspond to the x-axis, y-axis, z-axis direction. Column matrix has been particularly marked, the last row of the matrix are zero, only the last element is 1. If there is a 4X4 matrix contains a different position and orientation of the coordinate system, and then a vector representation of the original coordinate system (represented as a column matrix or vector) multiplied by this matrix, the result is converted to a new coordinate system the new vector. This means that space anywhere and in any direction you want can be uniquely determined by a 4X4 matrix, and if all vectors with an object multiplied by this matrix, then we will transform the whole object into a given space position and orientation. Matrix: matrix in addition to a set of elements on the diagonal, the other elements are zero. A vector / matrix by a matrix, this is equivalent to a vector / matrix by 1, any change does not occur.

6. Use of a matrix

Model view matrix model view matrix is ​​a 4X4 matrix, which represents a transformation of coordinate system, can be used to place the object, and we determine the orientation of the object. The matrix contains a single vertex data multiplied by the model view matrix will be a new vision coordinate. We call math3d library m3dTranslationMatrix44 function using the model-view transformation matrix.

1.平移
void m3dTranslationMatrix44(M3DMatrix44f m,float x,float y,float z);
2.旋转
m3dRotationMatrix44(M3DMatrix44f m,float angle,float x,float y,float z);
3.缩放
void m3dScaleMatrix44(M3DMatrix44f m,float xScale,float yScale,float zScale);
4.综合(math3d库函数m3dMatrixMultiply44用来将两个矩阵相乘并返回运算结果)
void m3dMatrixMultiply44(M3DMatrix44f product,const M3DMatrix44f a,const M3DMatrix44f b);

eg:
    M3DMatrix44f mFinalTransform, mTranslationMatrix, mRotationMatrix;
    //平移 xPos,yPos
    m3dTranslationMatrix44(mTranslationMatrix, xPos, yPos, 0.0f);
    // 每次重绘时,旋转5度
    static float yRot = 0.0f;
    yRot += 5.0f;
    m3dRotationMatrix44(mRotationMatrix, m3dDegToRad(yRot), 0.0f, 0.0f, 1.0f);
    //将旋转和移动的结果合并到mFinalTransform 中
    m3dMatrixMultiply44(mFinalTransform, mTranslationMatrix, mRotationMatrix);
复制代码

Projection view matrix

1.正投影
GLFrustum::SetOrthographic(GLfloat xMin,GLfloat xMax,GLfloat yMin,GLfloat yMax,GLfloat zMin,GLfloat zMax);
2.透视投影
GLFrustum::SetPerspective(float fFov,float fAspect,float fNear,float fFar);
// 参数1:从顶点方向看去的视场角度值
// 参数2:宽和高的纵横比
// 参数3:近裁剪面的距离
// 参数4:远裁剪面的距离
复制代码

The maximum depth of the matrix stack constructor GLMatrixStack class allows you to specify the stack, the stack depth is the default matrix stack 64. This has been included in the matrix stack during initialization. (Matrix stack last-out)

GLMatrixStack::GLMatrixStack(int iStackDepth=64);
复制代码

Matrix Stack of use:

1.矩阵堆栈顶部载入单元矩阵
void GLMatrixStack::LoadIdentity(void);

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

3.用一个矩阵乘以矩阵堆栈的顶部矩阵,相乘得到的结果随后将存储在堆栈的顶部
void GLMatrixStack::MultMatrix(const M3DMatrix44f);

4.获取矩阵堆栈顶部的值
const M3DMatrix44f& GLMatrixStack::GetMatrix(void);
void GLMatrixStack::GetMatrix(M3DMatrix44f mMatrix);

5.压栈和出栈
void GLMatrixStack::PushMatrix(void);
void PushMatrix(const M3DMatrix44f mMatrix);
void PushMatrix(GLFrame& frame);
void GLMatrixStack::PopMatrix(void);

6.仿射变换 
GLMatrixStack类也有对创建旋转、平移和缩放矩阵的支持。
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);
复制代码

We look at the use of matrix codes and matrix stack by drawing a plurality of graphical point of view: first import the header file:

#include "GLTools.h"	// OpenGL toolkit
#include "GLMatrixStack.h"    //矩阵堆栈工具类
#include "GLFrame.h"    //矩阵位置工具类
#include "GLFrustum.h"  // 透视投影矩阵类
#include "GLBatch.h"    //三角形批次类
#include "GLGeometryTransform.h"   //变换管道
#include "StopWatch.h"

#include <math.h>    // 数学类
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
复制代码

Declare global variables:

GLShaderManager	    shaderManager; //存储着色器管理
GLMatrixStack		modelViewMatrix;//模型视图矩阵堆栈
GLMatrixStack		projectionMatrix;// 投影视图矩阵堆栈
GLFrame				cameraFrame;//观察者位置
GLFrame             objectFrame;//世界坐标位置
GLFrustum			viewFrustum;//视景体,用来构造投影矩阵
GLTriangleBatch     CC_Triangle;//三角形批次类
//每一种图形都需要一个单独的三角形批次类:
GLTriangleBatch     sphereBatch;//球
GLTriangleBatch     torusBatch;//环
GLTriangleBatch     cylinderBatch;//圆柱
GLTriangleBatch     coneBatch;//锥
GLTriangleBatch     diskBatch;//磁盘
GLGeometryTransform transformPipeline;//变换管道,用来管理模型,投影矩阵
M3DMatrix44f		shadowMatrix;
GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f }; //定义颜色:绿色
GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };//定义颜色:黑色
int nStep = 0; //定义第几个图形
复制代码

Program entry main () function:

int main(int argc, char* argv[])
{
    gltSetWorkingDirectory(argv[0]);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
   //设置GLUT窗口大小、窗口标题
    glutInitWindowSize(800, 600);
    glutCreateWindow("Sphere");
    //注册重塑函数---设置视口
    glutReshapeFunc(ChangeSize);
    //注册空格函数---切换图形
    glutKeyboardFunc(KeyPressFunc);
    //注册移动函数---上下左右移动图形
    glutSpecialFunc(SpecialKeys);
     //注册显示函数
    glutDisplayFunc(RenderScene);
    
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }
    //设置渲染环境
    SetupRC();
    glutMainLoop();
    return 0;
}
复制代码

Remodeling function ChangeSize (): when the window is first displayed, or will be re-called resize the window function when remodeling, receiving a new w, h values.

void ChangeSize(int w, int h)
{
    //1.视口 
    if(h == 0){  // 防止h变为0
        h = 1;
    }
    glViewport(0, 0, w, h);  //设置视口坐标,大小,一般情况下视口的坐标都是窗口的左下角,故设置为(0,0);
    
    //2.设置透视投影
    //创建透视投影矩阵
    viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 500.0f);
    //projectionMatrix 投影视图矩阵堆栈---加载透视投影矩阵
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    
    //3.modelViewMatrix 模型视图矩阵堆栈 ----加载一个单元矩阵
     modelViewMatrix.LoadIdentity();
    
    //4.通过GLGeometryTransform管理矩阵堆栈
    //使用transformPipeline 管道管理模型视图矩阵堆栈 和 投影视图矩阵堆栈
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}
复制代码

Set the rendering environment SetupRC () function:

// 将上下文中,进行必要的初始化
void SetupRC()
{
    //1.设置背景颜色值
    glClearColor(0.7f, 0.7f, 0.7f, 1.0f );
    //2.初始化存储着色器管理
    shaderManager.InitializeStockShaders();
    //3.开启深度测试(无论绘制什么图形,都开启深度测试)
    glEnable(GL_DEPTH_TEST);
    //4.将观察者坐标位置Z移动往屏幕里移动15个单位位置
    //表示离屏幕之间的距离。
    //负数,是往屏幕后面移动
    //正数,是往屏幕前面移动
    cameraFrame.MoveForward(-15.0f);
    //5.利用三角形批次类构造图形对象
    // 球
    /*
      gltMakeSphere(GLTriangleBatch& sphereBatch, GLfloat fRadius, GLint iSlices, GLint iStacks);
     参数1:sphereBatch,三角形批次类对象
     参数2:fRadius,球体半径
     参数3:iSlices,从球体底部堆叠到顶部的三角形带的数量;其实球体是一圈一圈三角形带组成
     参数4:iStacks,围绕球体一圈排列的三角形对数
     
     建议:一个对称较好的球体的片段数量是堆叠数量的2倍,就是iStacks = 2 * iSlices;
     绘制球体都是围绕Z轴,这样+z就是球体的顶点,-z就是球体的底部。
     */
    gltMakeSphere(sphereBatch, 3.0, 10, 20);
    
    // 环面
    /*
     gltMakeTorus(GLTriangleBatch& torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor);
     参数1:torusBatch,三角形批次类对象
     参数2:majorRadius,甜甜圈中心到外边缘的半径
     参数3:minorRadius,甜甜圈中心到内边缘的半径
     参数4:numMajor,沿着主半径的三角形数量
     参数5:numMinor,沿着内部较小半径的三角形数量
     */
    gltMakeTorus(torusBatch, 3.0f, 0.75f, 15, 15);
    
    // 圆柱
    /*
     void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks);
     参数1:cylinderBatch,三角形批次类对象
     参数2:baseRadius,底部半径
     参数3:topRadius,头部半径
     参数4:fLength,圆形长度
     参数5:numSlices,围绕Z轴的三角形对的数量
     参数6:numStacks,圆柱底部堆叠到顶部圆环的三角形数量
     */
    gltMakeCylinder(cylinderBatch, 2.0f, 2.0f, 3.0f, 15, 2);
    
    //锥
    /*
     void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks);
     参数1:cylinderBatch,三角形批次类对象
     参数2:baseRadius,底部半径
     参数3:topRadius,头部半径
     参数4:fLength,圆形长度
     参数5:numSlices,围绕Z轴的三角形对的数量
     参数6:numStacks,圆柱底部堆叠到顶部圆环的三角形数量
     */
    //圆柱体,从0开始向Z轴正方向延伸。
    //圆锥体,是一端的半径为0,另一端半径可指定。
    gltMakeCylinder(coneBatch, 2.0f, 0.0f, 3.0f, 13, 2);
    
    // 磁盘
    /*
    void gltMakeDisk(GLTriangleBatch& diskBatch, GLfloat innerRadius, GLfloat outerRadius, GLint nSlices, GLint nStacks);
     参数1:diskBatch,三角形批次类对象
     参数2:innerRadius,内圆半径
     参数3:outerRadius,外圆半径
     参数4:nSlices,圆盘围绕Z轴的三角形对的数量
     参数5:nStacks,圆盘外网到内围的三角形数量
     */
    gltMakeDisk(diskBatch, 1.5f, 3.0f, 13, 3);
}
复制代码

RenderScene display the scene () function:

//召唤场景
void RenderScene(void)
{
    //1.清除当前缓存,防止在渲染过程中出现错误
   //GL_COLOR_BUFFER_BIT :指当前激活的用来进行颜色写入缓冲区
   //GL_DEPTH_BUFFER_BIT :指深度缓存区
   //GL_STENCIL_BUFFER_BIT:指模板缓冲区
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    //2.模型视图矩阵栈堆,压栈
    modelViewMatrix.PushMatrix();
    //3.创建摄像头矩阵
    M3DMatrix44f mCamera;
    //从camereaFrame中获取矩阵到mCamera
    cameraFrame.GetCameraMatrix(mCamera);
    //模型视图堆栈的 矩阵与mCamera矩阵 相乘之后,存储到modelViewMatrix矩阵堆栈中
    modelViewMatrix.MultMatrix(mCamera);
    //4.创建矩阵mObjectFrame
    M3DMatrix44f mObjectFrame;
    //从ObjectFrame 获取矩阵到mOjectFrame中
    objectFrame.GetMatrix(mObjectFrame);
    //将modelViewMatrix 的堆栈中的矩阵 与 mOjbectFrame 矩阵相乘,存储到modelViewMatrix矩阵堆栈中
    modelViewMatrix.MultMatrix(mObjectFrame);
    //5.判断你目前是绘制第几个图形
    switch(nStep) {
        case 0:
            DrawWireFramedBatch(&sphereBatch);
            break;
        case 1:
            DrawWireFramedBatch(&torusBatch);
            break;
        case 2:
            DrawWireFramedBatch(&cylinderBatch);
            break;
        case 3:
            DrawWireFramedBatch(&coneBatch);
            break;
        case 4:
            DrawWireFramedBatch(&diskBatch);
            break;
    }
    //6. pop绘制完成之后,把栈顶矩阵pop出去,不要影响下一次的绘制。(还原到以前的模型视图矩阵 (单位矩阵))
    modelViewMatrix.PopMatrix();
    //7. 进行缓冲区交换
    glutSwapBuffers();
}
复制代码

The following highlights mark at this code:

  1. modelViewMatrix.PushMatrix (); let the model view expressed push, here PushMatrix () brackets are empty and do not indicate the content push is empty, but the top element of the matrix stack copy be push , down to the top of the stack. If the brackets are not empty, on behalf pressed into a matrix of the matrix stack to stack.
  1. M3DMatrix44f mCamera; a statement observer matrix; cameraFrame.GetCameraMatrix (mCamera); means acquiring a matrix from the viewer cameraFrame coordinate system, and then assigned to mCamera.
  1. modelViewMatrix.MultMatrix (mCamera); means that the matrix and the matrix to stack top observer matrix (mCamera) multiplied by the result matrix, the matrix stack back into the top of the stack (i.e., to replace just the matrix stack Stack top matrix).
  1. M3DMatrix44f mObjectFrame; declared a world coordinate position of the object matrix. objectFrame.GetMatrix (mObjectFrame); mean acquisition matrix from objectFrame the world coordinate system, and then assigned to mObjectFrame.
  1. modelViewMatrix.MultMatrix (mObjectFrame); modelViewMatrix the stack in the stack multiplied with the matrix copy mOjbectFrame matrix, a matrix, to obtain the result matrix stack modelViewMatrix stack. (Note here: matrix multiplication is not commutative, so when the top of the stack matrix multiplication, and can not at first mObjectFrame, then is mCamera)
  1. modelViewMatrix.PopMatrix (); meaning that the top of the stack the stack array, the stack returns to the original matrix, it does not affect subsequent drawing.

Here the record about : in SetupRC () this method, we will move towards the observer position Z coordinate screen 15 units in mobile location, cameraFrame.MoveForward (-15.0f); but in fact we can not move the viewer, so that objects moving objectFrame.MoveForward (15.0f) to the observer; in this case RenderScene () this method,

M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);

M3DMatrix44f mObjectFrame;
objectFrame.GetMatrix(mObjectFrame);
modelViewMatrix.MultMatrix(mObjectFrame);
复制代码

This code may need to add a few words, then the model view matrix stack push operation, modelViewMatrix.PushMatrix (); is pressed into objectFrame modelViewMatrix.PushMatrix (objectFrame); Why did this happen? Because we SetupRC () method, objectFrame record the movement of the object to an observer state, while the specialKeys () method, (objectFrame.RotateWorld (m3dDegToRad (-5.0f), 1.0f, 0.0f, 0.0f) ;) objectFrame the same record as the world coordinate system moving state, the last in rendering time (RenderScene ()), modelViewMatrix.PushMatrix (objectFrame); is to change the rotation of change and movement combine in the matrix stack.

The figure is drawn on a stack of a stack appreciated flowchart matrix.

Graphing function DrawWireFramedBatch ():

void DrawWireFramedBatch(GLTriangleBatch* pBatch)
{
    //----绘制图形----
    //1.平面着色器,绘制三角形
    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
    //参数1:着色器类型
    //参数2:通过transformPipeline获取模型视图投影矩阵
    //参数3:颜色

    //传过来的参数,对应不同的图形Batch
    pBatch->Draw();
    
    
    //2.开启多边形偏移
    glEnable(GL_POLYGON_OFFSET_LINE);
    //多边形模型(背面、线) 将多边形背面设为线框模式
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    //开启多边形偏移(设置偏移数量)
    glPolygonOffset(-1.0f, -1.0f);
    //线条宽度
    glLineWidth(2.5f);
    
    //3.开启混合功能(颜色混合&抗锯齿功能)
    glEnable(GL_BLEND);
    //开启处理线段抗锯齿功能
    glEnable(GL_LINE_SMOOTH);
    //设置颜色混合因子
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   
   //4.平面着色器绘制线条
    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
    pBatch->Draw();
    
    //5.恢复多边形模式和深度测试
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glDisable(GL_POLYGON_OFFSET_LINE);
    glLineWidth(1.0f);
    glDisable(GL_BLEND);
    glDisable(GL_LINE_SMOOTH);
}
复制代码

Moving graphics functions SpecialKeys ():

//点击键盘的上下左右,来移动世界坐标系从而移动图形
void SpecialKeys(int key, int x, int y)
{
    if(key == GLUT_KEY_UP)
        //移动世界坐标系,而不是去移动物体。
        //将世界坐标系在X方向移动-5.0
    objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);
    if(key == GLUT_KEY_DOWN)
        objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);
    if(key == GLUT_KEY_LEFT)
        objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
    if(key == GLUT_KEY_RIGHT)
        objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
    // 通知GLUT在进行一次同样操作
    glutPostRedisplay();
}
复制代码

Switching graphics functions KeyPressFunc ():

//点击键盘空格,切换渲染的图形
void KeyPressFunc(unsigned char key, int x, int y)
{
    if(key == 32)
    {
        nStep++;
        if(nStep > 4)
            nStep = 0;
    }
    switch(nStep)
    {
        case 0:
            glutSetWindowTitle("Sphere");
            break;
        case 1:
            glutSetWindowTitle("Torus");
            break;
        case 2:
            glutSetWindowTitle("Cylinder");
            break;
        case 3:
            glutSetWindowTitle("Cone");
            break;
        case 4:
            glutSetWindowTitle("Disk");
            break;
    }
    glutPostRedisplay();
}
复制代码

Then look at the graphical results of code execution:

Reproduced in: https: //juejin.im/post/5d09fbf75188252b8d1d454d

Guess you like

Origin blog.csdn.net/weixin_34143774/article/details/93182326