美文网首页
OpenGL(五)-矩阵变换

OpenGL(五)-矩阵变换

作者: 搜捕儿 | 来源:发表于2018-03-01 18:50 被阅读270次

    关键函数讲解

    平移

        //创建单元矩阵 
        M3DMatrix44f m3;
        m3dLoadIdentity44(m3);
    
        /*
          m3dTranslationMatrix44(M3DMatrix44f m, float x, float y, float z)
         参数1:结果矩阵,平移之后的结果矩阵
         参数2:沿着X轴移动多少,正数\负数
         参数3:沿着Y轴移动多少,正数\负数
         参数4:沿着Z轴移动多少,正数\负数
         */
        m3dTranslationMatrix44(m3, 0.0f, 10.0f, 0.0f);
    

    旋转

        /*
          m3dRotationMatrix44(M3DMatrix44f m, float angle, float x, float y, float z);
         参数1:结果矩阵,旋转之后的结果矩阵
         参数2:旋转多少弧度
         参数3:是否围绕X轴旋转,是(1),不是(0)
         参数4:是否围绕Y轴旋转,是(1),不是(0)
         参数5:是否围绕Z轴旋转,是(1),不是(0)
         */
        m3dRotationMatrix44(m3, m3dDegToRad(45.0f), 1.0f, 0.0f, 0.0f);
    

    缩放

        /*
         void m3dScaleMatrix44(M3DMatrix44f m, float xScale, float yScale, float zScale)
         参数1:结果矩阵
         参数2:围绕X轴放大\缩小;放大x>1,缩小:0.5f
         参数3:围绕Y轴放大\缩小;放大x>1,缩小:0.5f
         参数4:围绕Z轴放大\缩小;放大x>1,缩小:0.5f
         */
        m3dScaleMatrix44(m3, 1.0f, 10.0f, 1.0f);
    

    案例1 : 利用矩阵的平移、旋转、综合变化等, 实现矩阵的移动.

    GLBatch squareBatch;
    GLfloat blockSize = 0.1f;
    GLfloat vVerts[] = {
        -blockSize, -blockSize, 0.0f,
        blockSize, -blockSize, 0.0f,
        blockSize,  blockSize, 0.0f,
        -blockSize,  blockSize, 0.0f};
    
    GLfloat xPos = 0.0f;
    GLfloat yPos = 0.0f;
    
    void SetupRC()
    {
        //背景颜色
        glClearColor(0.0f, 0.0f, 1.0f, 1.0f );
        
        shaderManager.InitializeStockShaders();
        
        // 加载矩形
        squareBatch.Begin(GL_TRIANGLE_FAN, 4);
        squareBatch.CopyVertexData3f(vVerts);
        squareBatch.End();
    }
    
    //移动(移动只是计算了X,Y移动的距离,以及碰撞检测)
    void SpecialKeys(int key, int x, int y)
    {
        GLfloat stepSize = 0.025f;
        
        
        if(key == GLUT_KEY_UP)
            yPos += stepSize;
        
        if(key == GLUT_KEY_DOWN)
            yPos -= stepSize;
        
        if(key == GLUT_KEY_LEFT)
            xPos -= stepSize;
        
        if(key == GLUT_KEY_RIGHT)
            xPos += stepSize;
        
        // 碰撞检测
        if(xPos < (-1.0f + blockSize)) xPos = -1.0f + blockSize;
        
        if(xPos > (1.0f - blockSize)) xPos = 1.0f - blockSize;
        
        if(yPos < (-1.0f + blockSize))  yPos = -1.0f + blockSize;
        
        if(yPos > (1.0f - blockSize)) yPos = 1.0f - blockSize;
        
        // 每次操作方向键之后, 重新调用RenderScene进行新的场景渲染
        glutPostRedisplay();
    }
    
    void RenderScene(void)
    {
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        
        GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
        
        //!!!矩阵变化 - 关键代码!!!
        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);
        
        //将矩阵结果提交到固定着色器(平面着色器)中。
        shaderManager.UseStockShader(GLT_SHADER_FLAT, mFinalTransform, vRed);
    
        //!!!矩形重新绘制, 即会出现一个既平移了方向又旋转了角度的新矩形
        squareBatch.Draw();
        
        // 执行缓冲区交换
        glutSwapBuffers();
    }
    
    void ChangeSize(int w, int h)
    {
        glViewport(0, 0, w, h);
    }
    
    
    int main(int argc, char* argv[])
    {
        gltSetWorkingDirectory(argv[0]);
        
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
        glutInitWindowSize(600, 600);
        glutCreateWindow("Move Block with Arrow Keys");
        
        GLenum err = glewInit();
        if (GLEW_OK != err)
        {
            
            fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
            return 1;
        }
        
    
        glutReshapeFunc(ChangeSize);//设置视口大小
        glutDisplayFunc(RenderScene);//渲染场景
        glutSpecialFunc(SpecialKeys);//键盘方向键操作
        
        SetupRC();
        
        glutMainLoop();
        return 0;
    }
    
    

    效果图:

    注: 本例是键盘的上下左右方向键来控制矩形的旋转平移, 具体代码参见上面


    利用矩阵变换实现模型变化.gif

    案例2 : 利用模型视图矩阵和投影矩阵让一个球体旋转

    绘制球体
        gltMakeSphere(torusBatch, 0.4f, 10, 20);
        
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    
    设置模型视图矩阵 和 投影矩阵
        //建立一个基于时间变化的动画
        static CStopWatch rotTimer;
        
        //当前时间 * 60s
        float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
        
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        //矩阵变量
        M3DMatrix44f mTranlate,mRotate,mModelView,mModelViewProjection;
        
        //将圆球像Z轴负方向移动2.5个单位长度
        m3dTranslationMatrix44(mTranlate, 0.0f , 0.0f,-2.5f);
        
        //旋转
        m3dRotationMatrix44(mRotate, m3dDegToRad(yRot), 0.0f, 1.0f, 0.0f);
        
        //将平移和旋转的矩阵进行叉乘,产生一个新的矩阵mModelView
        m3dMatrixMultiply44(mModelView, mTranlate, mRotate);
        
        //模型视图矩阵 和 投影矩阵
        //将投影矩阵 与 模型视图矩阵进行叉乘 ,将变化最终结果通过矩阵叉乘的方式应用到mModelViewProjection中来
        m3dMatrixMultiply44(mModelViewProjection, viewFrustum.GetProjectionMatrix(), mModelView);
        
        GLfloat vBlack[] = {0.0f,0.0f,0.0f,1.0f};
        
        //平面着色器来渲染图像
        shaderManager.UseStockShader(GLT_SHADER_FLAT,mModelViewProjection,vBlack);
        
        //开始绘图
        torusBatch.Draw();
        
        glutSwapBuffers();
        glutPostRedisplay();
    
    效果图
    ModelViewProjection.gif

    相关文章

      网友评论

          本文标题:OpenGL(五)-矩阵变换

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