OpenGL(五)-矩阵变换

关键函数讲解

平移

    //创建单元矩阵 
    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;
}

效果图:

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


OpenGL(五)-矩阵变换_第1张图片
利用矩阵变换实现模型变化.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();
效果图
OpenGL(五)-矩阵变换_第2张图片
ModelViewProjection.gif

你可能感兴趣的:(OpenGL(五)-矩阵变换)