美文网首页
OpenGL-04-入门级案例2:绘制通过键位移动的正方形

OpenGL-04-入门级案例2:绘制通过键位移动的正方形

作者: 宇宙那么大丶 | 来源:发表于2020-07-10 18:37 被阅读0次

与上篇中的绘制三角形的主要区别:修改了图元链接方式、增加了键位控制

void setupRC() //函数中修改一行代码

//修改图元链接方式GL_TRIANGLE_FAN
triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
     
int main(int argc,char *argv[]) //函数中新增两行代码
 
//针对MAC OS X,为了更加安全,设置当前工作目录
gltSetWorkingDirectory(argv[0]);

//添加新的特殊函数
glutSpecialFunc(SpecialKeys);

坐标更新方法

运行可以发现:每次点击键位进行移动的时候,都会走一次RenderScene方法
此外还需要考虑超出边界的问题,增加限制条件

一个非常形象的正方形
#include "GLShaderManager.h"
#include "GLTools.h"
#include <GLUT/GLUT.h>

//定义一个着色管理器
GLShaderManager shaderManager;
//简单的批次容器,是GLTools的一个简单的容器类
GLBatch triangleBatch;

//设置顶点到X/Y轴距离 = 正方形边长的一半
GLfloat blockSize = 0.1f;

//正方形的4个点坐标
GLfloat vVerts[] = {
        -blockSize,-blockSize,0.0f,//A点
        blockSize,-blockSize,0.0f,//B点
        blockSize,blockSize,0.0f,//C点
        -blockSize,blockSize,0.0f//D点
};

void changeSize(int w,int h)
{
    glViewport(0, 0, w, h);
}

//渲染方法,每次更新界面(或者图形进行移动就会触发)
void RenderScene(void)
{

    //1、清除一个或一组特定缓存区
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
     
    //2、设置颜色
    GLfloat vColor[] = {1.0,1.0,0.0,1.0f};
    
    //3、传递到存储着色器中
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vColor);
    
    //4、提交着色器
    triangleBatch.Draw();
    
    //5、将后台缓冲区进行渲染,渲染结束后交换给前台
    glutSwapBuffers();
    
   
    
}


void setupRC()
{
    
    //1、设置背景颜色
    glClearColor(0.98f, 0.4f, 0.7f, 1);
    
    //2、初始化渲染管理器
    shaderManager.InitializeStockShaders();
    
    //3、顶点已经声明在公共
    
    //4、修改图元链接方式GL_TRIANGLE_FAN
    triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
    triangleBatch.CopyVertexData3f(vVerts);
    triangleBatch.End();
    
}


void SpecialKeys (int key, int x,int y)
{
    //每次移动的距离
    GLfloat stepSize = 0.05f;
    
    //拿到左上角顶点D的坐标
    GLfloat squX = vVerts[9];
    GLfloat squY = vVerts[10];
    
    if (key == GLUT_KEY_UP) {
        //向上移动,Y+size
        squY += stepSize;
    }
    
    if (key == GLUT_KEY_DOWN) {
        squY -= stepSize;
    }
    
    if (key == GLUT_KEY_RIGHT) {
        squX += stepSize;
    }
    
    if (key == GLUT_KEY_LEFT) {
        squX -= stepSize;
    }
    
    //===考虑到边界问题===
    if (squX < -1.0f) {
        squX = -1.0f;
    }
    
    if ((squX + blockSize *2) > 1.0f) {
        squX = 1.0f - blockSize*2;
    }
    
    if (squY > 1.0f) {
        squY = 1.0f;
    }
    
    if ((squY - blockSize *2) < -1.0f) {
        squY = -1.0f + blockSize *2;
    }
    
    //然后更新ABCD四个顶点
    //此时是根据D点的计算,A的Y比D的Y小 = DY-边长(边长 = blockSize*2)
    vVerts[0] = squX;
    vVerts[1] = squY - blockSize*2;
    
    vVerts[3] = squX + blockSize*2;
    vVerts[4] = squY - blockSize*2;
    
    vVerts[6] = squX + blockSize*2;
    vVerts[7] = squY;
    
    vVerts[9] = squX;
    vVerts[10] = squY;
    
    //更新数据,触发重新渲染
    triangleBatch.CopyVertexData3f(vVerts);
    glutPostRedisplay();
    
}
int main(int argc,char *argv[])
{
    //针对MAC OS X,为了更加安全,设置当前工作目录
    gltSetWorkingDirectory(argv[0]);
    
    //准备工作
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
    glutInitWindowSize(800, 600);
    glutCreateWindow("Square");
    glutReshapeFunc(changeSize);
    glutDisplayFunc(RenderScene);
    //添加新的特殊函数
    glutSpecialFunc(SpecialKeys);
    
    
    GLenum status = glewInit();
    if (GLEW_OK != status) {
        printf("GLEW Error:%s\n",glewGetErrorString(status));
        return 1;
    }
    
 
    setupRC();
    glutMainLoop();
 
    return  0;
    
}

 

矩阵方式

思考:如果一个图形有100个顶点,那坐标更新要写100次吗?
我们可以用矩阵方式修改代码进行简单实现。
并且在上述代码基础上,增加边移动边旋转效果(矩阵相乘)

我们先声明两个需要用到的参数,然后只需要修改如下2个方法就可以了。

//矩阵方法
//记录在X轴方向上偏移的距离
GLfloat xPos = 0.0f;
//记录在Y轴方向上偏移的距离
GLfloat yPos = 0.0f;
void RenderScene2(void)
{

    //1、清除一个或一组特定缓存区
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
     
    //2、设置颜色
    GLfloat vColor[] = {1.0,1.0,0.0,1.0f};
    
    //设置矩阵  平移+旋转+最终
    M3DMatrix44f mTransfrom,mRotation,mFinal;
    
    //平移
    m3dTranslationMatrix44(mTransfrom, xPos, yPos, 0.0f);
    
    //旋转  (每次平移旋转5度)
    static float yRot = 0.0f;
    yRot += 5.0f;
    m3dRotationMatrix44(mRotation, m3dDegToRad(yRot), 0.0f, 0.0f, 1.0f);
    
    //矩阵相乘拿到mFinal
    m3dMatrixMultiply44(mFinal, mTransfrom, mRotation);
    
    //3、使用着色器:GLT_SHADER_IDENTITY不够用,换成平面着色器(是一个固定着色器)
    shaderManager.UseStockShader(GLT_SHADER_FLAT,mFinal,vColor);
    
    //4、进行绘制
    triangleBatch.Draw();
    
    //5、将后台缓冲区进行渲染,渲染结束后交换给前台
    glutSwapBuffers();
    
   
    
}
void SpecialKeys2 (int key, int x,int y)
{
    //每次移动的距离
    GLfloat stepSize = 0.05f;
    
    
    if (key == GLUT_KEY_UP) {
        //向上移动,Y+size
        yPos += stepSize;
    }
    
    if (key == GLUT_KEY_DOWN) {
        yPos -= stepSize;
    }
    
    if (key == GLUT_KEY_RIGHT) {
        xPos += stepSize;
    }
    
    if (key == GLUT_KEY_LEFT) {
        xPos -= stepSize;
    }
    
    //===考虑到边界问题,碰撞检测===
    //此处xPos yPos可以看成中心点
    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;
    }
    
    //触发重新渲染
    glutPostRedisplay();
    
}

相关文章

网友评论

      本文标题:OpenGL-04-入门级案例2:绘制通过键位移动的正方形

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