ImageVerifierCode 换一换
格式:DOCX , 页数:11 ,大小:20.33KB ,
资源ID:7929746      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7929746.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(opengl之曲线和曲面.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

opengl之曲线和曲面.docx

1、opengl 之曲线和曲面之曲线和曲面 计算机图形学中,所有的光滑曲线、曲面都采用线段或三角形逼近来模拟,但为了精确地表现曲线,通常需要成千上万个线段或三角形来逼近,这种方法对于计算机的硬件资源有相当高的要求。然而,许多有用的曲线、曲面在数学上只需要用少数几个参数(如控制点等)来描述。这种方法所需要的存储空间比线段、三角形逼近的方法来所需要的空间要小得多,并且控制点方法描述的曲线、曲面比线段、三角形逼近的曲线、曲面更精确。为了说明如何在 OpenGL中绘制复杂曲线和曲面,我们对上述两类比方法都进行了介绍。下面我们先来介绍有关基础知识,然后再看是如何实现的吧。一、曲线的绘制 OpenGL通过一种

2、求值器的机制来产生曲线和曲面,该机制非常灵活,可以生成任意角度的多项式曲线,并可以将其他类型的多边形曲线和曲面转换成贝塞尔曲线和曲面。这些求值器能在任何度的曲线及曲面上计算指定数目的点。随后,OpenGL利用曲线和曲面上的点生成标准 OpenGL图元,例如与曲线或曲面近似的线段和多边形。由于可让 OpenGL 计算在曲线上所需的任意数量的点,因此可以达到应用所需的精度。对于曲线,OpenGL中使用 glMap1*()函数来创建一维求值器,该函数原型为:void glMap1fd(GLenum target,TYPE u1,TYPE u2,GLint stride,GLint order,con

3、st TYPE*points);函数的第一个参数 target 指出控制顶点的意义以及在参数 points 中需要提供多少值,具体值见表一所示。参数 points 指针可以指向控制点集、RGBA 颜色值或纹理坐标串等。例如若 target 是 GL_MAP1_COLOR_4,则就能在 RGBA 四维空间中生成一条带有颜色信息的曲线,这在数据场可视化中应用极广。参数 u1 和 u2,指明变量 U的范围,U一般从 0 变化到 1。参数 stride是跨度,表示在每块存储区内浮点数或双精度数的个数,即两个控制点间的偏移量,比如上例中的控制点集 ctrpoint43的跨度就为 3,即单个控制点的坐标元

4、素个数。函数参数 order是次数加 1,叫阶数,与控制点数一致。参数 意义 GL_MAP1_VERTEX_3 x,y,z 顶点坐标 GL_MAP1_VERTEX_4 x,y,z,w 顶点坐标 GL_MAP1_INDEX 颜色表 GL_MAP1_COLOR_4 R,G,B,A GL_MAP1_NORMAL 法向量 GL_MAP1_TEXTURE_COORD_1 s 纹理坐标 GL_MAP1_TEXTURE_COORD_2 s,t 纹理坐标 GL_MAP1_TEXTURE_COORD_3 s,t,r 纹理坐标 GL_MAP1_TEXTURE_COORD_4 s,t,r,q 纹理坐标 表一、参数

5、target 的取值表 使用求值器定义曲线后,必须要启动求值器,才能进行下一步的绘制工作。启动函数仍是 glEnable(),其中参数与 glMap1*()的第一个参数一致。同样,关闭函数为 glDisable(),参数也一样。一旦启动一个或多个求值器,我们就可以构造近似曲线了。最简单的方法是通过调用计算坐标函数 glEvalcoord1*()替换所有对函数 glVertex*()的调用。与glVertex*()使用二维、三维和四维坐标不同,glEvalcoord1*()将 u值传给所有已启动的求值器,然后由这些已启动的求值器生成坐标、法向量、颜色或纹理坐标。OpenGL曲线坐标计算的函数形式

6、如下:void glEvalCoord1fdv(TYPE u);该函数产生曲线坐标值并绘制。参数 u 是定义域内的值,这个函数调用一次只产生一个坐标。在使用 glEvalCoord1*()计算坐标,因为 u可取定义域内的任意值,所以由此计算出的坐标值也是任意的。使用 glEvalCoord1*()函数的优点是,可以对 U使用任意值,然而,如果想对u 使用 N个不同的值,就必须对 glEvalCoord1*()函数执行 N次调用,为此,OpenGL提供了等间隔值取值法,即先调用 glMapGrid1*()定义一个间隔相等的一维网格,然后再用 glEvalMesh1()通过一次函数执行,将求值器应

7、用在网格上,计算相应的坐标值。下面详细解释这两个函数:1、void glMapGrid1fd(GLint n,TYPE u1,TYPE u2);定义一个网格,从 u1到 u2分为 n 步,它们是等间隔的。实际上,这个函数定义的是参数空间网格。2、void glEvalMesh1(GLenum mode,GLint p1,GLint p2);计算并绘制坐标点。参数 mode可以是 GL_POINT 或 GL_LINE,即沿曲线绘制点或沿曲线绘制相连的线段。这个函数的调用效果同在 p1 和 p2之间的每一步给出一个 glEvalCoord1()的效果一样。从编程角度来说,除了当 i=0或 i=n,

8、它准确以 u1或u2 作为参数调用 glEvalCoord1()之外,它等价于一下代码:glBegin(GL_POINT);/*glBegin(GL_LINE_STRIP);*/for(i=p1;i=p2;i+)glEvalCoord1(u1+i*(u2-u1)/n);glEnd();为了进一步说明 OpenGL中曲线的绘制方法。下面我们来看一个简单的例子,这是用四个控制顶点来画一条三次 Bezier 曲线。程序如下(注:这是本讲座中提供的第一个完整的 OpenGL实例代码,如果读者朋友对整个程序结构有些迷惑的话,也不要紧,慢慢地往下看,先有一个感官上的印象,主要是掌握如何实现曲线绘制这一部分

9、。关于 OpenGL 的程序整体结构实现,笔者将在第五讲中专门阐述):#include glos.h#include#include#include void myinit(void);void CALLBACK myReshape(GLsizei w,GLsizei h);void CALLBACK display(void);GLfloat ctrlpoints43=-4.0,-4.0,0.0,-2.0,4.0,0.0,2.0,-4.0,0.0,4.0,4.0,0.0 ;void myinit(void)glClearColor(0.0,0.0,0.0,1.0);glMap1f(GL_MA

10、P1_VERTEX_3,0.0,1.0,3,4,&ctrlpoints00);glEnable(GL_MAP1_VERTEX_3);glShadeModel(GL_FLAT);void CALLBACK display(void)int i;glClear(GL_COLOR_BUFFER_BIT);glColor3f(1.0,1.0,1.0);glBegin(GL_LINE_STRIP);for(i=0;i=30;i+)glEvalCoord1f(GLfloat)i/30.0);glEnd();/*显示控制点*/glPointSize(5.0);glColor3f(1.0,1.0,0.0);g

