欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenGL之利用矩阵的平移、旋转、综合变换等实现矩阵的移动

程序员文章站 2024-03-20 14:46:28
...

核心业务

  • 矩形的绘制
    // 加载矩形
    squareBatch.Begin(GL_TRIANGLE_FAN, 4);
    squareBatch.CopyVertexData3f(vVerts);
    squareBatch.End();
  • 碰撞检测
    // 碰撞检测
    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();
  • 矩阵的变换(平移、旋转、综合变换)
    // 矩阵变化
    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);

示例代码

#include <stdio.h>

// GLTool.h头⽂文件包含了大部分GLTool中类似C语言的独立函数
#include "GLTools.h"
// 矩阵的⼯具类.可以利于GLMatrixStack 加载单元矩阵/矩阵/矩阵相乘/压栈/出栈/缩放/平移/旋转
#include "GLMatrixStack.h"
// 矩阵工具类,表示位置.通过设置vOrigin,vForward,vUps等
#include "GLFrame.h"
// 矩阵⼯具类,⽤来快速设置正/透视投影矩阵.完成坐标从3D->2D的映射过程
#include "GLFrustum.h"
// 三⻆形批次类,帮助类,利用它可以传输顶点/光照/纹理/颜⾊数据到存储着⾊器中
#include "GLBatch.h"
// 变换管道类,⽤来快速在代码中传输视图矩阵/投影矩阵/视图投影变换矩阵等
#include "GLGeometryTransform.h"


//  在Mac 系统下,`#include<glut/glut.h>`在Windows 和 Linux上,我们使用freeglut的静态库版本并且需要添加一个宏
#include <math.h> // 数学库
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

GLShaderManager        shaderManager;
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.5f, 0.5f, 0.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[] = {0.5f, 0.0f, 0.5f, 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之利用矩阵的平移、旋转、综合变换等实现矩阵的移动