美文网首页
OpenGL学习之路(5.0) 三角形批次类案例

OpenGL学习之路(5.0) 三角形批次类案例

作者: velue | 来源:发表于2019-03-04 22:56 被阅读0次

    通过三角形批次类画图形示例

    • 球体
    //球
        /**
         gltMakeSphere(GLTriangleBatch &sphereBatch, GLfloat fRadius, GLint iSlices, GLint iStacks)
         参数一:sphereBatch 三角形批次类对象
         参数二:fRadius , 球体半径
         参数三:iSlices   从球体底部堆叠到顶部的三角形带的数量;其实s球体是一圈一圈三角形带组成
         参数四:iStacks   围绕球体一圈排列的三角形对数
         
         建议:一个对称性较好的球体的片段数量是堆叠数量的2倍,就是iStacks = 2 * iSlices;
         绘制球体都是围绕Z轴,这样+z就是球体的顶点,-z就是球体的底部。
         */
        gltMakeSphere(sphereBatch, 3.0, 10, 20);
    
    
    image.png
    • 环面
    
    //环面
        /**
         gltMakeTorus(GLTriangleBatch &torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor)
         参数一:torusBatch : 三角形批次类对象
         参数二:majorRadius :甜甜圈中心到外边缘的半径
         参数三:minorRadius :甜甜圈中心到内边缘的半径
         参数四:numMajor   : 沿着主半径的三角形数量
         参数五:numMinor   : 沿着内部较小半径的三角形数量
         
         */
        gltMakeTorus(torusBatch, 3.0f, 0.75f, 15, 15);
    
    
    image.png
    • 圆柱
    
    //圆柱
        /**
         gltMakeCylinder(GLTriangleBatch &cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks)
         参数一:cylinderBatch:三角形批次对象
         参数二:baseRadius:   底部半径
         参数三:topRadius:    头部半径
         参数四:fLength        圆形长度
         参数五:numSlices:    围绕Z轴的三角形对的数量
         参数六:numStacks:    圆柱底部堆叠到顶部圆环的三角形数量
         */
        gltMakeCylinder(cylinderBatch, 2.0f, 2.0, 3.0f, 13, 2);
    
    
    image.png
    • 圆锥体
    
     //锥体
        /**
         gltMakeCylinder(GLTriangleBatch &cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks)
         参数一:cylinderBatch:三角形批次对象
         参数二:baseRadius:   底部半径
         参数三:topRadius:    头部半径
         参数四:fLength        圆形长度
         参数五:numSlices:    围绕Z轴的三角形对的数量
         参数六:numStacks:    圆柱底部堆叠到顶部圆环的三角形数量
         */
        //圆柱体,从0开始向Z轴正方向延伸。
        //圆锥体,是一端的半径为0,另一端半径可指定。
        gltMakeCylinder(coneBatch, 2.0f, 0.0, 3.0f, 13, 2);
    
    
    image.png
    • 磁盘
    
        //磁盘
        /**
        gltMakeDisk(GLTriangleBatch &diskBatch, GLfloat innerRadius, GLfloat outerRadius, GLint nSlices, GLint nStacks)
         参数一:diskBatch  三角形批次类对象
         参数二:innerRadius    内圆半径
         参数三:outerRadius    外圆半径
         参数四:nSlices        圆盘围绕Z轴的三角形对的数量
         参数五:nStacks。      圆盘外网到内为的三角形数量
         */
        gltMakeDisk(diskBatch, 1.5, 3.0f, 13, 3);
    
    
    image.png

    代码案例

    • 该代码案例需要搭建OpenGL环境
    #include "GLTools.h"    // OpenGL toolkit
    #include "GLMatrixStack.h"
    #include "GLFrame.h"
    #include "GLFrustum.h"
    #include "GLBatch.h"
    #include "GLGeometryTransform.h"
    #include "StopWatch.h"
    
    #include <math.h>
    #ifdef __APPLE__
    #include <glut/glut.h>
    #else
    #define FREEGLUT_STATIC
    #include <GL/glut.h>
    #endif
    
    
    GLShaderManager     shaderManager;
    //模型视图矩阵堆栈
    GLMatrixStack       modelViewMatrix;
    
    //投影视图矩阵堆栈
    GLMatrixStack       projectionMatrix;
    
    //观察者位置
    GLFrame             cameraFrame;
    
    //世界坐标位置
    GLFrame             objectFrame;
    
    //视景体,用来构造投影矩阵
    GLFrustum           viewFrustum;
    
    //三角形批次类
    GLTriangleBatch     CC_Triangle;
    //球
    GLTriangleBatch     sphereBatch;
    //环
    GLTriangleBatch     torusBatch;
    //圆柱
    GLTriangleBatch     cylinderBatch;
    //锥
    GLTriangleBatch     coneBatch;
    //磁盘
    GLTriangleBatch     diskBatch;
    
    //管道,用来管理投影视图矩阵堆栈和模型视图矩阵堆栈的
    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;
    
    //2
    // 将上下文中,进行必要的初始化
    void SetupRC()
    {
        //清理屏幕颜色
        glClearColor(0.7f, 0.7f, 0.7f, 1.f);
        
        //初始化固定着色管理器
        shaderManager.InitializeStockShaders();
        
        //当渲染立体图形的时,开启深度测试
        glEnable(GL_DEPTH_TEST);
        
        //通过GLGeometryTransform管理矩阵
        //使用transformPipeline管道管理模型视图矩阵和投影矩阵
        transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
        
        //将观察者坐标位置Z移动往屏幕里移动15个单位位置
        //表示离l屏幕之间的距离 负数、是往屏幕后面移动;正数代表往屏幕前面移动
        cameraFrame.MoveForward(-15);
        
        //例如三角形批次类构造图形对象
        //球
        /**
         gltMakeSphere(GLTriangleBatch &sphereBatch, GLfloat fRadius, GLint iSlices, GLint iStacks)
         参数一:sphereBatch 三角形批次类对象
         参数二:fRadius , 球体半径
         参数三:iSlices   从球体底部堆叠到顶部的三角形带的数量;其实s球体是一圈一圈三角形带组成
         参数四:iStacks   围绕球体一圈排列的三角形对数
         
         建议:一个对称性较好的球体的片段数量是堆叠数量的2倍,就是iStacks = 2 * iSlices;
         绘制球体都是围绕Z轴,这样+z就是球体的顶点,-z就是球体的底部。
         */
        gltMakeSphere(sphereBatch, 3.0, 10, 20);
        
        //环面
        /**
         gltMakeTorus(GLTriangleBatch &torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor)
         参数一:torusBatch : 三角形批次类对象
         参数二:majorRadius :甜甜圈中心到外边缘的半径
         参数三:minorRadius :甜甜圈中心到内边缘的半径
         参数四:numMajor   : 沿着主半径的三角形数量
         参数五:numMinor   : 沿着内部较小半径的三角形数量
         
         */
        gltMakeTorus(torusBatch, 3.0f, 0.75f, 15, 15);
        
        //圆柱
        /**
         gltMakeCylinder(GLTriangleBatch &cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks)
         参数一:cylinderBatch:三角形批次对象
         参数二:baseRadius:   底部半径
         参数三:topRadius:    头部半径
         参数四:fLength        圆形长度
         参数五:numSlices:    围绕Z轴的三角形对的数量
         参数六:numStacks:    圆柱底部堆叠到顶部圆环的三角形数量
         */
        gltMakeCylinder(cylinderBatch, 2.0f, 2.0, 3.0f, 13, 2);
        
    
        
        //锥体
        /**
         gltMakeCylinder(GLTriangleBatch &cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks)
         参数一:cylinderBatch:三角形批次对象
         参数二:baseRadius:   底部半径
         参数三:topRadius:    头部半径
         参数四:fLength        圆形长度
         参数五:numSlices:    围绕Z轴的三角形对的数量
         参数六:numStacks:    圆柱底部堆叠到顶部圆环的三角形数量
         */
        //圆柱体,从0开始向Z轴正方向延伸。
        //圆锥体,是一端的半径为0,另一端半径可指定。
        gltMakeCylinder(coneBatch, 2.0f, 0.0, 3.0f, 13, 2);
        
        //磁盘
        /**
        gltMakeDisk(GLTriangleBatch &diskBatch, GLfloat innerRadius, GLfloat outerRadius, GLint nSlices, GLint nStacks)
         参数一:diskBatch  三角形批次类对象
         参数二:innerRadius    内圆半径
         参数三:outerRadius    外圆半径
         参数四:nSlices        圆盘围绕Z轴的三角形对的数量
         参数五:nStacks。      圆盘外网到内为的三角形数量
         */
        gltMakeDisk(diskBatch, 1.5, 3.0f, 13, 3);
    }
    
    //4
    void DrawWireFramedBatch(GLTriangleBatch* pBatch)
    {
        //平面着色器管理器
        shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
        
        //传过来的参数,对应不同的图形Batch
        pBatch->Draw();
        
        //画出黑色轮廓
        glPolygonOffset(-1.0f, -1.0f);
        //开启处理线
        glEnable(GL_LINE_SMOOTH);
        
        //开启混合功能
        glEnable(GL_BLEND);
        
        //颜色混合
        //表示源颜色乘以自身的alpha 值,目标颜色乘以1.0减去源颜色的alpha值,这样一来,源颜色的alpha值越大,则产生的新颜色中源颜色所占比例就越大,而目标颜色所占比例则减 小。这种情况下,我们可以简单的将源颜色的alpha值理解为“不透明度”。这也是混合时最常用的方式。
        //设置混合方程式
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        
        //通过程序点大小模式来设置点的大小
        glEnable(GL_POLYGON_OFFSET_LINE);
        
        //多变形模型(背面,线)将多边形背面设为线框模式
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        
        //线条宽度
        glLineWidth(2.5f);
        
        //平面着色器绘制线条
        shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(),vBlack);
        
        pBatch->Draw();
        
        //恢复多边形模式和深度测试
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glDisable(GL_POLYGON_OFFSET_LINE);
        glLineWidth(1.0f);
        glDisable(GL_BLEND);
        glDisable(GL_LINE_SMOOTH);
    
    }
    
    //3
    //召唤场景
    void RenderScene(void)
    {
        //用当前清理颜色清除窗口背景
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        
        //模型视图矩阵堆栈,压栈
        modelViewMatrix.PushMatrix();
        //获取摄像头矩阵
        M3DMatrix44f mCamera;
        //从camereaFrame中获取矩阵到mCamera
        cameraFrame.GetCameraMatrix(mCamera);
        //模型视图堆栈的矩阵与mCamera矩阵相乘之后,储存到modelViewMatrix矩阵堆栈中
        modelViewMatrix.MultMatrix(mCamera);
        
        //创建矩阵mObjectFrame
        M3DMatrix44f mObjectFrame;
        //从ObjectFrame 获取矩阵到mObjectFrame中
        objectFrame.GetMatrix(mObjectFrame);
        //将modelViewMatrix的堆栈中的矩阵与 mObjectFrame 矩阵相乘,存储到modelViewMatrix矩阵堆栈中
        modelViewMatrix.MultMatrix(mObjectFrame);
        
        //然后使用平面着色器
        /**
         参数一:GLT_SHADER_FLAT 平面着色器
         参数二:通过transformPipeline获取模型视图矩阵
         参数三:颜色
         */
        shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
        
        //判断你目前是绘制第几个图形
        switch (nStep) {
            case 0:
                DrawWireFramedBatch(&sphereBatch); //球体
                break;
            case 1:
                DrawWireFramedBatch(&torusBatch);//环面
                break;
            case 2:
                DrawWireFramedBatch(&cylinderBatch);//圆体
                break;
            case 3:
                DrawWireFramedBatch(&coneBatch);//锥体
                break;
            case 4:
                DrawWireFramedBatch(&diskBatch); // 磁盘
                break;
        }
        //前面压栈了,需要出栈
        modelViewMatrix.PopMatrix();
        
        glutSwapBuffers();
    }
    
    //1
    void ChangeSize(int w, int h)
    {
        //设置窗口尺寸
        glViewport(0, 0, w, h);
        
        //设置投影矩阵
        viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 500.f);
        
        //获取并加载投影矩阵
        projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
        
        //modelViewMatrix 矩阵堆栈 加载单元矩阵
        modelViewMatrix.LoadIdentity();
    }
    
    
    //上下左右,移动图形
    void SpecialKeys(int key, int x, int y)
    {
        if(key == GLUT_KEY_UP)
            //移动世界坐标系,而不是去移动物体。
            //将世界坐标系在X方向移动-5.0
            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 > 4)
                nStep = 0;
        }
        
        switch(nStep)
        {
            case 0:
                glutSetWindowTitle("Sphere");
                break;
            case 1:
                glutSetWindowTitle("Torus");
                break;
            case 2:
                glutSetWindowTitle("Cylinder");
                break;
            case 3:
                glutSetWindowTitle("Cone");
                break;
            case 4:
                glutSetWindowTitle("Disk");
                break;
        }
        
        glutPostRedisplay();
    }
    
    
    
    
    int main(int argc, char* argv[])
    {
        gltSetWorkingDirectory(argv[0]);
        
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
        glutInitWindowSize(800, 600);
        glutCreateWindow("Sphere");
        glutReshapeFunc(ChangeSize);
        glutKeyboardFunc(KeyPressFunc);
        glutSpecialFunc(SpecialKeys);
        glutDisplayFunc(RenderScene);
        
        GLenum err = glewInit();
        if (GLEW_OK != err) {
            fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
            return 1;
        }
        
        
        SetupRC();
        
        glutMainLoop();
        return 0;
    }
    
    
    
    

    相关文章

      网友评论

          本文标题:OpenGL学习之路(5.0) 三角形批次类案例

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