11、lBegin(GL_POINTS);for(i=0;i 4;i+)glVertex3fv(&ctrlpointsi0);glEnd();glFlush();void CALLBACK myReshape(GLsizei w,GLsizei h)glViewport(0,0,w,h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if(w=h)glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0);else glOrtho(-5.0*(GLfloat

12、)w/(GLfloat)h,5.0*(GLfloat)w/(GLfloat)h,-5.0,5.0,-5.0,5.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();二、曲面构造 曲面的绘制方法基本上与曲线的绘制方法是相同的,所不同的是曲面使用二维求值器,并且控制点连接起来形成一个网格。对于曲面,求值器除了使用二个参数 U、V之外,其余与一维求值器基本相同。顶点坐标、颜色、法线矢量和纹理坐标都对应于曲面而不是曲线。在 OpenGL中定义二维求值器的函数是:void glMap2fd(GLenum target,TYPE u1,TYPE u2,GLint

13、ustride,GLint uorder,TYPE v1,TYPE v2,GLint vstride,GLint vorder,TYPE points);参数 target 可以是表一中任意值,不过需将 MAP1 改为 MAP2。同样,启动曲面的函数仍是 glEnable(),关闭是 glDisable()。u1、u2为 u的最大值和最小值;v1、v2为 v 的最大值和最小值。参数 ustride和 vstride指出在控制点数组中 u和 v 向相邻点的跨度,即可从一个非常大的数组中选择一块控制点长方形。例如,若数据定义成如下形式:GLfloat ctlpoints1001003;并且,要用从

14、 ctlpoints2030开始的 4x4子集,选择 ustride为 100*3,vstride为 3,初始点设置为 ctlpoints20300。最后的参数都是阶数,uorder和 vorder,二者可以不同。曲面坐标计算函数为:void glEvalCoord2fdv(TYPE u,TYPE v);该函数产生曲面坐标并绘制。参数 u和 v是定义域内的值。下面看一个绘制Bezier曲面的例子:/*控制点的坐标*/GLfloat ctrlpoints443=-1.5,-1.5,2.0,-0.5,-1.5,2.0,0.5,-1.5,-1.0,1.5,-1.5,2.0,-1.5,-0.5,1.0

15、,-0.5,1.5,2.0,0.5,0.5,1.0,1.5,-0.5,-1.0,-1.5,0.5,2.0,-0.5,0.5,1.0,0.5,0.5,3.0,1.5,-1.5,1.5,-1.5,1.5,-2.0,-0.5,1.5,-2.0,0.5,0.5,1.0,1.5,1.5,-1.0;void myinit(void)glClearColor(0.0,0.0,0.0,1.0);glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,&ctrlpoints000);glEnable(GL_MAP2_VERTEX_3);glMapGrid2f(20,0.0,1.0,2

16、0,0.0,1.0);glEnable(GL_DEPTH_TEST);void CALLBACK display(void)int i,j;glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glColor3f(0.3,0.6,0.9);glPushMatrix();glRotatef(35.0,1.0,1.0,1.0);for(j=0;j=8;j+)glBegin(GL_LINE_STRIP);for(i=0;i=30;i+)glEvalCoord2f(GLfloat)i/30.0,(GLfloat)j/8.0);glEnd();glBegin(

17、GL_LINE_STRIP);for(i=0;i=30;i+)glEvalCoord2f(GLfloat)j/8.0,(GLfloat)i/30.0);glEnd();glPopMatrix();glFlush();OpenGL中定义均匀间隔的曲面坐标值的函数与曲线的类似,其函数形式为:void glMapGrid2fd(GLenum nu,TYPE u1,TYPE u2,GLenum nv,TYPE v1,TYPE v2);void glEvalMesh2(GLenum mode,GLint p1,GLint p2,GLint q1,GLint q2);第一个函数定义参数空间的均匀网格,从

