opengl之曲线和曲面Word文档格式.docx
- 文档编号:21064848
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:11
- 大小:20.33KB
opengl之曲线和曲面Word文档格式.docx
《opengl之曲线和曲面Word文档格式.docx》由会员分享,可在线阅读,更多相关《opengl之曲线和曲面Word文档格式.docx(11页珍藏版)》请在冰豆网上搜索。
函数参数order是次数加1,叫阶数,与控制点数一致。
参数意义GL_MAP1_VERTEX_3x,y,z顶点坐标GL_MAP1_VERTEX_4x,y,z,w顶点坐标GL_MAP1_INDEX颜色表GL_MAP1_COLOR_4R,G,B,AGL_MAP1_NORMAL法向量GL_MAP1_TEXTURE_COORD_1s纹理坐标GL_MAP1_TEXTURE_COORD_2s,t纹理坐标GL_MAP1_TEXTURE_COORD_3s,t,r纹理坐标GL_MAP1_TEXTURE_COORD_4s,t,r,q纹理坐标表一、参数target的取值表使用求值器定义曲线后,必须要启动求值器,才能进行下一步的绘制工作。
启动函数仍是glEnable(),其中参数与glMap1*()的第一个参数一致。
同样,关闭函数为glDisable(),参数也一样。
一旦启动一个或多个求值器,我们就可以构造近似曲线了。
最简单的方法是通过调用计算坐标函数glEvalcoord1*()替换所有对函数glVertex*()的调用。
与glVertex*()使用二维、三维和四维坐标不同,glEvalcoord1*()将u值传给所有已启动的求值器,然后由这些已启动的求值器生成坐标、法向量、颜色或纹理坐标。
OpenGL曲线坐标计算的函数形式如下:
voidglEvalCoord1fdv(TYPEu);
该函数产生曲线坐标值并绘制。
参数u是定义域内的值,这个函数调用一次只产生一个坐标。
在使用glEvalCoord1*()计算坐标,因为u可取定义域内的任意值,所以由此计算出的坐标值也是任意的。
使用glEvalCoord1*()函数的优点是,可以对U使用任意值,然而,如果想对u使用N个不同的值,就必须对glEvalCoord1*()函数执行N次调用,为此,OpenGL提供了等间隔值取值法,即先调用glMapGrid1*()定义一个间隔相等的一维网格,然后再用glEvalMesh1()通过一次函数执行,将求值器应用在网格上,计算相应的坐标值。
下面详细解释这两个函数:
1、voidglMapGrid1fd(GLintn,TYPEu1,TYPEu2);
定义一个网格,从u1到u2分为n步,它们是等间隔的。
实际上,这个函数定义的是参数空间网格。
2、voidglEvalMesh1(GLenummode,GLintp1,GLintp2);
计算并绘制坐标点。
参数mode可以是GL_POINT或GL_LINE,即沿曲线绘制点或沿曲线绘制相连的线段。
这个函数的调用效果同在p1和p2之间的每一步给出一个glEvalCoord1()的效果一样。
从编程角度来说,除了当i=0或i=n,它准确以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实例代码,如果读者朋友对整个程序结构有些迷惑的话,也不要紧,慢慢地往下看,先有一个感官上的印象,主要是掌握如何实现曲线绘制这一部分。
关于OpenGL的程序整体结构实现,笔者将在第五讲中专门阐述):
#includeglos.h#include#include#includevoidmyinit(void);
voidCALLBACKmyReshape(GLsizeiw,GLsizeih);
voidCALLBACKdisplay(void);
GLfloatctrlpoints43=-4.0,-4.0,0.0,-2.0,4.0,0.0,2.0,-4.0,0.0,4.0,4.0,0.0;
voidmyinit(void)glClearColor(0.0,0.0,0.0,1.0);
glMap1f(GL_MAP1_VERTEX_3,0.0,1.0,3,4,&
ctrlpoints00);
glEnable(GL_MAP1_VERTEX_3);
glShadeModel(GL_FLAT);
voidCALLBACKdisplay(void)inti;
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);
/*显示控制点*/glPointSize(5.0);
glColor3f(1.0,1.0,0.0);
glBegin(GL_POINTS);
i4;
i+)glVertex3fv(&
ctrlpointsi0);
glFlush();
voidCALLBACKmyReshape(GLsizeiw,GLsizeih)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);
elseglOrtho(-5.0*(GLfloat)w/(GLfloat)h,5.0*(GLfloat)w/(GLfloat)h,-5.0,5.0,-5.0,5.0);
glMatrixMode(GL_MODELVIEW);
二、曲面构造曲面的绘制方法基本上与曲线的绘制方法是相同的,所不同的是曲面使用二维求值器,并且控制点连接起来形成一个网格。
对于曲面,求值器除了使用二个参数U、V之外,其余与一维求值器基本相同。
顶点坐标、颜色、法线矢量和纹理坐标都对应于曲面而不是曲线。
在OpenGL中定义二维求值器的函数是:
voidglMap2fd(GLenumtarget,TYPEu1,TYPEu2,GLintustride,GLintuorder,TYPEv1,TYPEv2,GLintvstride,GLintvorder,TYPEpoints);
参数target可以是表一中任意值,不过需将MAP1改为MAP2。
同样,启动曲面的函数仍是glEnable(),关闭是glDisable()。
u1、u2为u的最大值和最小值;
v1、v2为v的最大值和最小值。
参数ustride和vstride指出在控制点数组中u和v向相邻点的跨度,即可从一个非常大的数组中选择一块控制点长方形。
例如,若数据定义成如下形式:
GLfloatctlpoints1001003;
并且,要用从ctlpoints2030开始的4x4子集,选择ustride为100*3,vstride为3,初始点设置为ctlpoints20300。
最后的参数都是阶数,uorder和vorder,二者可以不同。
曲面坐标计算函数为:
voidglEvalCoord2fdv(TYPEu,TYPEv);
该函数产生曲面坐标并绘制。
参数u和v是定义域内的值。
下面看一个绘制Bezier曲面的例子:
/*控制点的坐标*/GLfloatctrlpoints443=-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;
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,20,0.0,1.0);
glEnable(GL_DEPTH_TEST);
voidCALLBACKdisplay(void)inti,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);
i+)glEvalCoord2f(GLfloat)i/30.0,(GLfloat)j/8.0);
i+)glEvalCoord2f(GLfloat)j/8.0,(GLfloat)i/30.0);
glPopMatrix();
OpenGL中定义均匀间隔的曲面坐标值的函数与曲线的类似,其函数形式为:
voidglMapGrid2fd(GLenumnu,TYPEu1,TYPEu2,GLenumnv,TYPEv1,TYPEv2);
voidglEvalMesh2(GLenummode,GLintp1,GLintp2,GLintq1,GLintq2);
第一个函数定义参数空间的均匀网格,从u1到u2分为等间隔的nu步,从v1到v2分为等间隔的nv步,然后glEvalMesh2()把这个网格应用到已经启动的曲面计算上。
第二个函数参数mode除了可以是GL_POINT和GL_LINE外,还可以是GL_FILL,即生成填充空间曲面。
下面举出一个用网格绘制一个经过光照和明暗处理的Bezier曲面的例程:
voidinitlights(void);
/*控制点坐标*/GLfloatctrlpoints443=-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;
voidinitlights(void)GLfloatambient=0.4,0.6,0.2,1.0;
GLfloatposition=0.0,1.0,3.0,1.0;
GLfloatmat_diffuse=0.2,0.4,0.8,1.0;
GLfloatmat_specular=1.0,1.0,1.0,1.0;
GLfloatmat_shininess=80.0;
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);
glLightfv(GL_LIGHT0,GL_POSITION,position);
glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
voidCALLBACKdisplay(void)glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glEvalMesh2(GL_FILL,0,20,0,20);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
initlights();
if(w=h)glOrtho(-4.0,4.0,-4.0*(GLfloat)h/(GLfloat)w,4.0*(GLfloat)h/(GLfloat)w,-4.0,4.0);
elseglOrtho(-4.0*(GLfloat)w/(GLfloat)h,4.0*(GLfloat)w/(GLfloat)h,-4.0,4.0,-4.0,4.0);
voidmain(void)auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,500,500);
auxInitWindow(LightedandFilledBezierSurface);
myinit();
auxReshapeFunc(myReshape);
auxMainLoop(display);
三、图元逼近法绘制三维物体在OpenGL的辅助库中,提供了绘制11种基本几何图形的函数,具体参考第一讲的有关内容,在此不再赘述。
这里我们讨论用另外一种方法来绘制三维物体。
需要注意的是,这里我们用来近似曲面的多边形最好选择三角形,而不是四边形或其他形状的多边形,这是因为三角形的三个顶点在任何时候都位于同一平面内,它一定是非常简单的非凹多边形,而四边形或其他多边形的顶点可能不在同一平面内,也就有可能不是简单多边形,对于这样的多边形,OpenGL是不能正常处理的。
假设我们绘制一个球体,球体表面用很多个小三角形拼接而成,显然,用来近似球面的三角形越小、三角形越多,那么球面就越光滑。
为了简要地说明如何用三角形逼近球体,这里我们使用三角形来构造一个20面体,二十面体的顶点坐标定义在vdata数组中,tindinces数组定义了构成二十面体的二十个三角形顶点的绘制顺序。
下面是主要实现代码:
#definex5.25731#definez8.50651staticGLfloatvdata123=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;
staticGLinttindices203=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(inti=0;
i20;
i+)glBegin(GL_TRIANGLES);
glVertex3fv(&
vdatatindicesi00);
vdatatindicesi10);
vdatatindicesi20);
显然,用正二十面体来表示一个球体显得过于粗糟,可以通过增加面数的方法使正多面体和求更为接近,一种简单的方法是剖分法,即将前面定义的三角形面分成几个面,例如,一分为四,形成4个多边形等,具体实现方法这里就不再赘述了。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- opengl 曲线 曲面