美文网首页
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