OpenGl--实战操作详解(创建几何图形三角形、球、环、圆柱、锥、磁盘)

OpenGl--实战操作详解(创建几何图形三角形、球、环、圆柱、锥、磁盘)

  • 一、引用头文件
  • 二、相关属性
  • 三、相关函数
      • 1.main函数
      • 2.自定义重塑函数
      • 3.自定义键盘空格键响应函数
      • 4.自定义特殊键位处理函数
      • 5.自定义鼠标右击菜单栏函数
      • 6.自定义渲染函数
      • 7.自定义函数
      • 8.自定义函数
  • 四、运行效果

一、引用头文件

#include "GLTools.h" //OpenGL工具类:包含大部分GLTools中类似C语言的独立函数
#include "GLMatrixStack.h" //矩阵堆栈工具类:用于加载单元矩阵、矩阵相乘、压栈、出栈、缩放、平移、旋转等操作
#include "GLFrame.h" //矩阵工具类:表示位置,通过vOrigin、vForward、vUp定义
#include "GLFrustum.h" //矩阵工具类:用于快速设置正投影、透视投影矩阵,完成坐标从3D->2D的映射过程
#include "GLBatch.h" //三角形批次类:用于传输顶点、光照、纹理、颜色等数据到存储着色器
#include "GLGeometryTransform.h" //变换管道类:用于快速在代码中传输视图矩阵、投影矩阵、视图投影变换矩阵等
#include   //数学库

二、相关属性

GLShaderManagershaderManager; //存储着色器管理者

GLMatrixStackmodelViewMatrix; //模型视图矩阵
GLMatrixStackprojectionMatrix; //投影矩阵

GLFramecameraFrame; //角色帧:摄像机、观察者位置
GLFrame            objectFrame; //角色帧;物体、世界坐标位置

GLFrustumviewFrustum; //视景体,用来构造投影矩阵

//三角形批次类
GLTriangleBatch    sphereBatch; //球
GLTriangleBatch    torusBatch; //环
GLTriangleBatch    cylinderBatch; //圆柱
GLTriangleBatch    coneBatch; //锥
GLTriangleBatch    diskBatch; //磁盘

GLGeometryTransformtransformPipeline; //变换管道,存储模型视图、投影、模型视图投影矩阵

三、相关函数

1.main函数

  程序入口函数,OpenGL为面向过程编程,所以OpenGL及其封装的图形图像处理框架,处理过程都是以链式形式进行的。

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("Sphere");
    
    //注册函数:窗口大小变化
    glutReshapeFunc(ChangeSize);
    //注册函数:键盘”空格”键的回调函数
    glutKeyboardFunc(KeyPressFunc);
    //注册函数:键盘“上、下、左、右”键的回调函数
    glutSpecialFunc(SpecialKeys);
    //注册函数:鼠标右键菜单栏
    glutCreateMenu(ProcessMenu);
    glutAddMenuEntry("Menu1", 1);
    glutAddMenuEntry("Menu2", 2);
    glutAddMenuEntry("Menu3", 3);
    
    //注册函数:渲染函数
    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;
}

2.自定义重塑函数

  当屏幕大小发生变化,或者第一次创建窗口时调用该函数。通过glutReshapFunc(函数名)注册。(需在main函数中通过注册调用)

void ChangeSize(int w, int h)
{
    //1.防止h变为0
    if(h == 0)
        h = 1;
    
    //2.设置视口窗口尺寸
    glViewport(0, 0, w, h);
    
    //3.设置透视模式,初始化其透视矩阵
    //setPerspective函数的参数是一个从顶点方向看去的视场角度(用角度值表示)
    viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 500.0f);
    
    //4.把透视矩阵viewFrustum加载到投影矩阵堆栈projectionMatrix中
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    
    //5.modelViewMatrix矩阵堆栈加载单元矩阵。(该方法可不写,系统已默认加载)
    //modelViewMatrix.LoadIdentity();
    
    //6.初始化渲染管线:使用transformPipeline管理模型视图矩阵堆栈modelViewMatix和投影矩阵堆栈projectionMatrix
    //也可在SetupRC()方法中进行初始化
    //transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}

3.自定义键盘空格键响应函数

  用于切换渲染图形。(需在main函数中通过注册调用)

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();
}

