内部支持的表面

GLU库中提供了一些二次曲面的支持。这些二次方程可以渲染球体,圆柱体,圆盘。这些函数有很大的灵活性,我们可以指定圆柱体的一端的半径,然后让另一端的半径为0,这样的话就能构建一个圆锥。我们还可以绘制一个有洞的圆盘。如下图:

这些二次方程对象可以构建出更复杂的模型,例如我们可以用球体,圆柱体,圆锥,圆盘来构建一个3D坐标系的模型。在glTools中有提供了这个函数:

void gltdDrawUnitAxes();

设置二次方程状态

在绘制二次方程对象之前,我们可以为其制定法线向量,纹理坐标等。如果我们每次在绘制这些二次方程对象时,把这些可选项都通过参数的方式传递,那工作量就变得很大。所以OpenGL用二次方程状态对象的方式来实现,这样我们可以通过一些函数来设置这个二次方程状态对象,以后每次绘制二次方程对象的时候只要传递这个二次方程状态,OpenGL就知道是以什么样的方式绘制二次方程对象了。(利用面向对象的方式来达到复用的目的)。

步骤是:

首先我们创建一个二次方程状态对象.

调用函数设置二次方程状态

以二次方程状态对象作为参数,传到绘制二次方程的函数

使用完之后销毁。

GLUquadricObj *pObj; //创建二次方程状态对象 pObj = gluNewQuadric(); //设置二次方程状态 gluQuadricDrawStyle(pObj, GLU_LINE);

... //销毁 gluDeleteQuadric(pObj);

GLU库的gluNewQuadric()方法不仅仅为GLUQuadricObj对象申请了内存空间,而且还初始化了一些默认值。GLU库有四个函数可以修改这个二次方程对象的状态:

void gluQuadricDrawStyle(GLUquadricObj *obj, GLenum drawStyle);

第一个参数是二次方程对象状态的指针,第二个参数的枚举值如下表:

常量

描述

GLU_FILL

二次方程对象画成实体

GLU_LINE

二次方程对象画成线框

GLU_POINT

二次方程对象画成一组顶点的集合

GLU_SILHOUETTE

类似于线框,但相邻的多边形的边不被绘制。

void gluQuadricNormals(GLUquadricObj *pbj, GLenum normals);

上面的这个函数指定二次方程对象如何生成法线。第二个参数可以是:GLU_NONE不生成法线,GLU_FLAT扁平法线,GLU_SMOOTH平滑法线。

如果指定的是平滑法线,那么每个顶点都指定了一条法线,垂直于被模拟的表面,这样可以产生一个平滑的表面。扁平法线是所有的法线都是面法线,垂直于三角形(多边形)面。

goid gluQuadricOrientation(GLUQuadricObj *obj, GLenum orientation);

上面的这个函数可以指定法线的朝向,指向外面还是只想里面。orientation可以是GLU_OUTSIDE或者是GLU_INSIDE这两个值。OpenGL默认是以GL_CCW逆时针为正方向的。

最后,我们还可以为二次方程表面指定纹理坐标,通过下面的函数调用来实现:

void gluQuadsricTexture(GLUquadricObj *obj, GLenum textureCoords);

textureCoords这个参数可以是GL_TRUE或者GL_FALSE.当为球体和圆柱体生成纹理坐标时,纹理是对称地环绕在球体和圆柱体的表面的。如果应用到圆盘上,那么纹理的中心就是圆盘的中心,然后以线性插值的方式扩展到圆盘的边界。

绘制二次方程图形

void gluSphere(GLUQuadricObj *obj, GLdouble radius, GLint slices, GLint stacks);

上面的函数式绘制球体的函数。第一个参数是指向二次方程状态的指针,第二个参数是球体的半径。第三个参数可以理解为地球的经线的条数。最后一个参数可以理解为纬线的条数。

...

gltDrawUnitAxes();

GLUquadricObj *quadricObj = gluNewQuadric();

gluQuadricDrawStyle(quadricObj, GLU_LINE);

gluSphere(quadricObj, 0.8, 26, 13);

...

我们可以通过指定底部的半和顶部的半径(方向是沿z轴正方向向外),还有高度(即圆柱体的长度)来绘制一个圆柱体。绘制圆柱体的函数如下:

void gluCylinder(GLUquadricObj *obj, GLdouble baseRadius, GLdouble topRadius, GLdouble height, GLint slices, GLint stacks);

gltDrawUnitAxes();

GLUquadricObj *quadricObj = gluNewQuadric();

gluQuadricDrawStyle(quadricObj, GLU_LINE);

gluCylinder(quadricObj, 0.7, 0.7, 2, 26, 13);

把顶部半径设置为0.

gluCylinder(quadricObj, 0.7, 0.0, 2, 26, 13);

绘制圆盘的函数

void gluDisk(GLUquadricObj *obj, GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops);

指定内半径为0才是实心的圆盘。

gluDisk(quadricObj, 0.0, 0.7, 26, 13);