18、u1 到 u2分为等间隔的 nu步,从 v1到 v2分为等间隔的 nv 步,然后 glEvalMesh2()把这个网格应用到已经启动的曲面计算上。第二个函数参数 mode 除了可以是 GL_POINT 和 GL_LINE 外,还可以是GL_FILL,即生成填充空间曲面。下面举出一个用网格绘制一个经过光照和明暗处理的 Bezier曲面的例程:#include glos.h#include#include#include void myinit(void);void initlights(void);void CALLBACK myReshape(GLsizei w,GLsizei h);void

19、 CALLBACK display(void);/*控制点坐标*/GLfloat ctrlpoints443=-1.5,-1.5,2.0,-0.5,-1.5,2.0,0.5,-1.5,-1.0,1.5,-1.5,2.0,-1.5,-0.5,1.0,-0.5,1.5,2.0,0.5,0.5,1.0,1.5,-0.5,-1.0,-1.5,0.5,2.0,-0.5,0.5,1.0,0.5,0.5,3.0,1.5,-1.5,1.5,-1.5,1.5,-2.0,-0.5,1.5,-2.0,0.5,0.5,1.0,1.5,1.5,-1.0;void initlights(void)GLfloat ambi

20、ent=0.4,0.6,0.2,1.0;GLfloat position=0.0,1.0,3.0,1.0;GLfloat mat_diffuse=0.2,0.4,0.8,1.0;GLfloat mat_specular=1.0,1.0,1.0,1.0;GLfloat mat_shininess=80.0;glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);glLightfv(GL_LIGHT0,GL_POSITION,position);glMaterialfv(GL_FRONT,G

21、L_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);void CALLBACK display(void)glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glPushMatrix();glRotatef(35.0,1.0,1.0,1.0);glEvalMesh2(GL_FILL,0,20,0,20);glPopMatrix();glFlush();void

