美文网首页OpenGL
OpenGL 点/面/立体图绘制

OpenGL 点/面/立体图绘制

作者: 夏天的枫_ | 来源:发表于2020-07-21 10:26 被阅读0次

    准备工作:预先搭建好的OpenGL环境工程;(包含:glew文件、libGLTools.a)

    1.新建C++ File,导入相关头文件

    #include "GLTools.h"    // OpenGL  工具类
    #include "GLMatrixStack.h" // 矩阵堆栈类
    #include "GLFrame.h" // 矩阵变换类
    #include "GLFrustum.h" // 投影矩阵
    #include "GLBatch.h" // 各种容器类(点、线、线环、三角形等)
    #include "GLGeometryTransform.h" // 几何变换管道
    

    2.编码流程及思路


    编码流程集思录
    • 上代码
    #include <math.h>
    #ifdef __APPLE__
    #include <glut/glut.h>
    #else
    #define FREEGLUT_STATIC
    #include <GL/glut.h>
    #endif
    
    /*
     GLMatrixStack 变化管线使用矩阵堆栈
     GLMatrixStack 构造函数允许指定堆栈的最大深度、默认的堆栈深度为64.这个矩阵堆在初始化时已经在堆栈中包含了单位矩阵。
     GLMatrixStack::GLMatrixStack(int iStackDepth = 64);
     //通过调用顶部载入这个单位矩阵
     void GLMatrixStack::LoadIndentiy(void);
     //在堆栈顶部载入任何矩阵
     void GLMatrixStack::LoadMatrix(const M3DMatrix44f m);
     */
    // 各种需要的类
    GLShaderManager     shaderManager;
    GLMatrixStack       modelViewMatrix;
    GLMatrixStack       projectionMatrix;
    GLFrame             cameraFrame;
    GLFrame             objectFrame;
    //投影矩阵
    GLFrustum           viewFrustum;
    
    //容器类(7种不同的图元对应7种容器对象)
    GLBatch             pointBatch;
    GLBatch             lineBatch;
    GLBatch             lineStripBatch;
    GLBatch             lineLoopBatch;
    GLBatch             triangleBatch;
    GLBatch             triangleStripBatch;
    GLBatch             triangleFanBatch;
    
    //几何变换的管道
    GLGeometryTransform transformPipeline;
    
    GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };
    GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    
    
    // 跟踪效果步骤
    int nStep = 0;
    
    // 初始化场景(只做一次)
    void SetupRC()
    {
        // 灰色的背景
        glClearColor(0.7f, 0.7f, 0.7f, 1.0f );
        shaderManager.InitializeStockShaders();
        glEnable(GL_DEPTH_TEST);
        //设置变换管线以使用两个矩阵堆栈
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
        cameraFrame.MoveForward(-30.0f);
        
        /*
         常见函数:
         void GLBatch::Begin(GLenum primitive,GLuint nVerts,GLuint nTextureUnits = 0);
          参数1:表示使用的图元
          参数2:顶点数
          参数3:纹理坐标(可选)
         //复制顶点坐标
         void GLBatch::CopyVertexData3f(GLFloat *vNorms);
         //结束,表示已经完成数据复制工作
         void GLBatch::End(void);
         */
        //定义一些点,三角形形状。
       
        GLfloat vCoast[9] = {
            3,3,0,0,3,0,3,0,0
            
        };
        
        //用点的形式
        pointBatch.Begin(GL_POINTS, 3);
        pointBatch.CopyVertexData3f(vCoast);
        pointBatch.End();
    
    }
    
    // 召唤场景
    void RenderScene()
    {
        // Clear the window with current clearing color
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
       
        //压栈
        modelViewMatrix.PushMatrix();
        M3DMatrix44f mCamera;
        cameraFrame.GetCameraMatrix(mCamera);
        
        //矩阵乘以矩阵堆栈的顶部矩阵,相乘的结果随后简存储在堆栈的顶部
        modelViewMatrix.MultMatrix(mCamera);
        
        M3DMatrix44f mObjectFrame;
        //只要使用 GetMatrix 函数就可以获取矩阵堆栈顶部的值,这个函数可以进行2次重载。用来使用GLShaderManager 的使用。或者是获取顶部矩阵的顶点副本数据
        objectFrame.GetMatrix(mObjectFrame);
        
        //矩阵乘以矩阵堆栈的顶部矩阵,相乘的结果随后简存储在堆栈的顶部
        modelViewMatrix.MultMatrix(mObjectFrame);
        
        /* GLShaderManager 中的Uniform 值——平面着色器
         参数1:平面着色器
         参数2:运行为几何图形变换指定一个 4 * 4变换矩阵
         --transformPipeline.GetModelViewProjectionMatrix() 获取的
         GetMatrix函数就可以获得矩阵堆栈顶部的值
         参数3:颜色值(黑色)
         */
        shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
        
        switch(nStep) {
            case 0:
                //设置点的大小
                glPointSize(4.0f);
                pointBatch.Draw();
                glPointSize(1.0f);
                break;
        }
        
        //还原到以前的模型视图矩阵(单位矩阵)
        modelViewMatrix.PopMatrix();
        
        // 进行缓冲区交换
        glutSwapBuffers();
    }
    
    
    //特殊键位处理(上、下、左、右移动)
    void SpecialKeys(int key, int x, int y)
    {
        
        if(key == GLUT_KEY_UP)
            //围绕一个指定的X,Y,Z轴旋转。
            objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);
        
        if(key == GLUT_KEY_DOWN)
            objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);
        
        if(key == GLUT_KEY_LEFT)
            objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
        
        if(key == GLUT_KEY_RIGHT)
            objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
        
        glutPostRedisplay();
    }
    
    
    
    
    //根据空格次数。切换不同的“窗口名称”
    void KeyPressFunc(unsigned char key, int x, int y)
    {
        if(key == 32)
        {
            nStep++;
            
            if(nStep > 6)
                nStep = 0;
        }
        
        switch(nStep)
        {
            case 0:
                glutSetWindowTitle("GL_POINTS");
                break;
            case 1:
                glutSetWindowTitle("GL_LINES");
                break;
            case 2:
                glutSetWindowTitle("GL_LINE_STRIP");
                break;
            case 3:
                glutSetWindowTitle("GL_LINE_LOOP");
                break;
            case 4:
                glutSetWindowTitle("GL_TRIANGLES");
                break;
            case 5:
                glutSetWindowTitle("GL_TRIANGLE_STRIP");
                break;
            case 6:
                glutSetWindowTitle("GL_TRIANGLE_FAN");
                break;
        }
        
        glutPostRedisplay();
    }
    
    
    // 窗口已更改大小,或刚刚创建。无论哪种情况,我们都需要
    // 使用窗口维度设置视口和投影矩阵.
    void ChangeSize(int w, int h)
    {
        glViewport(0, 0, w, h);
        //创建投影矩阵,并将它载入投影矩阵堆栈中
        viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 500.0f);
        projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
        
        //调用顶部载入单元矩阵
        modelViewMatrix.LoadIdentity();
    }
    
    
    int main(int argc, char* argv[])
    {
        gltSetWorkingDirectory(argv[0]);
        glutInit(&argc, argv);
        //申请一个颜色缓存区、深度缓存区、双缓存区、模板缓存区
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
        //设置window 的尺寸
        glutInitWindowSize(800, 600);
        //创建window的名称
        glutCreateWindow("GL_POINTS");
        //注册回调函数(改变尺寸)
        glutReshapeFunc(ChangeSize);
        //点击空格时,调用的函数
        glutKeyboardFunc(KeyPressFunc);
        //特殊键位函数(上下左右)
        glutSpecialFunc(SpecialKeys);
        //显示函数
        glutDisplayFunc(RenderScene);
        
        //判断一下是否能初始化glew库,确保项目能正常使用OpenGL 框架
        GLenum err = glewInit();
        if (GLEW_OK != err) {
            fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
            return 1;
        }
        
        //绘制
        SetupRC();
        
        //runloop运行循环
        glutMainLoop();
        return 0;
    }
    
    

    相关文章

      网友评论

        本文标题:OpenGL 点/面/立体图绘制

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