美文网首页
OpenGL 球体公转+自转案例

OpenGL 球体公转+自转案例

作者: _涼城 | 来源:发表于2020-07-23 08:57 被阅读0次
    声明变量

    声明一个着色器管理器实例,为模型视图矩阵和投影矩阵声明GLMatrixStack实例,使用GLFrustum类构造投影矩阵,最后用GLGeometryTransform类声明一个管线实例管理矩阵堆栈。

    GLShaderManager shaderManager;
    GLMatrixStack modelViewMatrix;
    GLMatrixStack projectionMatrix;
    GLFrustum viewFrustum;
    GLGeometryTransform transformPipeline;
    
    初始化工程
    绘制地板
    绘制地板流程.png
    声明批次类容器实例
    GLBatch floorBatch;
    
    批次容器拷贝顶点坐标
     floorBatch.Begin(GL_LINES, 324);
        for(GLfloat x = -20.0; x <= 20.0f; x += 0.5){
            floorBatch.Vertex3f(x, -0.55f, 20.0f);
            floorBatch.Vertex3f(x, -0.55f, -20.0f);
            floorBatch.Vertex3f(20.0f, -0.55f, x);
            floorBatch.Vertex3f (-20.0f, -0.55f, x);
     }
     floorBatch.End();
    
    平面着色器绘制地板
    static GLfloat vFloorColor[] = { 0.0f,1.0f,0.0f,1.0f };
    shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor);
    floorBatch.Draw();
    
    绘制自转球
    绘制自转球流程图.png
    声明批次类容器实例
    GLTriangleBatch  torusBatch; 
    //角度
    GLfloat yRot;
    
    设置大球模型
    gltMakeSphere(torusBatch, 0.4f, 40, 80);
    
    RenderScene
      static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };
        //2.基于时间动画
      static CStopWatch    rotTimer;
      float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
        //** 压栈
      modelViewMatrix.PushMatrix();
        //4.获取光源位置
      M3DVector4f vLightPos = {0.0f,10.0f,5.0f,1.0f};
        //5.使得大球位置平移(3.0)向屏幕里面
      modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);
        //6.压栈(复制栈顶)
      modelViewMatrix.PushMatrix();
        //7.大球自转
      modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
        //8.指定合适的着色器(点光源着色器)
      shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
                                     transformPipeline.GetProjectionMatrix(), vLightPos, vTorusColor);
      torusBatch.Draw();
        //9.绘制完毕则Pop
      modelViewMatrix.PopMatrix();
      modelViewMatrix.PopMatrix();
      glutSwapBuffers();
      //提交重新渲染
      glutPostRedisplay();
    
    绘制静态球
    绘制静态球流程图.png
    声明批次类容器实例
    GLTriangleBatch sphereBatch;
    //随机球个数
    #define NUM_SPHERES 50
    //随机球顶点数组
    GLFrame spheres[NUM_SPHERES];
    
    初始化
     //设置小球模型
        gltMakeSphere(sphereBatch, 0.1f, 13, 26);
    //绘制小球顶点坐标
        for (int i = 0; i < NUM_SPHERES; i++) {
              //y轴一致
            GLfloat x = ((GLfloat)((rand() % 400) - 200) * 0.1f);
            GLfloat z = ((GLfloat)((rand() % 400) - 200) * 0.1f);
            spheres[i].SetOrigin(x,0.0f,z);
        }
    
    RenderScene
    
    /*
     绘制小球
    */
    for (int i = 0 ; i < NUM_SPHERES; i++) {
        modelViewMatrix.PushMatrix();
        modelViewMatrix.MultMatrix(spheres[I]);
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSmallSphereColor);
        sphereBatch.Draw();
        modelViewMatrix.PopMatrix();
    }
    
    绘制公转球
    绘制公转球流程图.png
    RenderScene
    /*
      绘制运动的小球
    */
        modelViewMatrix.PushMatrix();
        modelViewMatrix.Rotate(yRot * -2, 0, 1, 0);
        modelViewMatrix.Translate(0.8f, 0.0f,0.0f);
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSmallSphereColor);
        sphereBatch.Draw();
        modelViewMatrix.PopMatrix();
    
    设置特殊键位调整观察者位置
    调整观察者位置
    //移动(移动只是计算了X,Y移动的距离,以及碰撞检测)
    void SpecialKeys(int key, int x, int y)
    {
        float linear = 0.1f;
        float angular = float(m3dDegToRad(5.0f));
        if (key == GLUT_KEY_UP) {
            cameraFrame.MoveForward(linear);
        }
        if (key == GLUT_KEY_DOWN) {
            cameraFrame.MoveForward(-linear);
        }
        if (key == GLUT_KEY_LEFT) {
            cameraFrame.RotateWorld(angular, 0, 1, 0);
        }
        if (key == GLUT_KEY_RIGHT) {
           cameraFrame.RotateWorld(-angular, 0, 1, 0);
        }
    
    }
    
    渲染
     //在渲染前,调整观察者位置
     M3DMatrix44f mCamera;
     cameraFrame.GetCameraMatrix(mCamera);
     modelViewMatrix.PushMatrix(mCamera);
    
    最后附上完整代码
    
    #include "GLTools.h"
    #include "GLShaderManager.h"
    #include "math3d.h"
    #include <GLFrame.h>
    #include <GLMatrixStack.h>
    #include <GLGeometryTransform.h>
    #include <GLFrustum.h>
    #include <StopWatch.h>
    #ifdef __APPLE__
    #include <glut/glut.h>
    #else
    #define FREEGLUT_STATIC
    #include <GL/glut.h>
    #endif
    
    GLShaderManager shaderManager;
    GLMatrixStack modelViewMatrix;
    GLMatrixStack projectionMatrix;
    GLFrustum viewFrustum;
    GLGeometryTransform transformPipeline;
    GLTriangleBatch torusBatch;
    GLTriangleBatch sphereBatch;
    
    GLBatch floorBatch;
    GLfloat yRot;
    
    //观察者
    GLFrame cameraFrame;
    
    //随机球
    #define NUM_SPHERES 50
    GLFrame spheres[NUM_SPHERES];
    
    void SetupRC()
    {
         //设置清屏颜色(背景颜色)
        glClearColor(0.0f, 0.0f, 0.0f, 1);
        //没有着色器,在OpenGL 核心框架中是无法进行任何渲染的。初始化一个渲染管理器。
        //在前面的课程,我们会采用固管线渲染,后面会学着用OpenGL着色语言来写着色器
        shaderManager.InitializeStockShaders();
    
        //投影变换矩阵 & 移动变换矩阵  > 变换管道 > 快速去矩阵相乘 > 遍历
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
    
        //绘制地板
        floorBatch.Begin(GL_LINES, 324);
        for(GLfloat x = -20.0; x <= 20.0f; x += 0.5){
            floorBatch.Vertex3f(x, -0.55f, 20.0f);
            floorBatch.Vertex3f(x, -0.55f, -20.0f);
            floorBatch.Vertex3f(20.0f, -0.55f, x);
            floorBatch.Vertex3f (-20.0f, -0.55f, x);
        }
        floorBatch.End();
    
        //绘制大球
        gltMakeSphere(torusBatch, 0.4f, 40, 80);
    
        //绘制小球本身坐标
        gltMakeSphere(sphereBatch, 0.1f, 13, 26);
        //绘制小球顶点坐标
        for (int i = 0; i < NUM_SPHERES; i++) {
              //y轴一致
            GLfloat x = ((GLfloat)((rand() % 400) - 200) * 0.1f);
            GLfloat z = ((GLfloat)((rand() % 400) - 200) * 0.1f);
            spheres[i].SetOrigin(x,0.0f,z);
        }
    
    }
    
    //移动(移动只是计算了X,Y移动的距离,以及碰撞检测)
    void SpecialKeys(int key, int x, int y)
    {
        float linear = 0.1f;
        float angular = float(m3dDegToRad(5.0f));
        if (key == GLUT_KEY_UP) {
            cameraFrame.MoveForward(linear);
        }
        if (key == GLUT_KEY_DOWN) {
            cameraFrame.MoveForward(-linear);
        }
        if (key == GLUT_KEY_LEFT) {
            cameraFrame.RotateWorld(angular, 0, 1, 0);
        }
        if (key == GLUT_KEY_RIGHT) {
           cameraFrame.RotateWorld(-angular, 0, 1, 0);
        }
    
    }
    
    //进行调用以绘制场景
    void RenderScene(void)
    {
    
        static GLfloat vFloorColor[] = { 0.0f,1.0f,0.0f,1.0f };
        static GLfloat vBigSphereColor[] = {1.0f,0.0f,0.0f,1.0f};
        static GLfloat vSmallSphereColor[] = {0.0f,0.0f,1.0f,1.0f};
        //定时器
        static CStopWatch rotTimer;
        float yRot = rotTimer.GetElapsedSeconds() * 60.f;
    
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        //    //颜色值
         glEnable(GL_DEPTH_TEST);
        M3DVector4f vLightPos = {
            0.0,10.0,5.0,1.0
         };
        modelViewMatrix.PushMatrix();
        M3DMatrix44f mCamera;
        cameraFrame.GetCameraMatrix(mCamera);
        modelViewMatrix.PushMatrix(mCamera);
    //    //基于时间的动画
        shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor);
        floorBatch.Draw();
    
    //    //绘制旋转的
        modelViewMatrix.Translate(0.0, 0.0, -3.0f);
        modelViewMatrix.PushMatrix();
        modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
    
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vBigSphereColor);
        torusBatch.Draw();
        //出栈
        modelViewMatrix.PopMatrix();
    
        /*
         绘制小球
         */
        for (int i = 0 ; i < NUM_SPHERES; i++) {
            modelViewMatrix.PushMatrix();
            modelViewMatrix.MultMatrix(spheres[I]);
            shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSmallSphereColor);
            sphereBatch.Draw();
            modelViewMatrix.PopMatrix();
        }
    
        /*
         绘制运动的小球
         */
        modelViewMatrix.PushMatrix();
        modelViewMatrix.Rotate(yRot * -2, 0, 1, 0);
        modelViewMatrix.Translate(0.8f, 0.0f,0.0f);
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSmallSphereColor);
        sphereBatch.Draw();
        modelViewMatrix.PopMatrix();
    
        //出栈
        modelViewMatrix.PopMatrix();
        modelViewMatrix.PopMatrix();
        glDisable(GL_DEPTH_TEST);
        glutSwapBuffers();
        glutPostRedisplay();
    }
    
    // 屏幕改变大小或初始化
    void ChangeSize(int w, int h)
    {
        glViewport(0, 0, w, h);
        //创建投影矩阵,并将它载入投影矩阵堆栈中
        viewFrustum.SetPerspective(35.0f, float(w) / (float)h, 1.0f, 100.0f);
        projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
        //设置变换管线以使用两个矩阵堆栈
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
    }
    
    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 球体公转+自转案例

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