4.自定义特殊键位处理函数

  用于处理键盘上、下、左、右键的响应操作。通过键位控制,移动objectFrame的视界坐标系RotateWorld,而非物体本身,来改变视口。(需在main函数中通过注册调用)

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();
}

5.自定义鼠标右击菜单栏函数

  用于处理鼠标右击显示选项功能。(需在main函数中通过注册调用)

void ProcessMenu(int value)
{
    switch (value) {
        case 1:
            //处理操作
            break;
        case 2:
            //处理操作
            break;
        case 3:
            //处理操作
            break;
        default:
            break;
    }
}

6.自定义渲染函数

  当屏幕大小发生变化、或者开发者主动渲染(调用glutPostRedisplay()函数)时,会调用此函数。通过glutDisplayFunc(函数名)来注册。实现从数据->渲染的过程。(需在main函数中通过注册调用)

void RenderScene(void)
{
    //1.清除颜色缓冲区、深度缓冲区、清除窗口背景
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
    //2.模型视图矩阵栈堆,压栈
    modelViewMatrix.PushMatrix();
    
    //3.压栈 方法一:将objectFrame压入模型视图矩阵
    //modelViewMatrix.PushMatrix(objectFrame);
    
    //3.压栈 方法二:objectFrame + cameraFrame (要求先压入cameraFrame,后压入objectFrame)
    //使用cameraFrame时,就需要在SetupRC方法中设置cameraFrame.MoveForward(-15.0f);否则设置objectFrame.MoveForward(-15.0f);
    //a.压栈cameraFrame对应矩阵
    M3DMatrix44f mCamera;
    //GetCameraMatrix获取摄像机矩阵,获取camereaFrame矩阵堆栈的顶部矩阵到mCamera
    cameraFrame.GetCameraMatrix(mCamera);
    //MultMatrix矩阵相乘:将矩阵modelViewMatrix与mCamera矩阵相乘,然后将相乘的结果存储到modelViewMatrix矩阵堆栈顶部
    modelViewMatrix.MultMatrix(mCamera);
    
    //b.压栈objectFrame对应矩阵
    M3DMatrix44f mObjectFrame;
    //GetCameraMatrix:获取objectFrame矩阵堆栈顶部矩阵到mOjectFrame
    objectFrame.GetMatrix(mObjectFrame);
    //MultMatrix矩阵相乘:将矩阵modelViewMatrix与mOjbectFramek矩阵相乘,然后相乘的结果存储到modelViewMatrix矩阵堆栈顶部
    modelViewMatrix.MultMatrix(mObjectFrame);
    
    //5.判断你目前是绘制第几个图形
    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;
    }
    
    //6.还原到以前的模型视图矩阵(单位矩阵)
    modelViewMatrix.PopMatrix();
    
    //7.缓冲区交换
    glutSwapBuffers();
}

7.自定义函数

  用于封装图形填充及三角形线条的绘制。(RenderScene函数中调用)

void DrawWireFramedBatch(GLTriangleBatch* pBatch)
{
    //----绘制图形----
    //1.平面着色器,绘制三角形
    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
     //传过来的参数,对应不同的图形Batch
    pBatch->Draw();
    
    //---画出黑色轮廓---
    
    //2.开启多边形偏移
    glEnable(GL_POLYGON_OFFSET_LINE);
    //多边形模型(背面、线) 将多边形背面设为线框模式
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    //开启多边形偏移(设置偏移数量)
    glPolygonOffset(-1.0f, -1.0f);
    //线条宽度
    glLineWidth(2.5f);
    
    //3.开启混合功能(颜色混合&抗锯齿功能)
    glEnable(GL_BLEND);
    //开启处理线段抗锯齿功能
    glEnable(GL_LINE_SMOOTH);
    //设置颜色混合因子
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   
   //4.平面着色器绘制线条
    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
    
    pBatch->Draw();
    
    //5.恢复多边形模式和深度测试
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glDisable(GL_POLYGON_OFFSET_LINE);
    glLineWidth(1.0f);
    glDisable(GL_BLEND);
    glDisable(GL_LINE_SMOOTH);
}

8.自定义函数

  用于设置需要渲染图形的初始化顶点数据、颜色数据等。(main函数中直接调用,无需通过注册调用)