gluDisk(quadricObj, 0.2, 0.7, 26, 13); 中间有洞的圆盘。

用二次方程进行建模

下面是一个雪人的例子。这个雪人由3个雪球堆成,由两个小眼睛和一个鼻子。还带了一顶帽子。步骤如下:

先从底部向上使用gluSphere函数绘制三个雪球(使用平移glTranslate)

用gluSphere再绘制两个眼睛,用gluCylinder绘制一个圆锥形的鼻子

使用gluCylinder绘制圆柱体的帽子,再使用gluDisk画帽子的边。

代码示例如下:

#include "gltools.h" #include "math3d.h" #include "glframe.h" #include

GLFrame objFrame; void SetupRC()

{

glClearColor(0.3f, 0.3f, 0.5f, 1.0f); //开启深度检测,消除隐藏面 glEnable(GL_DEPTH_TEST);

glEnable(GL_CULL_FACE);

glCullFace(GL_BACK);

glFrontFace(GL_CCW); //开启光照 GLfloat whiteLight[] = {0.05f, 0.05f, 0.05f, 1.0f};

GLfloat sourceLight[] = {0.25f, 0.25f, 0.25f, 1.0f};

GLfloat lightPos[] = {-5.0f, 15.0f, 5.0f, 1.0f};

glEnable(GL_LIGHTING);

glLightModelfv(GL_LIGHT_MODEL_AMBIENT, whiteLight);

glLightfv(GL_LIGHT0, GL_AMBIENT_AND_DIFFUSE, sourceLight);

glLightfv(GL_LIGHT0, GL_POSITION, lightPos);

glEnable(GL_LIGHT0); //开启颜色追踪 glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

glEnable(GL_COLOR_MATERIAL);

} void ChangeSize(GLsizei w, GLsizei h)

{ if (h == 0)

h = 1;

glViewport(0, 0, w, h);

GLfloat aspect = (GLfloat)w/(GLfloat)h;

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluPerspective(35.0, aspect, 1.0, 40.0);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

} void RenderScene()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //设置二次方程的状态 GLUquadricObj *quadricObj = gluNewQuadric();

gluQuadricNormals(quadricObj, GLU_SMOOTH);

glPushMatrix();

glTranslatef(0.0f, -.6f, -8.0f);

objFrame.ApplyCameraTransform();

glPushMatrix(); //画三个雪球 glColor3f(1.0f, 1.0f, 1.0f);

gluSphere(quadricObj, .65f, 26, 13);

glTranslatef(0.0f, 0.85f, 0.0f);

gluSphere(quadricObj, 0.42f, 26, 13);

glTranslatef(0.0f, 0.63f, 0.0f);

gluSphere(quadricObj, 0.36f, 26, 13); //画两个眼睛 glTranslatef(-0.2f, 0.1f, 0.31f);

glColor3f(0.0f, 0.0f, 0.0f);

gluSphere(quadricObj, 0.05f, 26, 13);

glTranslatef(0.4f, 0.0f, 0.0f);

gluSphere(quadricObj, 0.05f, 26,13); //画一个鼻子 glTranslatef(-0.2f, -0.08f, 0.03f);

glColor3f(1.0f, 0.3f, 0.3f);

gluCylinder(quadricObj, 0.04f, 0.0f, 0.6f, 26, 13);

glPopMatrix(); //画帽子 glPushMatrix();

glColor3f(0.0f, 0.0f, 0.0f);

glTranslatef(0.0f, 2.2f, 0.0f);

glRotatef(90.0, 1.0f, 0.0f, 0.0f);

gluCylinder(quadricObj, 0.2f, 0.2f, 0.4f, 26, 13);

glDisable(GL_CULL_FACE);

gluDisk(quadricObj, 0.17f, 0.2f, 26, 13);

glTranslatef(0.0f, 0.0f, 0.40f);

gluDisk(quadricObj, 0.0f, 0.4f, 26, 13);

glEnable(GL_CULL_FACE);

glPopMatrix();

glPopMatrix();

glutSwapBuffers();

} //通过按键来移动和旋转 void SpecialKey(int value, int x, int y)

{ if (value == GLUT_KEY_RIGHT)

{

objFrame.RotateLocalY(0.5f);

} if (value == GLUT_KEY_LEFT)

{

objFrame.RotateLocalY(-0.5f);

} if (value == GLUT_KEY_UP)

{

objFrame.MoveUp(0.5f);

} if (value == GLUT_KEY_DOWN)

{

objFrame.MoveUp(-0.5f);

}

glutPostRedisplay();

} int main(int args, char **argv)

{

glutInit(&args, argv);

glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);

glutInitWindowSize(800, 600);

glutCreateWindow("snowman");

glutDisplayFunc(RenderScene);

glutReshapeFunc(ChangeSize);

SetupRC();

glutSpecialFunc(SpecialKey);

glutMainLoop(); return 0;

}

