贝齐尔曲面绘制(共23页).doc
精选优质文档-倾情为你奉上目 录专心-专注-专业1 绪论1.1贝齐尔曲面的介绍 到了70年代,法国雷诺汽车公司的工程师贝齐尔(Bezier)创造出一种适用于几何体外形设计的新的曲线表示法。这种方法的优越性在于:对于在平面上随手勾画出的一个多边形(称为特征多边形),只要把其顶点坐标输入计算机,经过不到一秒钟的计算,绘图机就会自动画出同这个多边形很相像、又十分光滑的一条曲线。这种方法被人们称为贝齐尔(Bezier)方法(以下统称为Bezier方法)。 贝齐尔曲线的形状是通过一组多边折线(也称为贝齐尔控制多边形)的各顶点惟一地定义出来的。在该多边折线的各顶点中,只有第一点和最后一点在曲线上,其余的顶点则用来定义曲线的形状。图1-1列举了一些Bezier多边折线和相应的Bezier曲线的形状关系。 图1-1 Bezier曲线 曲线和曲面是计算机图形学中研究的重要内容之一,他们在实际工作中有着广泛的应用。例如,实验数据的曲线表示,设计、优化的曲面表示等。为了外形美观和物理性能最佳,汽车飞机等的外型设计十分重要。由于实际问题不断对曲线和曲面提出新的要求,近几十年来,曲线和曲面理论及其应用得到了很大的发展。1963年,波音飞机公司的Ferguson将曲线曲面表示成参数矢量形式,并用3次参数曲线来构造组合曲线,用4个角点的位置矢量及其两个方向的切向矢量来构造3次曲面。1964年,麻省理工学院的coons用封闭的曲线的4条边界定义一个曲面。同年,Schoenberg给出了参数样条曲线和曲面的形式。1971年,法国雪铁龙汽车公司的De Vasteljau 独立地研究出与Bezier类似的方法。1972年,De Boor给出了B样条的标准计算方法。1974年,美国通用汽车公司的Gordon和Riesenfeld将B样条用于形状描述,提出了B样条曲线和B样条曲面。1975年,美国锡拉丘兹大学的Versprill在其博士论文中提出了有理B样条方法。19世纪80年代后期,美国的Piegl和Tiller将有理B样条发展成为非均匀有理B样条方法。非均匀有理B样条方法已成为当今自由曲线和曲面描述的通用方法,可以统一表示初等解析曲线和曲面、有理与非有理Bezier曲线和曲面以及有理与非有理B样条曲线和曲面。1.2贝齐尔曲面的应用曲面造型(Surface Modeling)是计算机辅助几何设计 (Computer Aided Geometric Design,CAGD)和计算机图形学(Computer Graphics)的一项重要内容,主要研究在计算机图像系统的环境下对曲面的表示、设计、显示和分析。它起源于汽车、飞机、船舶、叶轮等的外形放样工艺,由Coons、Bezier等大师于二十世纪六十年代奠定其理论基础。如今经过三十多年的发展,曲面造型现在已形成了以有理B样条曲面(Rational B-spline Surface)参数化特征设计和隐式代数曲面(Implicit Algebraic Surface)表示这两类方法为主体,以插值(Interpolation)、拟合(Fitting)、逼近(Approximation)这三种手段为骨架的几何理论体系。曲面造型是指在产品设计中对于曲面形状产品外观的一种建模方法,曲面造型方法使用三维CAD软件的曲面指令功能构建产品的外观形状曲面并得到实体化模型。在不同的三维软件比如ProE、UG、CATIA和Solidworks中所使用的指令有所差别,但基本的造型策略都是类似的。形状信息的核心问题是计算机表示,即要解决既适合计算机处理,且有效地满足形状表示与几何设计要求,又便于形状信息传递和产品数据交换的形状描述的数学方法。1971年法国雷诺汽车公司的Bezier提出一种由控制多边形设计曲线的新方法。这种方法不仅简单易用,而且漂亮地解决了整体形状控制问题,把曲线曲面的设计向前推进了一大步,为曲面造型的进一步发展奠定了坚实的基础。但Bezier方法仍存在连接问题和局部修改问题。到1972年,de-Boor总结、给出了关于B样条的一套标准算法,1974年Gordon和Riesenfeld又把B样条理论应用于形状描述,最终提出了B样条方法。这种方法继承了Bezier方法的一切优点,克服了Bezier方法存在的缺点,较成功地解决了局部控制问题,又轻而易举地在参数连续性基础上解决了连接问题,从而使自由型曲线曲面形状的描述问题得到较好解决。但随着生产的发展,B样条方法显示出明显不足,不能精确表示圆锥截线及初等解析曲面,这就造成了产品几何定义的不唯一,使曲线曲面没有统一的数学描述形式,容易造成生产管理混乱。曲面造型由于其实用性,在航空航天、汽车制造、造船、机械制造、电子、电器、消费品行业得到广泛应用。它的集成解决方案覆盖所有的产品设计与制造领域,满足了工业领域各类大、中、小型企业的需要。2 贝齐尔曲面设计2.1 贝齐尔曲面定义设为个空间点列,则m×n次Bezier曲面定义为: (式2-1) 其中 ,是Bernstein基函数。依次用线段连接点列中相邻两点所形成的空间网格,称之为特征网格。Bezier曲面的矩阵表示式是: (式2-2)在一般实际应用中,n、m不大于4。(1) 双线性Bezier曲面 当m=n=1时 u,w0,1 (式2-3)定义一张双线性Bezier曲面。已知四个角点之后,则 (式2-4) (2) 双二次Bezier曲面 当m=n=2时 (式2-5)由此式定义的曲面,其边界曲线及参数坐标曲线均为抛物线。 (3) 双三次Bezier曲面 当m=n=3时 (式2-6) (式2-7)其矩阵表示为 (式2-8)2.2 贝齐尔曲面性质 1Bezier曲面特征网格的四个角点正好是Bezier曲面的四个角点,即 P(0,0)=P00 P(1,0)=PM0 P(0,1)=P0N P(1,1)=PMN2. Bezier曲面特征网格最外一圈顶点定义Bezier曲面的四条边界;Bezier曲面边界的跨界切矢只能与定义该边界的顶点及相邻一排顶点有关,且P00P10P01, P0nP1nP0,n-1, Pm0Pm-1,0Pm1,分别是四个角点的切平面;跨界二阶导矢只与定义该边界的及相邻两排顶点有关。几何不变性、凸包性、对称性等性质可由Bezier曲线的相关性质容易推广得到。图2-1 阴影三角形2.3 贝齐尔曲面算法Bezier曲线的递推(de Casteljau)算法,可以推广到Bezier曲面的情形。若给定Bezier曲面特征网格的控制顶点:和一对参数值(u,v),则: 式(2-9)一条曲线可以表示成两条低一次曲线的组合,一张曲面可以表示成低一次的四张曲面的线性组合。其中: 式(2-10)或: 式(2-11)上面给出了确定曲面上一点的两种方案。当按(1)式方案执行时,先以u参数值对控制网格u向的n+1个多边形执行曲线de Casteljau算法,m级递推后,得到沿v向由n+1个顶点构成的中间多边形。再以v参数值对它执行曲线的de Casteljau算法,n级递推以后,得到一个,即所求曲面上的点。也可以按(2) 式方案执行,先以v参数值对控制网格沿v向的m+1个多边形执行n级递推,得沿u向由m+1个顶点构成的中间多边形。再以u参数值对它执行n级递推,得所求点。2.4 程序设计步骤2.4.1 Bezier曲面的生成Bezier曲面是基于Beizer曲线而定义的,有特征网格决定其大致形状,而特征网格是由控制点确定的。因而,绘制Bezier曲面的步骤与绘制Bezie曲面的步骤是一致的: 第一,定义控制点序列; 第二,定义一个二维评价器; 第三,激活二维评价器; 最后,创建网格。 定义一个二维评价器的函数为:glMap2d()或glMap2f()函数,glMap2d()函数的原型为: Void glMap2d(GLenum target, GLdouble u1, GLdouble u2, Glint ustride, Glint uorder, GLdouble v1, GLdouble v2, Glint vorder, Glint uorder, const GLdouble * points);其中,target参数表示评价器最后生成的坐标类别,它可以取表2-1中的一个常量:常 量含 义GL_MAP2_VERTEX_3用(x,y,z)描述一个控制点GL_MAP2_VERTEX_4用(x,y,z,w)描述一个控制点GL_MAP2_INDEX控制点代表一个颜色素引值GL_MAP2_COLOR_4控制点是RGBA颜色值GL_MAP2_NORMAL控制点是一个法线向量GL_MAP2_TEXTURE_COORD_1控制点是一个纹理坐标的s分量GL_MAP2_TEXTURE_COORD_2控制点是一个(s,t)纹理坐标GL_MAP2_TEXTURE_COORD_3控制点是一个(s,t,r)纹理坐标GL_MAP2_TEXTURE_COORD_4控制点是一个(s,t,r,q)纹理坐标表2-12.4.2 绘制网格曲面(1)添加一个菜单添加一个名为Surface的菜单,在其属性对话框里的Caption栏中键入Surface。为其增加一个菜单项,其名为Bezier,在其属性对话框的Caption栏中键入Bezier,勾选Pop-up属性。按表2-2完成。CaptionID&MeahIDM_BZRSUFAC_MESH&FillIDM_BZRSUFAC_FILL&TextureIDM_BZRSUFAC_TEXTURE表2-2(2)添加保护成员函数 添加一个保护成员函数:BzeSufacMesh(),编辑如下:Int I,j; GLfloat points443= -0.8f,-0.6f,0.8f,-0.2f,-0.6f,1.6f,0.2f,-0.6f,-0.4f,0.6f,-0.6f,0.8f,-0.6f,-0.2f,0.8f,-0.2f,-0.2f,1.6f,0.2f,-0.2f,-0.4f,0.6f,-0.2f,0.8f,-0.6f,0.2f,0.8f,-0.2f,0.2f,0.4f,0.2f,0.2f,0.0f,0.3f,0.2f,-0.4f,-0.6f,0.6f,0.8f,-0.2f,0.6f,0.4f,-0.8f,0.6f,0.0f,0.8f,0.6f,-0.4f; /控制点glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,(float*)controlPoints);/ 二维评价器glEnable(GL_MAP2_VERTEX_3);glColor3f(0,0,1); /激活glPushMatrix();glRotated(45,1,1,1);for (j=0;j<8;j+)glBegin(GL_LINE_STRIP);for (i=0;i<30;i+)glEvalCoord2f(float)i/30,(float)j/8);glEnd();glBegin(GL_LINE_STRIP);for (i=0;i<30;i+)glEvalCoord2f(float)j/8,(float)i/30);glEnd(); glPopMatrix(); /绘制glDisable(GL_MAP2_VERTEX_3); /挂起该函数将绘制一个网格曲面,因为glBegin()函数的参数为GL_LINE_STRIP。(3)编辑DrawScenc()函数在语句switch(m_typeControl).中添加语句:Case BezierSrufaceMesh: BzrSufacMesh(); break;(4)运行程序,得到如图2-2的结果图2-2 Bezier网格曲面2.4.3 绘制一个填充曲面(1)增加两个保护函数Lighting()和BzrSufacFill()函数, Lighting()函数光照处理,BzrSufacFill()函数则绘制曲面。 Lighting();glEnable(GL_AUTO_NORMAL);glEnable(GL_NORMALIZE); /光照glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,(float*)controlPoints); /二维评价器glMapGrid2f(30,0,1,30,0,1); /自动网格glEnable(GL_MAP2_VERTEX_3); /激活glPushMatrix();glRotated(45,1,1,1);glEvalMesh2(GL_FILL,0,30,0,30);glPopMatrix(); /绘制glDisable(GL_MAP2_VERTEX_3);glDisable(GL_AUTO_NORMAL);glDisable(GL_NORMALIZE);glDisable(GL_LIGHTING); /挂起 (2)编辑DrawScene()函数 在语句switch(m_typeControl).中添加语句; Case BezierSurfaceFill: BzeSufacFill(); break; (3)运行程序,得到如图2-3的结果图2-3 Beizer填充曲面2.4.4 三次贝齐尔曲面通过改变控制点坐标即可改变曲面的形状,这是Bezier曲面的一个特性。说明:程序输出的是斜二测投影图,X轴正方向向右,Y轴正方向向下,X、Y、Z三个轴正方成右手坐标系曲面显示在Z轴负坐标的位置上。图2-4中所示为轮船船艏,首柱线与设计水线交于曲面的右上角;最大横剖线与设计水线交于曲面左上角:曲面右下角为首柱线与龙骨线的切点或交点:曲面左下角为最大横剖线与底部龙骨起跑线的交点。图2-4 运行结果2.5 主程序#include "StdAfx.h"#include "OpenGL.h" /添加头文件名/#include <math.h>#include "bitmap.h"#define PI (double)3.)#define RADIANS(fAngle) (double)(fAngle)*PI/180.0)COpenGL:COpenGL(void):type(MESH) /类型网格/GLfloat points443=/ GLfloat points4*4*3=/ /-0.8f,-0.6f,0.8f,-0.2f,-0.6f,1.6f,0.2f,-0.6f,-0.4f,0.6f,-0.6f,0.8f,/-0.6f,-0.2f,0.8f,-0.2f,-0.2f,1.6f,0.2f,-0.2f,-0.4f,0.6f,-0.2f,0.8f,/ -0.6f,0.2f,0.8f,-0.2f,0.2f,0.4f,0.2f,0.2f,0.0f,0.3f,0.2f,-0.4f,/ -0.6f,0.6f,0.8f,-0.2f,0.6f,0.4f,-0.8f,0.6f,0.0f,0.8f,0.6f,-0.4f/ ; / 输入各点坐标 / for(int i=0;i<4;i+)/ for (int j=0;j<4;j+)/ for (int m=0;m<3;m+)/ controlPointsijm=pointsi*4*3+j*3+m;/ / / COpenGL:COpenGL(void) /添加函数类型为void/wglMakeCurrent(hDC, NULL);wglDeleteContext(hRC);void COpenGL:Init(void)glClearColor(1.0,1.0,1.0,1.0); glClearDepth(1.0);glEnable(GL_DEPTH_TEST);glShadeModel(GL_SMOOTH);glDepthFunc(GL_LEQUAL);glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);bool COpenGL:SetupPixelFormat(HDC hDC0)int nPixelFormat; hDC=hDC0;PIXELFORMATDESCRIPTOR pfd = sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 ; if (!(nPixelFormat = ChoosePixelFormat(hDC, &pfd) MessageBox(NULL,"can not find proper mode","Error",MB_OK|MB_ICONEXCLAMATION); /若错误则显示can not find proper mode error/return FALSE; /返回FLASH/SetPixelFormat(hDC,nPixelFormat,&pfd);hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); return TRUE; /返回TURE/void COpenGL:Reshape(int width,int height)/ glViewport(0,0,width,height);/ glMatrixMode(GL_PROJECTION);/ glLoadIdentity();/ gluPerspective(60,(GLfloat)width/(GLfloat)height,0.1,3000.0);/ glMatrixMode(GL_MODELVIEW);glViewport(0,0,width,height);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60,(GLfloat)width/(GLfloat)height,0.1,3000.0);glMatrixMode(GL_MODELVIEW);/glMatrixMode(GL_MODELVIEW);enum AspectFRONT,BACK,LEFT,RIGHT,UP,DOWN;enum ColorBLUE,GREEN,RED,ORANGE,WHITE,YELLOW; /代表颜色索引值/const GLubyte colorTable63=0,0,255,0,255,0,255,0,0,255,102,0,255,255,255,255,255,0;void COpenGL:Render()glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glLoadIdentity();gluLookAt(0,0,3,0,0,0,0,1,0);switch(type)case MESH:DrawMesh(); /绘制网格/break;case FILL:DrawFill(); /绘制填充曲面/break;case TEXTURE:DrawTexture(); /绘制贴图曲面/break;default:break;/draw stuff/ draw cube/ GLint vertices83=/ -1,-1,-1,1,-1,-1,-1,-1,1,1,-1,1,/ -1,1,-1,1,1,-1,-1,1,1,1,1,1/ ;/ /in order:front ,back ,left ,right,top,bottom/ GLubyte vertIndex64=/ 6,2,3,7,/ 5,1,0,4,/ 4,0,2,6,/ 7,3,1,5,/ 7,5,4,6,/ 2,0,1,3/ ;/ for (int i=0;i<6;i+)/ glColor3ubv(colorTablei);/ glBegin(GL_QUADS);/ for (int j=0;j<4;j+)/ glVertex3iv(verticesvertIndexij);/ / glEnd();/ glFlush();SwapBuffers(hDC);void COpenGL:DrawMesh()GLfloat controlPoints443=-0.8f,-0.6f,0.8f,-0.2f,-0.6f,1.6f,0.2f,-0.6f,-0.4f,0.6f,-0.6f,0.8f,-0.6f,-0.2f,0.8f,-0.2f,-0.2f,1.6f,0.2f,-0.2f,-0.4f,0.6f,-0.2f,0.8f,-0.6f,0.2f,0.8f,-0.2f,0.2f,0.4f,0.2f,0.2f,0.0f,0.3f,0.2f,-0.4f,-0.6f,0.6f,0.8f,-0.2f,0.6f,0.4f,-0.8f,0.6f,0.0f,0.8f,0.6f,-0.4f; /定义控制点/int i,j;glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,(float*)controlPoints); /二维评价器/glEnable(GL_MAP2_VERTEX_3);glColor3f(0,0,1); /激活/glPushMatrix();glRotated(45,1,1,1);for (j=0;j<8;j+)glBegin(GL_LINE_STRIP);for (i=0;i<30;i+)glEvalCoord2f(float)i/30,(float)j/8);glEnd();glBegin(GL_LINE_STRIP);for (i=0;i<30;i+)glEvalCoord2f(float)j/8,(float)i/30);glEnd();glPopMatrix(); /绘制/glDisable(GL_MAP2_VERTEX_3); /挂起/ /该函数将绘制一个网格曲面/void COpenGL:DrawFill() /绘制填充曲面/GLfloat controlPoints443=-0.8f,-0.6f,0.8f,-0.2f,-0.6f,1.6f,0.2f,-0.6f,-0.4f,0.6f,-0.6f,0.8f,-0.6f,-0.2f,0.8f,-0.2f,-0.2f,1.6f,0.2f,-0.2f,-0.4f,0.6f,-0.2f,0.8f,-0.6f,0.2f,0.8f,-0.2f,0.2f,0.4f,0.2f,0.2f,0.0f,0.3f,0.2f,-0.4f,-0.6f,0.6f,0.8f,-0.2f,0.6f,0.4f,-0.8f,0.6f,0.0f,0.8f,0.6f,-0.4f /输入控制点/;Lighting(); /增加光照函保护成员数/glEnable(GL_AUTO_NORMAL);glEnable(GL_NORMALIZE); /光照函数/glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,(float*)controlPoints); /二维评价器/glMapGrid2f(30,0,1,30,0,1); /自动网格/glEnable(GL_MAP2_VERTEX_3); /激活/glPushMatrix();glRotated(45,1,1,1);glEvalMesh2(GL_FILL,0,30,0,30);glPopMatrix(); /绘制/glDisable(GL_MAP2_VERTEX_3);glDisable(GL_AUTO_NORMAL);glDisable(GL_NORMALIZE);glDisable(GL_LIGHTING); /挂起/void COpenGL:DrawTexture() /绘制贴图曲面/GLfloat controlPoints443=-0.8f,-0.6f,0.8f,-0.2f,-0.6f,1.6f,0.2f,-0.6f,-0.4f,0.6f,-0.6f,0.8f,-0.6f,-0.2f,0.8f,-0.2f,-0.2f,1.6f,0.2f,-0.2f,-0.4f,0.6f,-0.2f,0.8f,-0.6f,0.2f,0.8f,-0.2f,0.2f,0.4f,0.2f,0.2f,0.0f,0.3f,0.2f,-0.4f,-0.6f,0.6f,0.8f,-0.2f,0.6f,0.4f,-0.8f,0.6f,0.0f,0.8f,0.6f,-0.4f; /几何控制点/GLfloat textureCntrlPnt222=0,0,0,1,1,0,1,1; /纹理控制点/AUX_RGBImageRec *textureImage=LoadBMP("song.bmp"); /载入song.bmp图片/ Load The Bitmap, Check For Errors, If Bitmap's Not Found Quitif (textureImage)glPixelStoref(GL_UNPACK_ALIGNMENT,1);glTexImage2D(GL_TEXTURE_2D,0,3,textureImage->sizeX,textureImage->sizeY,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,textureImage->data);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL); /构造纹理/glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,(float*)controlPoints); glMap2f(GL_MAP2_TEXTURE_COORD_2,0,1,2,2,0,1,4,2,(float*)controlPoints); /二维评价器:生成几何坐标和纹理坐标/Lighting();glEnable(GL_TEXTURE_2D);glEnable(GL_MAP2_TEXTURE_COORD_2);glEnable(GL_MAP2_VERTEX_3);glEnable(GL_AUTO_NORMAL);glEnable(GL_NORMALIZE); /光照/glMapGrid2f(30,0,1,30,0,1);glPushMatrix();glScaled(1.2,1.2,1.2);glRotated(45,0,0,1);glRotated(45,1,1,1);glEvalMesh2(GL_FILL,0,30,0,30);glPopMatrix(); /绘制/glDisable(GL_MAP2_VERTEX_3);glDisable(GL_MAP2_TEXTURE_COORD_2);glDisable(GL_TEXTURE_2D);glDisable(GL_AUTO_NORMAL);glDisable(GL_NORMALIZE);glDisable(GL_LIGHTING); /挂起/elseMessageBox(NULL,"failed to load image"," ",MB_OK);void COpenGL:Lighting() /编辑光照函数/GLfloat lightAmb=0.2,0.2,0.2,1;GLfloat lightPos=1,1,2,1;GLfloat matDiffuse=0,0.7,0.7,1;GLfloat matSpecular=1,1,1,1;GLfloat matShininess=60;glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glLightfv(GL_LIGHT0,GL_AMBIENT,lightAmb);glLightfv(GL_LIGHT0,GL_POSITION,lightPos);glMaterialfv(GL_FRONT,GL_DIFFUSE,matDiffuse);glMaterialfv(GL_FRONT,GL_SPECULAR,matSpecular);