void SetupRC()
{
    //1.
    glClearColor(0.7f, 0.7f, 0.7f, 1.0f );
    shaderManager.InitializeStockShaders();
    
    //2.开启深度测试
    glEnable(GL_DEPTH_TEST);

    //3.初始化渲染管线:使用transformPipeline管理模型视图矩阵堆栈modelViewMatix和投影矩阵堆栈projectionMatrix
    //也可在ChangeSize()方法中进行初始化
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

    //4.将物体向屏幕外移动15.0(注:如果不设置MoveForward,图形将在屏幕z值为0的位置绘制,实际绘制效果会大于整个屏幕)
    //objectFrame.MoveForward(-15.0f);

    //5.将摄像机坐标Z往屏幕外移动15个单位距离 等效于 将物体坐标Z值往屏幕里边移动15个单位距离。
    //MoveForward:表示离屏幕之间的距离,负数:往屏幕后面移动;正数:往屏幕前面移动。
    //注:如果不设置MoveForward,图形将在屏幕z值为0的位置绘制,实际绘制效果会大于整个屏幕。
    cameraFrame.MoveForward(-15.0f);
    
    //6.利用三角形批次类构造图形对象
    // 球
    /*
      gltMakeSphere(GLTriangleBatch& sphereBatch, GLfloat fRadius, GLint iSlices, GLint iStacks);
     参数1:sphereBatch,三角形批次类对象
     参数2:fRadius,球体半径
     参数3:iSlices,从球体底部堆叠到顶部的三角形带的数量;其实球体是一圈一圈三角形带组成
     参数4: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);
     参数1:torusBatch,三角形批次类对象
     参数2:majorRadius,甜甜圈中心到外边缘的半径
     参数3:minorRadius,甜甜圈中心到内边缘的半径
     参数4:numMajor,沿着主半径的三角形数量
     参数5:numMinor,沿着内部较小半径的三角形数量
     */
    gltMakeTorus(torusBatch, 3.0f, 0.75f, 15, 15);
    
    // 圆柱
    /*
     void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks);
     参数1:cylinderBatch,三角形批次类对象
     参数2:baseRadius,底部半径
     参数3:topRadius,头部半径
     参数4:fLength,圆形长度
     参数5:numSlices,围绕Z轴的三角形对的数量
     参数6:numStacks,圆柱底部堆叠到顶部圆环的三角形数量
     */
    gltMakeCylinder(cylinderBatch, 2.0f, 2.0f, 3.0f, 15, 2);
    
    //锥
    /*
     void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks);
     参数1:cylinderBatch,三角形批次类对象
     参数2:baseRadius,底部半径
     参数3:topRadius,头部半径
     参数4:fLength,圆形长度
     参数5:numSlices,围绕Z轴的三角形对的数量
     参数6:numStacks,圆柱底部堆叠到顶部圆环的三角形数量
     */
    //圆柱体,从0开始向Z轴正方向延伸。
    //圆锥体,是一端的半径为0,另一端半径可指定。
    gltMakeCylinder(coneBatch, 2.0f, 0.0f, 3.0f, 13, 2);
    
    // 磁盘
    /*
    void gltMakeDisk(GLTriangleBatch& diskBatch, GLfloat innerRadius, GLfloat outerRadius, GLint nSlices, GLint nStacks);
     参数1:diskBatch,三角形批次类对象
     参数2:innerRadius,内圆半径
     参数3:outerRadius,外圆半径
     参数4:nSlices,圆盘围绕Z轴的三角形对的数量
     参数5:nStacks,圆盘外网到内围的三角形数量
     */
    gltMakeDisk(diskBatch, 1.5f, 3.0f, 13, 3);
}

四、运行效果

OpenGl--实战操作详解(创建几何图形三角形、球、环、圆柱、锥、磁盘)_第1张图片
OpenGl--实战操作详解(创建几何图形三角形、球、环、圆柱、锥、磁盘)_第2张图片
OpenGl--实战操作详解(创建几何图形三角形、球、环、圆柱、锥、磁盘)_第3张图片
OpenGl--实战操作详解(创建几何图形三角形、球、环、圆柱、锥、磁盘)_第4张图片
OpenGl--实战操作详解(创建几何图形三角形、球、环、圆柱、锥、磁盘)_第5张图片
注:按键盘“空格”键可以切换不同的图形;按键盘“上、下、左、右”键可移动图形的展示角度,能够观察到图形的立体效果。

你可能感兴趣的:(OpenGL)