深入理解linux white函数,OpenGL超级宝典学习笔记——曲线和曲面(一)相关推荐

  1. OpenGL超级宝典学习笔记——操作矩阵

    为了更强大的功能和灵活性,我们有时需要直接操作矩阵.在OpenGL中4x4的矩阵用包含16个浮点数值的一维数组来表示,而不是用二维的4x4的数组来表示.OpenGL之所以这么做,因为使用一维数组更高效 ...

  2. OpenGL超级宝典学习笔记:着色器存储区块、原子内存操作、内存屏障

    前言 本篇在讲什么 本篇为蓝宝书学习笔记 着色器存储区块 原子内存操作 内存屏障 本篇适合什么 适合初学Open的小白 本篇需要什么 对 C++语法有简单认知 对 OpenGL有简单认知 最好是有 O ...

  3. (第四章)OpenGL超级宝典学习:必要的数学知识

    必要的数学知识 前言 在本章当中,作者着重介绍了几个和3D图形学重要的数学知识,线性代数基础好的同学可以直接绕过本章,说实话这篇博客写到这里,我是非常犹豫的,本章节的内容可以说是很基础,但是相当的枯燥 ...

  4. OpenGL超级宝典(第7版)笔记13 前三章实例 下个五子棋 (上)

    OpenGL超级宝典(第7版)笔记13 前三章实例 下个五子棋 (上) 文章目录 OpenGL超级宝典(第7版)笔记13 前三章实例 下个五子棋 (上) 前言 1 初构建 2 构建数据结构 3 绘制 ...

  5. OpenGL超级宝典(第7版)笔记20 统一变量 一致区块 uniform相关内容 清单5.9-5.28

    OpenGL超级宝典(第7版)笔记20 统一变量 一致区块 uniform相关内容 清单5.9-5.28 文章目录 OpenGL超级宝典(第7版)笔记20 统一变量 一致区块 uniform相关内容 ...

  6. OpenGL超级宝典(第7版)笔记4 渲染管线介绍 清单2.3-2.7

    OpenGL超级宝典(第7版)笔记4 渲染管线介绍 清单2.3-2.7 文章目录 OpenGL超级宝典(第7版)笔记4 渲染管线介绍 清单2.3-2.7 1 OpenGL简介 2 OpenGL渲染管线 ...

  7. OpenGL超级宝典开发环境配置(VS2010)

    <OpenGL超级宝典>第五版中的例子使用了GLEW.freeglut和GLTools三个库. 1.GLEW The OpenGL Extension Wrangler Library i ...

  8. [转]OpenGL超级宝典 5e 环境配置

    OpenGL超级宝典(第五版)环境配置 1.各种库的配置 (1)glew 下载:https://sourceforge.net/projects/glew/files/glew/1.7.0/glew- ...

  9. OpenGL超级宝典(第7版)笔记11 帧缓存运算 计算着色器 清单 3.13

    OpenGL超级宝典(第7版)笔记11 帧缓存运算 计算着色器 清单 3.13 文章目录 OpenGL超级宝典(第7版)笔记11 帧缓存运算 计算着色器 清单 3.13 1 帧缓存运算 1.1 裁剪测 ...

最新文章

  1. GEF常见问题8:导出到图片
  2. 单个正态总体均值的区间估计_考研数学闭关修炼习题讲解(3536)统计、估计与检验...
  3. 手机版的python-python手机版
  4. STM32 电机教程 28 - ST MCLIB实战之 位置闭环控制
  5. remotepath != null 与 !TextUtils.isEmpty(remotepath) 的区别
  6. Tomcat启动Name or service not known错误解决
  7. 覆盖索引最左前缀原则索引下推
  8. struct file 结构体
  9. 【java】深入探讨 Java 类加载器
  10. 人脸关键点:MTCNN-Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks
  11. BZOJ:1001狼抓兔子
  12. Asp.Net MVC4入门指南(8):给数据模型添加校验器
  13. Windows下Cmder 安装及配置
  14. python - 搜狗词库 (.scel 文件转 txt)
  15. ProGuard详解 - Java代码混淆
  16. 无人驾驶轨迹跟踪之纯轨迹跟踪(Pure Pursuit)
  17. (转)yolov3运行及保存检测视频(包括摄像头)
  18. ThinkPad笔记本电脑网络重置之后wifi没有了
  19. 同步多个 git 远程仓库
  20. word 文本框插入图片

热门文章

  1. xampp启动MySQL出现Error: MySQL shutdown unexpectedly.
  2. 贪玩蓝月服务器维护需多少时间,贪玩蓝月合区维护一次多久 | 手游网游页游攻略大全...
  3. 最近有股强烈的挫败感
  4. CrawlSpider爬取拉勾网,解决302问题。
  5. 怎样把软件从计算机移到桌面上,怎么把电脑软件移动到D盘
  6. linux下dvwa安装教程,Kali linux2.0系统安装DVWA渗透测试平台 焕焕
  7. Arduino+OLED基础保姆级教程(1)
  8. 真彩色与伪彩色、直接色的区别
  9. C++关于float和double的有效位数
  10. 常用开源库收集+网站收集