cadcam实验贝齐尔(Bezier)曲线曲面的生成方法

更新时间:2024-05-28 03:48:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

1贝齐尔曲面设计 1.1 贝齐尔曲面定义

设Pij(0,1,?n;j?0,1,?m)为(n?1)?(m?1)个空间点列,则m×n次Bezier曲面定义为:

P(u,v)???PijBi,m(u)Bj,n(v)i?0j?0iiBi,m(u)?Cmu(1?u)m?imnu,v?[0,1] (式2-1)

其中

Bi,n(v)?Cnjvj(1?v)n?j是Bernstein基函数。依次用线段连

接点列中相邻两点所形成的空间网格,称之为特征网格。

Bezier曲面的矩阵表示式是:

?P00?PP(u,v)??B0,n(u),B1,n(u),?,Bm,n(u)??10????Pn0在一般实际应用中,n、m不大于4。 (1) 双线性Bezier曲面 当m=n=1时

P01?P0m??B0,m(v)??B(v)?P11?P1m???1,m???????????Pn1?Pnm??Bn,m(v)? (式2-2)

11S(u,w)???Bi,1(u)Bj,1(w)piji?0j?0 u,w∈[0,1] (式2-3)

定义一张双线性Bezier曲面。

已知四个角点之后,则

S(u,w)?(1?w)(1?u)?(1?u)p?(1?w)upuwp00011011 (式2-4)

(2) 双二次Bezier曲面 当m=n=2时

S(u,w)???Bi,2(u)Bj,2(w)piji?0j?022 u,w?[0,1] (式2-5)

由此式定义的曲面,其边界曲线及参数坐标曲线均为抛物线。 (3) 双三次Bezier曲面 当m=n=3时

S(u,w)???Bi,3(u)Bj,3(w)piji?0j?033 u,w?[0,1] (式2-6)

?p00?p10S(u,w)?[B0,3(u)B1,3(u)B2,3(u)B3,3(u)]??p20??p30其矩阵表示为

TS(u,w)?UMZBZMZWTp01p11p21p31p02p12p22p32p03??B0,3(w)??B1,3(w)?p13????p23??B2,3(w)????p33??B3,3(w)? (式2-7)

??13?3?3?633232U?[uuu1],W?[www1],Mz????330?00?11?0??0??0?(式2-8)

1.2 贝齐尔曲面性质

1.Bezier曲面特征网格的四个角点正好是Bezier曲面的四个角点,即

P(0,0)=P00 P(1,0)=PM0 P(0,1)=P0N P(1,1)=PMN 2. Bezier曲面特征网格最外一圈顶点定义Bezier曲面的四条边界;Bezier曲面边界的跨界切矢只能与定义该边界的顶点及相邻一排顶点有关,且

P00P10P01, P0nP1nP0,n-1, Pm0Pm-1,0Pm1,

分别是四个角点的切平面;跨界二阶导矢只与定义该边界的及相邻两排顶点有关。几何不变性、凸包性、对称性等性质可由Bezier曲线的相关性质容易推广得到。

图2-1 阴影三角形 1.3 贝齐尔曲面算法

Bezier曲线的递推(de Casteljau)算法,可以推广到Bezier曲面的情形。若给定Bezier曲面特征网格的控制顶点:pij(i?0,1,?m,j?0,1,?n)和一对参数值(u,v),则:

m.n

P(u,v)?Pi,kj,lBi,m(u)Bj,n(v)???P00u,v?[0,1] i j ? 0 式(2-9) ?0一条曲线可以表示成两条低一次曲线的组合,一张曲面可以表示成低一次的四张曲面的线性组合。

m?kn?l??Pi,kj,l其中:

?Pij?k?1,0??(1?u)Pijk?1,0?uPi?1,j?(1?v)Pm,l?1?vPm,l?10,j0,j?1?(k?l?0)(k?1,2,?,m;l?0)(k?m,l?1,2,?,n) 式(2-10)

Pijk,l或: 式(2-11)

上面给出了确定曲面上一点的两种方案。当按(1)式方案执行时,先以u参数值对控制网格u向的n+1个多边形执行曲线de Casteljau算法,m级递推后,得到沿v向由n+1个顶点的中间多边形。

再以v参数值对它执行曲线的de Casteljau算法,n级递推以后,得到一个

mnP00?Pij?1??(1?v)Pij0,l?1?vPi,0j,l??1?(1?u)Pk?1,n?uPk?1,ni0i?1,0?(k?l?0)(k?0;l?1,2,?,n)(k?1,2,?,m;l?n)m0p0j(j?0,1,?n)构成

,即所求曲面上的点。

也可以按(2) 式方案执行,先以v参数值对控制网格沿v向的m+1个多边形执行n级递推,得沿u

