美文网首页
OpenGL观察方式与矩阵

OpenGL观察方式与矩阵

作者: windy_3c22 | 来源:发表于2020-07-15 12:47 被阅读0次

    目前在OpenGL中矩阵变换主要涉及两种方式:

    • 观察者不动,物体移动。
    • 物体不动,观察者动。

    1、观察者不动,物体移动

    如图1:


    图1
    • 其中矩阵堆栈的变换
      矩阵相乘流程
    • 应用到观察者矩阵和物体矩阵的变换
      观察者矩阵、物体矩阵
    • 代码函数中矩阵设置
      1、SetupRC函数:设置观察者位置,使用GLGeometryTransform管理矩阵堆栈(视图模型矩阵堆栈和投影矩阵堆栈)。
    void SetupRC(){
        // 1、设置背景颜色
        glClearColor(0.7f, 0.7f, 0.7f, 1.0f );
        // 2、初始化固定着色器管理器
        shaderManager.InitializeStockShaders();
        // 3、绘制立体图形的时候,需要开启深度测试
        glEnable(GL_DEPTH_TEST);
        //4、 通过GLGeometryTransform管理矩阵堆栈
        // 使用transformPipeline 管道管理模型视图矩阵堆栈 和 投影矩阵堆栈
        //(把两个矩阵作为两个参数放进去)
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
      // 5、为了让效果明显,将观察者坐标位置Z移动往屏幕里移动15个单位位置
        // 参数:表示离屏幕之间的距离。 负数,是往屏幕后面移动;正数,往屏幕前面移动
        cameraFrame.MoveForward(-15.0f);
       //通过三角形创建金字塔
        GLfloat vPyramid[12][3]={
            -2.0f, 0.0f, -2.0f,
            2.0f, 0.0f, -2.0f,
            0.0f, 4.0f, 0.0f,
    
            2.0f, 0.0f, -2.0f,
            2.0f, 0.0f, 2.0f,
            0.0f, 4.0f, 0.0f,
    
            2.0f, 0.0f, 2.0f,
            -2.0f, 0.0f, 2.0f,
            0.0f, 4.0f, 0.0f,
    
            -2.0f, 0.0f, 2.0f,
            -2.0f, 0.0f, -2.0f,
            0.0f, 4.0f, 0.0f
        };
        
        //每三个顶点定义一个三角形、将顶点数据拷入、完成
        triangleBatch.Begin(GL_TRIANGLES, 12);
        triangleBatch.CopyVertexData3f(vPyramid);
        triangleBatch.End();
    }
    

    2、ChangeSize函数:设置投影方式,创建投影矩阵并载入投影矩阵堆栈中。最后的单元矩阵可省略。

    //窗口改变
    void ChangeSize(int w,int h){
        glViewport(0, 0, w, h);
        //创建投影矩阵,并将它载入投影矩阵堆栈中
        viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 500.0f);
        projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
        //调用顶部载入单元矩阵(可省略)
        modelViewMatrix.LoadIdentity();
    }
    

    3、RenderScene函数:完成观察者矩阵、物体矩阵的相关变换,压栈、相乘、出栈。

    void RenderScene(void){
        //清理缓冲区
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        
        //将观察者的坐标系压栈
        modelViewMatrix.PushMatrix();
        M3DMatrix44f mCamera;
        cameraFrame.GetCameraMatrix(mCamera);
        //矩阵乘矩阵堆栈的顶部矩阵,相乘的结果随后存储在堆栈的顶部
        modelViewMatrix.MultMatrix(mCamera);
        
        //图形环绕坐标系压栈
        M3DMatrix44f mObjectFrame;
        //只要使用GetMutrix函数就可以获取矩阵堆栈顶部的值,这个函数可以进行2次重载。
        //用来使用GLShaderManager的使用。或者获取顶部矩阵的顶点副本数据。
        objectFrame.GetMatrix(mObjectFrame);
        //矩阵乘以矩阵堆栈的顶部矩阵。相乘的结果随后存储在堆栈的顶部
        modelViewMatrix.MultMatrix(mObjectFrame);
        
        /* GLShaderManager 中的Uniform 值——平面着色器
        参数1:平面着色器
        参数2:运行为几何图形变换指定一个 4 * 4变换矩阵
        --transformPipeline.GetModelViewProjectionMatrix() 获取的
        GetMatrix函数就可以获得矩阵堆栈顶部的值
        参数3:颜色值(黑色)
        */
        //传递到存储着色器
        shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeLine.GetModelViewProjectionMatrix(),vGreen);
        //提交着色器
        DrawWireFramedBatch(&triangleBatch);
        
        //还原到单位矩阵
        modelViewMatrix.PopMatrix();
        //后台缓冲 -> 交换
        glutSwapBuffers();
    }
    

    4、SpecialKeys函数:上、下、左、右移动。决定观察者或物体围绕x、y、z轴的移动,触发重绘

    //特殊键位处理(上、下、左、右移动)
    void SpecailKeys(int key,int x,int y){
        //围绕xyz固定轴旋转
        if (key == GLUT_KEY_UP) {
    //        objectFrame.RotateLocalX(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);
        }
        glutPostRedisplay();
    }
    

    2、观察者动,物体不动

    观察者动,物体不动
    • 此时设置观察者时
      2.1 setupRC函数
    void SetupRC(){
       //此时的 objectFrame是观察者
       objectFrame.MoveForward(15.0f);
    }
    

    2.2 RenderScene函数

    void RenderScene(void){{
    //清理缓冲区
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
        //只需将观察者压入栈中即可。此时的 objectFrame是观察者
        modelViewMatrix.PushMatrix(objectFrame);
    
        //传递到存储着色器
        shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeLine.GetModelViewProjectionMatrix(),vGreen);
        //提交着色器
        DrawWireFramedBatch(&triangleBatch);
        
        //还原到单位矩阵
        modelViewMatrix.PopMatrix();
        //后台缓冲 -> 交换
        glutSwapBuffers();
    }
    

    此时objectFrame记录者观察者初始设置时移动的位置,及观察者围绕相应x,y,z轴旋转的弧度。此时观察者记录了所有的变化,所以只需将观察者入栈即可
    Demo链接
    demo中setupRC函数和RenderScene中替换注视代码(观察者动/不动)

    相关文章

      网友评论

          本文标题:OpenGL观察方式与矩阵

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