美文网首页
5.综合案例

5.综合案例

作者: bytebytebyte | 来源:发表于2020-11-26 09:24 被阅读0次
    #include "GLShaderManager.h"
    #include "GLTools.h"
    #include "GLFrustum.h"
    #include "GLBatch.h"
    #include "GLMatrixStack.h"
    #include "GLGeometryTransform.h"
    #include "StopWatch.h"
    
    #include <math.h>
    #include <stdio.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;                      //地板
    GLFrame cameraFrame;                     //照相机角色帧
    //添加附加随机球
    #define NUM_SPHERES 50
    GLFrame spheres[NUM_SPHERES];
    
    //为程序做一次性的设置
    void setupRC() {
        //1.初始化
        glClearColor(0, 0, 0, 1);
        shaderManager.InitializeStockShaders();
        
        //2.开启深度测试
        glEnable(GL_DEPTH_TEST);
        
        //3.设置地板顶点数据
        floorBatch.Begin(GL_LINES, 324);
        for (GLfloat x = -20; x <= 20; x += 0.5) {
            floorBatch.Vertex3f(x, -0.55, 20);
            floorBatch.Vertex3f(x, -0.55, -20);
            floorBatch.Vertex3f(20, -0.55, x);
            floorBatch.Vertex3f(-20, -0.55, x);
        }
        floorBatch.End();
        
        //4.设置打球模型
        gltMakeSphere(torusBatch, 0.4, 40, 80);
        
        //5.设置小球模型
        gltMakeSphere(sphereBatch, 0.1, 26, 13);
        
        //6.随机位置放置小球
        for (int i = 0; i < NUM_SPHERES; i ++) {
            //y轴不变,X,Z产生随机值
            GLfloat x = ((GLfloat)(rand() % 400 - 200)) * 0.1;
            GLfloat z = ((GLfloat)(rand() % 400 - 200)) * 0.1;
            //在y方向,将球体设置为0,0的位置,这使得它们看起来是漂浮在眼镜的高度
            //对spheres数组中的每一个顶点,设置顶点数据
            spheres[i].SetOrigin(x, 0, z);
        }
    }
    
    //绘制场景
    void renderScene(void) {
        //1.颜色值
        static GLfloat vFloorColor[] = { 0, 1, 0, 1 };
        static GLfloat vTorusColor[] = { 1, 0, 0, 1 };
        static GLfloat vSphereColor[] = { 0, 0, 1, 1 };
        
        //2.基于时间动画
        static CStopWatch rotTimer;
        float yRot = rotTimer.GetElapsedSeconds() * 60;
        
        //3.清除时间缓冲区和深度缓冲区
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        //4.加入观察者平移10步(地板,打球,小球,小小球)
        M3DMatrix44f mCamera;
        cameraFrame.GetCameraMatrix(mCamera);
        modelViewMatrix.PushMatrix(mCamera);
        
        //5.获取光源位置
        M3DVector4f vLightPos = { 0, 10, 5, 1 };
        
        //6.绘制地面
        shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vFloorColor);
        floorBatch.Draw();
        
        //打球默认位置是(0,0,0)Z深度(3)正负指的是方向,数字指的是移动距离
        //7.使得大球位置平移(3)向屏幕里面,只移动一次
        modelViewMatrix.Translate(0, 0, -3);
        
        //8.压栈(复制栈顶)
        modelViewMatrix.PushMatrix();
        
        //9.大球自转
        modelViewMatrix.Rotate(yRot, 0, 1, 0);
        
        //10.指定合适的着色器,点光源着色器
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vLightPos, vTorusColor);
        torusBatch.Draw();
        
        //11.绘制完毕pop
        modelViewMatrix.PopMatrix();
        
        //12.画小球
        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, vSphereColor);
            sphereBatch.Draw();
            modelViewMatrix.PopMatrix();
        }
        
        //13.让一个小球围绕打球公转自转
        //为何这里没加PushMatrix/PopMatrix?可以加,因为是最后的绘图因为没有不会影响就没有添加
        modelViewMatrix.PushMatrix();
        
        modelViewMatrix.Rotate(yRot * -2, 0, 1, 0);
        modelViewMatrix.Translate(0.8, 0, 0);
        shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vSphereColor);
        sphereBatch.Draw();
        
        modelViewMatrix.PopMatrix();
        
        modelViewMatrix.PopMatrix();
        
        glutSwapBuffers();
        glutPostRedisplay();
        
    }
    
    //窗口改变时接受新的宽度和高度,0,0代表窗口中视口的左下角坐标,w,h代表像素
    void ChangeSize(int w, int h) {
        //1.设置视口
        glViewport(0, 0, w, h);
        
        //2.创建投影矩阵并加载到投影矩阵堆栈中
        viewFrustum.SetPerspective(35, float(w) / float(h), 1, 100);
        projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
        
        //3.这个操作也可以在SetupRC 函数中完成,但是在窗口大小改变时或者窗口创建时设置它们并没有坏处。而且这样可以一次性完成矩阵和管线的设置。
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
    }
    
    void specialKeys(int key, int x, int y) {
        //移动步长
        float linear = 0.1;
        //旋转度数
        float angular = float(m3dDegToRad(5));
        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);
        }
    }
    
    int main(int argc, char *argv[]) {
        gltSetWorkingDirectory(argv[0]);
        
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
        glutInitWindowSize(800, 600);
        glutCreateWindow("OpenGL SphereWorld");
        
        glutReshapeFunc(ChangeSize);
        glutDisplayFunc(renderScene);
        glutSpecialFunc(specialKeys);
        GLenum err = glewInit();
        if (err != GLEW_OK) {
            fprintf(stderr, "GLEW Error:%s\n",glewGetErrorString(err));
            return 1;
        }
        setupRC();
        glutMainLoop();
        
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:5.综合案例

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