0np(i?0,1,?m)构成的中间多边形。再以u参数值对它执行n级递推,得所求点i向由m+1个顶点0mnP00。

1.4 程序设计步骤

1.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 GL_MAP2_VERTEX_4 GL_MAP2_INDEX GL_MAP2_COLOR_4 GL_MAP2_NORMAL GL_MAP2_TEXTURE_COORD_1 GL_MAP2_TEXTURE_COORD_2 GL_MAP2_TEXTURE_COORD_3 GL_MAP2_TEXTURE_COORD_4 表2-1 1.4.2 绘制网格曲面 (1)添加一个菜单

含 义 用(x,y,z)描述一个控制点 用(x,y,z,w)描述一个控制点 控制点代表一个颜色素引值 控制点是RGBA颜色值 控制点是一个法线向量 控制点是一个纹理坐标的s分量 控制点是一个(s,t)纹理坐标 控制点是一个(s,t,r)纹理坐标 控制点是一个(s,t,r,q)纹理坐标

添加一个名为Surface的菜单,在其属性对话框里的Caption栏中键入Surface。为其增加一个菜单项,其名为Bezier,在其属性对话框的Caption栏中键入Bezier,勾选Pop-up属性。按表2-2完成。

Caption &Meah &Fill &Texture ID IDM_BZRSUFAC_MESH IDM_BZRSUFAC_FILL IDM_BZRSUFAC_TEXTURE 表2-2

(2)添加保护成员函数

添加一个保护成员函数:BzeSufacMesh(),编辑如下: {

Int I,j;

GLfloat points[4][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}} };} ////控制点

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网格曲面 1.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填充曲面 1.4.4 三次贝齐尔曲面

通过改变控制点坐标即可改变曲面的形状,这是Bezier曲面的一个特性。说明:程序输出的是斜二

测投影图,X轴正方向向右,Y轴正方向向下,X、Y、Z三个轴正方成右手坐标系.曲面显示在Z轴负坐标的位置上。图2-4中所示为轮船船艏,首柱线与设计水线交于曲面的右上角;最大横剖线与设计水线交于曲面左上角:曲面右下角为首柱线与龙骨线的切点或交点:曲面左下角为最大横剖线与底部龙骨起跑线的交点。

图2-4 运行结果

2.5 主程序

#include \

#include \ /添加头文件名/ #include #include \

#define PI ((double)3.1415926)

#define RADIANS(fAngle) ((double)(fAngle)*PI/180.0)

COpenGL::COpenGL(void):type(MESH) /类型网格/ { //GLfloat points[4][4][3]= // GLfloat points[4*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++){ // controlPoints[i][j][m]=points[i*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,\not find proper mode\TION); /若错误则显示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 Aspect{FRONT,BACK,LEFT,RIGHT,UP,DOWN};

enum Color{BLUE,GREEN,RED,ORANGE,WHITE,YELLOW}; /代表颜色索引值/ const GLubyte colorTable[6][3]={ {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 vertices[8][3]={ // {-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 vertIndex[6][4]={ // 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(colorTable[i]); // glBegin(GL_QUADS); // for (int j=0;j<4;j++){ // glVertex3iv(vertices[vertIndex[i][j]]); // } // glEnd(); // } glFlush(); SwapBuffers(hDC); }

void COpenGL::DrawMesh() { GLfloat controlPoints[4][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}} }; /定义控制点/ 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 controlPoints[4][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}} /输入控制点/ }; 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 controlPoints[4][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}} }; /几何控制点/ GLfloat textureCntrlPnt[2][2][2]={0,0,0,1,1,0,1,1 }; /纹理控制点/

AUX_RGBImageRec *textureImage=LoadBMP(\ /载入song.bmp图片/ // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit if (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); /挂起/ }else{ MessageBox(NULL,\ } }

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); glMaterialfv(GL_FRONT,GL_SHININESS,matShininess); }

AUX_RGBImageRec * COpenGL::LoadBMP(char* fileName) { FILE *file=NULL; if (!fileName){ return NULL; } file=fopen(fileName,\

/载入文件格式为bmp图片/

if (file){ fclose(file); return auxDIBImageLoad(fileName); } return NULL; }

int COpenGL::LoadTextureFromFile(char *filename, GLuint *hTexture) { int Status=FALSE; AUX_RGBImageRec *textureImage=LoadBMP(filename); // Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit if (textureImage){ Status=TRUE; glGenTextures(1,hTexture); // Typical Texture Generation Using Data From The Bitmap glBindTexture(GL_TEXTURE_2D, *hTexture); glTexImage2D(GL_TEXTURE_2D, 0, 3, textureImage->sizeX, textureImage->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE, textureImage->data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); } if (textureImage){ if (textureImage->data){ free(textureImage->data); } free(textureImage); }

return Status;

本文来源:https://www.bwwdw.com/article/bs67.html

Top