22、myinit(void)glClearColor(0.0,0.0,0.0,1.0);glEnable(GL_DEPTH_TEST);glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,&ctrlpoints000);glEnable(GL_MAP2_VERTEX_3);glEnable(GL_AUTO_NORMAL);glEnable(GL_NORMALIZE);glMapGrid2f(20,0.0,1.0,20,0.0,1.0);initlights();void CALLBACK myReshape(GLsizei w,GLsizei h)glViewpor

23、t(0,0,w,h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if(w=h)glOrtho(-4.0,4.0,-4.0*(GLfloat)h/(GLfloat)w,4.0*(GLfloat)h/(GLfloat)w,-4.0,4.0);else glOrtho(-4.0*(GLfloat)w/(GLfloat)h,4.0*(GLfloat)w/(GLfloat)h,-4.0,4.0,-4.0,4.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();void main(void)auxInitDispla

24、yMode(AUX_SINGLE|AUX_RGBA);auxInitPosition(0,0,500,500);auxInitWindow(Lighted and Filled Bezier Surface);myinit();auxReshapeFunc(myReshape);auxMainLoop(display);三、图元逼近法绘制三维物体 在 OpenGL的辅助库中,提供了绘制 11 种基本几何图形的函数,具体参考第一讲的有关内容,在此不再赘述。这里我们讨论用另外一种方法来绘制三维物体。需要注意的是,这里我们用来近似曲面的多边形最好选择三角形,而不是四边形或其他形状的多边形,这是因为三

25、角形的三个顶点在任何时候都位于同一平面内,它一定是非常简单的非凹多边形,而四边形或其他多边形的顶点可能不在同一平面内,也就有可能不是简单多边形,对于这样的多边形,OpenGL是不能正常处理的。假设我们绘制一个球体,球体表面用很多个小三角形拼接而成,显然,用来近似球面的三角形越小、三角形越多,那么球面就越光滑。为了简要地说明如何用三角形逼近球体,这里我们使用三角形来构造一个 20面体,二十面体的顶点坐标定义在 vdata数组中,tindinces数组定义了构成二十面体的二十个三角形顶点的绘制顺序。下面是主要实现代码:#define x 5.25731#define z 8.50651 stati

26、c GLfloat vdata123=x,0.0,z,x,0.0,z,-x,0.0,-z,x,0.0,-z,0.0,z,x,0.0,z,-x,0.0,-z-x,0.0,-z,-x,z,x,0.0,-z,x,0.0,z,-x,0.0,-z,-x,0.0;static GLint tindices203=0,4,1,0,9,4,9,5,4,4,5,8,4,8,1,8,10,1,8,3,10,5,3,8,5,2,3,2,7,3,7,10,3,7,6,10,7,11,6,11,0,6,6,1,10,9,0,11,9,11,2,9,2,5,7,2,11;glColor3f(1.0,0.0,0.0);for(int i=0;i20;i+)glBegin(GL_TRIANGLES);glVertex3fv(&vdatatindicesi00);glVertex3fv(&vdatatindicesi10);glVertex3fv(&vdatatindicesi20);glEnd();显然,用正二十面体来表示一个球体显得过于粗糟,可以通过增加面数的方法使正多面体和求更为接近,一种简单的方法是剖分法,即将前面定义的三角形面分成几个面,例如,一分为四,形成 4个多边形等,具体实现方法这里就不再赘述了。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1