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; //角色帧:摄像机、观察者位置 GLFrameobjectFrame; //角色帧;物体、世界坐标位置GLFrustumviewFrustum; //视景体,用来构造投影矩阵//三角形批次类 GLTriangleBatchsphereBatch; //球 GLTriangleBatchtorusBatch; //环 GLTriangleBatchcylinderBatch; //圆柱 GLTriangleBatchconeBatch; //锥 GLTriangleBatchdiskBatch; //磁盘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.自定义特殊键位处理函数
【OpenGl--实战操作详解(创建几何图形三角形、球、环、圆柱、锥、磁盘)】??用于处理键盘上、下、左、右键的响应操作。通过键位控制,移动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--实战操作详解(创建几何图形三角形、球、环、圆柱、锥、磁盘)
文章图片

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

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

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

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

注:按键盘“空格”键可以切换不同的图形;按键盘“上、下、左、右”键可移动图形的展示角度,能够观察到图形的立体效果。

    推荐阅读