美文网首页iOS视觉
十五 OpenGL 案例分析(公转/自转)

十五 OpenGL 案例分析(公转/自转)

作者: 王俏 | 来源:发表于2020-08-05 08:39 被阅读0次

    显示效果

    image

    实现流程

    image

    重要函数功能分析

    • 重塑函数 changeSize
    image
    • 显示函数 RenderScene
    image
    • 功能按键函数 SpecialKeys
    image

    源码分析

    
    #include "GLTools.h"
    #include "GLShaderManager.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;// 几何图形变换管道
    
    
    //简单的批次容器,是GLTools的一个简单的容器类。
    GLBatch floorBatch;
    GLTriangleBatch torusBatch;
    GLTriangleBatch sphereBatch;
    
    #define NUM_SPHERE 50
    GLFrame sphere[NUM_SPHERE]; //GLFrame ->#include "GLFrustum.h"
    
        //角色帧 照相机角色帧
    GLFrame   cameraFrame;
    GLFrame  objectFrame; //物体角色帧
    
    /*
     在窗口大小改变时,接收新的宽度&高度。
     */
    void changeSize(int w,int h)
    {
        if(h ==0){
            h = 1;
        }
        /*
          设置视口
         x,y 参数代表窗口中视图的左下角坐标,而宽度、高度是像素为表示,通常x,y 都是为0
         */
        glViewport(0, 0, w, h);
    
        //投影矩阵
        viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0, 100.0f);
        projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    
        //初始化变换管道
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
        
    }
    
    void RenderScene(void)
    {
    
    
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    
            //1. 颜色(地板,大球颜色,小球颜色)
        static GLfloat vFloorColor[] = {0.0f,1.0f,0.0f,1.0f};
        static GLfloat vTorusColor[] = {1.0f,0.0f,0.0f,1.0f};
        static GLfloat vSpereColor[] = {0.0f,0.0f,1.0f,1.0f};
        static GLfloat vBigSpereColor[] = {0.0f,0.6f,1.0f,0.8f};
    
        //设置点光源位置
        M3DVector4f vLightPos = {0,10,5,1};
    
        //动画
        static CStopWatch rotTimer;
        float yRot = rotTimer.GetElapsedSeconds()*60.0f;
    
        //单元矩阵
        modelViewMatrix.PopMatrix();
    
    
        //观察者角色帧矩阵入栈
        M3DMatrix44f mCamera;
        cameraFrame.GetCameraMatrix(mCamera);
        modelViewMatrix.PushMatrix(mCamera);
    
        //绘制地板
        shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor);
        floorBatch.Draw();
    
        //平移模型视图矩阵,往里平移3个单位
        modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);
    
        //绘制大球 及自转
        modelViewMatrix.PushMatrix();
        modelViewMatrix.Rotate(yRot, 0, 1.0, 0);
        //点光源着色器
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vTorusColor);
        torusBatch.Draw();
        modelViewMatrix.PopMatrix();
    
        //绘制小球
        for(int i = 0 ; i < NUM_SPHERE; i++){
            modelViewMatrix.PushMatrix();
            modelViewMatrix.MultMatrix(sphere[i]);
            shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSpereColor);
            sphereBatch.Draw();
            modelViewMatrix.PopMatrix();
        }
    
        //小球围着大球公转;
        modelViewMatrix.Rotate(yRot * -2.0f, 0, 1, 0);
        modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vBigSpereColor);
        sphereBatch.Draw();
    
        modelViewMatrix.PopMatrix();
        modelViewMatrix.PopMatrix();
        glutSwapBuffers();
        glutPostRedisplay();
    
        
    }
    
    void setupRC()
    {
        //设置清屏颜色(背景颜色)
       glClearColor(0, 0, 0, 1);
        
        
        //没有着色器,在OpenGL 核心框架中是无法进行任何渲染的。初始化一个渲染管理器。
        shaderManager.InitializeStockShaders();
    
        //开启深度测试
        glEnable(GL_DEPTH_TEST);
    
    //    地板数据
        
        floorBatch.Begin(GL_LINES, 324); //[-20,20]以0.5的步进,横向和纵向每个方向81条线段,每条线段连个顶点 ;所有定点数是81*2*2=324
        for(GLfloat x = -20.0; x <= 20.0f; x+= 0.5) {
            //平行于x轴的线段
            floorBatch.Vertex3f(x, -0.55f, 20.0f);
            floorBatch.Vertex3f(x, -0.55f, -20.0f);
    
            //平行于z轴的线段
            floorBatch.Vertex3f(20.0f, -0.55f, x);
            floorBatch.Vertex3f(-20.0f, -0.55f, x);
        }
        floorBatch.End();
    
    
            //设置一个球体(基于gltools模型)
        gltMakeSphere(torusBatch, 0.4f, 40, 80);
    
            //绘制小球;
        gltMakeSphere(sphereBatch, 0.1f, 20, 40);
    
        //随机放置小球
        for(int i = 0; i < NUM_SPHERE;i++){
                //y轴不变,X,Z产生随机值
            GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
            GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
    
                //对spheres数组中的每一个顶点,设置顶点数据
            sphere[i].SetOrigin(x,0.0,z);
        }
        
    }
    
    void SpecialKeys(int key, int x, int y){
        float linner  = 0.2f;
        float arg = float(m3dDegToRad(5.0)); //#include "math3d.h"
        if(key == GLUT_KEY_UP){
            cameraFrame.MoveForward(linner);
        }
        if(key == GLUT_KEY_DOWN){
            cameraFrame.MoveForward(-linner);
        }
        if(key == GLUT_KEY_LEFT){
            cameraFrame.RotateLocal(arg, 0, 1.0, 0);
        }
        if(key == GLUT_KEY_RIGHT){
            cameraFrame.RotateLocal(-arg, 0, 1.0, 0);
        }
    }
    
    int main(int argc,char *argv[])
    {
    
        //初始化GLUT库,这个函数只是传说命令参数并且初始化glut库
        glutInit(&argc, argv);
        
    
       glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
        
        //GLUT窗口大小、窗口标题
        glutInitWindowSize(800, 600);
        glutCreateWindow("Triangle");
        
    
        //注册重塑函数
        glutReshapeFunc(changeSize);
        //注册显示函数
        glutDisplayFunc(RenderScene);
        //注册功能按键函数
        glutSpecialFunc(SpecialKeys);
    
        /*
         初始化一个GLEW库,确保OpenGL API对程序完全可用。
         在试图做任何渲染之前,要检查确定驱动程序的初始化过程中没有任何问题
         */
        GLenum status = glewInit();
        if (GLEW_OK != status) {
            
            printf("GLEW Error:%s\n",glewGetErrorString(status));
            return 1;
            
        }
        
        //设置我们的渲染环境
        setupRC();
        glutMainLoop();
     
        return  0;
        
    }
    
    

    相关文章

      网友评论

        本文标题:十五 OpenGL 案例分析(公转/自转)

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