《计算机图形学试验优秀课件.ppt》由会员分享,可在线阅读,更多相关《计算机图形学试验优秀课件.ppt(70页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、计算机图形学试验第1页,本讲稿共70页试验1:创建一个OpenGL窗口 v打开VC然后创建一个新工程,创建一个新的Win32程序(不是console控制台程序)第2页,本讲稿共70页v链接OpenGL库文件,Project-Settings,(工程设置)然后单击LINK标签:增加 OpenGL32.lib GLu32.lib 和 GLaux.lib 后单击OK按钮。第3页,本讲稿共70页v代码的前3行包括了我们使用的每个库文件的头文件。如下所示:#include /Windows的头文件#include /包含最新的gl.h,glu.h库#include /包含OpenGL实用库 第4页,本讲
2、稿共70页v完成程序的开发。如下图所示v参考程序第5页,本讲稿共70页试验2:绘制简单图形vglLoadIdentity(),重置当前的模型观察矩阵,将当前点移到了屏幕中心,X坐标轴从左至右Y坐标轴从下至上,Z坐标轴从里至外。OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。第6页,本讲稿共70页vglTranslatef(x,y,z)沿着 X,Y 和 Z 轴移动。glTranslatef(-1.5f,0.0f,-6.0f);/左移 1.5 单位,并移入屏幕 6.0 第7页,本讲稿共70页glBegin(GL_TRIANGLES);/绘制三角形 glVertex3f(0.0f,-1.0f,
3、0.0f);/上顶点 glVertex3f(-1.0f,-1.0f,0.0f);/左下顶点 glVertex3f(1.0f,-1.0f,0.0f);/右下顶点 glEnd();/三角形绘制结束 0.0f,1.0f,0.0f0.0f,1.0f,0.0f-1.0f,-1.0f,0.0f-1.0f,-1.0f,0.0f1.0f,-1.0f,0.0f1.0f,-1.0f,0.0f第8页,本讲稿共70页glBegin(GL_QUADS);/绘制正方形 glVertex3f(-1.0f,1.0f,0.0f);/左上 glVertex3f(1.0f,1.0f,0.0f);/右上 glVertex3f(1.0
4、f,-1.0f,0.0f);/左下 glVertex3f(-1.0f,-1.0f,0.0f);/右下 glEnd();/正方形绘制结束-1.0f,1.0f,0.0f1.0f,1.0f,0.0f1.0f,-1.0f,0.0f-1.0f,-1.0f,0.0f第9页,本讲稿共70页v在在第一实验的基础上,在完成程序的 DrawGLScene()过程中增加代码:glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);/清除屏幕及深度缓存 glLoadIdentity();/重置当前的模型观察矩阵 glTranslatef(-1.5f,0.0f,-6.0f);/
5、左移 1.5 单位,并移入屏幕 6.0 glBegin(GL_TRIANGLES);/绘制三角形 glVertex3f(0.0f,1.0f,0.0f);/上顶点上顶点 glVertex3f(-1.0f,-1.0f,0.0f);/左下左下 glVertex3f(1.0f,-1.0f,0.0f);/右下右下 glEnd();第10页,本讲稿共70页glTranslatef(3.0f,0.0f,0.0f);/右移3单位 glBegin(GL_QUADS);/绘制正方形 glVertex3f(-1.0f,1.0f,0.0f);/左上 glVertex3f(1.0f,1.0f,0.0f);/右上 glV
6、ertex3f(1.0f,-1.0f,0.0f);/左下 glVertex3f(-1.0f,-1.0f,0.0f);/右下 glEnd();/正方形绘制结束画完三角形后,我们要移到右半部分来画正方形。否则两个图形会相互重叠第11页,本讲稿共70页v完成程序的开发。如下图所示v参考程序第12页,本讲稿共70页试验3 着色vglColor3f(r,g,b)。括号中的三个参数依次是红、绿、蓝三色分量。参数取值范围从0,0f到1.0f。glColor3f(1.0f,0.0f,0.0f)红色红色glColor3f(0.0f,1.0f,0.0f)绿色绿色glColor3f(0.0f,0.0f,1.0f)蓝
7、色蓝色第13页,本讲稿共70页v修改实验2中,画三角形的代码为:glBegin(GL_TRIANGLES);/绘制三角形 glColor3f(1.0f,0.0f,0.0f);/设置当前色为红色设置当前色为红色 glVertex3f(0.0f,1.0f,0.0f);/上顶点上顶点 glColor3f(0.0f,1.0f,0.0f);/设置当前色为绿色设置当前色为绿色 glVertex3f(-1.0f,-1.0f,0.0f);/左下左下 glColor3f(0.0f,0.0f,1.0f);/设置当前色为蓝色设置当前色为蓝色 glVertex3f(1.0f,-1.0f,0.0f);/右下右下 glE
8、nd();第14页,本讲稿共70页v修改实验2中,画正方形的代码为:glColor3f(0.5f,0.5f,1.0f);/一次性将当前色设置为蓝色 glBegin(GL_QUADS);/绘制正方形 glVertex3f(-1.0f,1.0f,0.0f);/左上 glVertex3f(1.0f,1.0f,0.0f);/右上 glVertex3f(1.0f,-1.0f,0.0f);/左下 glVertex3f(-1.0f,-1.0f,0.0f);/右下 glEnd();/正方形绘制结束 第15页,本讲稿共70页v完成程序的开发。如下图所示v参考程序第16页,本讲稿共70页试验4 旋转vglRota
9、tef(Angle,Xvector,Yvector,Zvector)负责让对象绕某个轴旋转。Xvector,Yvector 和 Zvector 三个参数则共同决定旋转轴的方向。比如(1,0,0)所描述的矢量经过X坐标轴的1个单位处并且方向向右。(-1,0,0)所描述的矢量经过X坐标轴的1个单位处,但方向向左。第17页,本讲稿共70页X轴您正在使用一台台锯。锯片中心的轴从左至右摆放(就像OpenGL中的X轴)。尖利的锯齿绕着X轴狂转,看起来要么向上转,要么向下转。取决于锯片开始转时的方向。这与我们在OpenGL中绕着X轴旋转什么的情形是一样的。Y轴假设您正处于一个巨大的龙卷风中心,龙卷风的中心从
10、地面指向天空(就像OpenGL中的Y轴)。垃圾和碎片围着Y轴从左向右或是从右向左狂转不止。这与我们在OpenGL中绕着Y轴旋转什么的情形是一样的。Z轴您从正前方看着一台风扇。风扇的中心正好朝着您(就像OpenGL中的Z轴)。风扇的叶片绕着Z轴顺时针或逆时针狂转。这与我们在OpenGL中绕着Z轴旋转什么的情形是一样的。第18页,本讲稿共70页v在实验3中画三角形的语句前添加 glRotatef(rtri,0.0f,1.0f,0.0f);/绕Y轴旋转三角形 在屏幕的左面画了一个彩色渐变三角形,并绕着Y轴从左向右旋转。第19页,本讲稿共70页v在实验3中画正方形的前面加上语句:glRotatef(r
11、quad,1.0f,0.0f,0.0f);/绕X轴旋转四边形 第20页,本讲稿共70页v完成程序,后效果如下:v参考程序第21页,本讲稿共70页试验5 三维图形v给三角形增加一个左侧面,一个右侧面,一个后侧面来生成一个金字塔(四棱锥)。计算好坐标,绘制其它侧面三角形的方法相同。注意所有的面三角形都是逆时针次序绘制的注意所有的面三角形都是逆时针次序绘制的 第22页,本讲稿共70页v给正方形增加左、右、上、下及背面生成一个立方体。计算好坐标,绘制其它侧面正方形的方法相同。所有的四边形都以逆时针次序绘制。第23页,本讲稿共70页v在3D空间创建对象的方法。必须将OpenGL屏幕想象成一张很大的画纸,
12、后面还带着许多透明的层。差不多就是个由大量的点组成的立方体。这些点从左至右、从上至下、从前到后的布满了这个立方体。如果您能想象的出在屏幕的深度方向,应该在设计新3D对象时没有任何问题。第24页,本讲稿共70页v程序完成的,效果如下:v参考程序第25页,本讲稿共70页试验6 纹理映射 v在第一实验代码开始处增加新代码:#include 第26页,本讲稿共70页v在 ReSizeGLScene()之前,增加了下面这一段代码。用来加载位图文件 AUX_RGBImageRec*LoadBMP(char*Filename)/载入位图图象 FILE*File=NULL;/文件句柄 if(!Filename
13、)/确保文件名已提供 return NULL;/如果没提供,返回 NULL File=fopen(Filename,“r”);/尝试打开文件 if(File)/文件存在么?fclose(File);/关闭句柄 return auxDIBImageLoad(Filename);/载入位图并返回指针 return NULL;/如果载入失败,返回 NULL 第27页,本讲稿共70页涉及到的函数vglGenTextures(1,&texture0)告诉OpenGL想生成一个纹理名字(如果想载入多个纹理,加大数字)。第28页,本讲稿共70页vglBindTexture(GL_TEXTURE_2D,tex
14、ture0)告诉OpenGL将纹理名字 texture0 绑定到纹理目标上。2D纹理只有高度(在 Y 轴上)和宽度(在 X 轴上)。主函数将纹理名字指派给纹理数据。第29页,本讲稿共70页vglTexImage2D(GL_TEXTURE_2D,0,3,TextureImage0-sizeX,TextureImage0-sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage0-data);告诉OpenGL此纹理是一个2D纹理(GL_TEXTURE_2D)。参数“0”代表图像的详细程度,通常就由它为零去了。参数三是数据的成分数。因为图像是由红色数据,绿色数据,蓝色
15、数据三种组分组成。TextureImage0-sizeX 是纹理的宽度。如果您知道宽度,您可以在这里填入,但计算机可以很容易的为您指出此值。TextureImage0-sizey 是纹理的高度。参数零是边框的值,一般就是“0”。GL_RGB 告诉OpenGL图像数据由红、绿、蓝三色数据组成。GL_UNSIGNED_BYTE 意味着组成图像的数据是无符号字节类型的。最后.TextureImage0-data 告诉OpenGL纹理数据的来源。此例中指向存放在 TextureImage0 记录中的数据。第30页,本讲稿共70页vglTexParameteri()告诉OpenGL在显示图像时,当它比放
16、大得原始的纹理大(GL_TEXTURE_MAG_FILTER)或缩小得比原始得纹理小(GL_TEXTURE_MIN_FILTER)时OpenGL采用的滤波方式。通常这两种情况下都采用 GL_LINEAR。第31页,本讲稿共70页vglBindTexture(GL_TEXTURE_2D,texture 所使用纹理对应的数字)选择要绑定的纹理。当您想改变纹理时,应该绑定新的纹理。有一点值得指出的是,您不能在 glBegin()和 glEnd()之间绑定纹理,必须在 glBegin()之前或 glEnd()之后绑定。第32页,本讲稿共70页v为了将纹理正确的映射到四边形上,您必须将纹理的右上角映射到
17、四边形的右上角,纹理的左上角映射到四边形的左上角,纹理的右下角映射到四边形的右下角,纹理的左下角映射到四边形的左下角。如果映射错误的话,图像显示时可能上下颠倒,侧向一边或者什么都不是。glTexCoord2f 的第一个参数是X坐标。0.0f 是纹理的左侧。0.5f 是纹理的中点,1.0f 是纹理的右侧。glTexCoord2f 的第二个参数是Y坐标。0.0f 是纹理的底部。0.5f 是纹理的中点,1.0f 是纹理的顶部。v所以纹理的左上坐标是 X:0.0f,Y:1.0f,四边形的左上顶点是 X:-1.0f,Y:1.0f。其余三点依此类推。v试着玩玩 glTexCoord2f 的X,Y坐标参数。
18、把 1.0f 改为 0.5f 将只显示纹理的左半部分,把 0.0f 改为 0.5f 将只显示纹理的右半部分。第33页,本讲稿共70页 int LoadGLTextures()/载入位图(调用上面的代码)并转换成纹理 int Status=FALSE;/状态指示器 AUX_RGBImageRec*TextureImage1;/创建纹理的存储空间 memset(TextureImage,0,sizeof(void*)*1);/将指针设为 NULL/载入位图,检查有无错误,如果位图没找到则退出 if(TextureImage0=LoadBMP(Data/NeHe.bmp)Status=TRUE;/将
19、 Status 设为 TRUE glGenTextures(1,&texture0);/创建纹理/使用来自位图数据生成 的典型纹理 glBindTexture(GL_TEXTURE_2D,texture0);/生成纹理 glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage0-sizeX,TextureImage0-sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage0-data);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);/线形滤波 glTe
20、xParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);/线形滤波 第34页,本讲稿共70页if(TextureImage0)/纹理是否存在 if(TextureImage0-data)/纹理图像是否存在 free(TextureImage0-data);/释放纹理图像占用的内存 free(TextureImage0);/释放图像结构 第35页,本讲稿共70页vInitGL(GLvoid)改动为:int InitGL(GLvoid)/此处开始对OpenGL进行所有设置 if(!LoadGLTextures()/调用纹理载入子例程 r
21、eturn FALSE;/如果未能载入,返回FALSE glEnable(GL_TEXTURE_2D);/启用纹理映射 glShadeModel(GL_SMOOTH);/启用阴影平滑 glClearColor(0.0f,0.0f,0.0f,0.5f);/黑色背景 glClearDepth(1.0f);/设置深度缓存 glEnable(GL_DEPTH_TEST);/启用深度测试 glDepthFunc(GL_LEQUAL);/所作深度测试的类型 glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);/真正精细的透视修正 return TRUE;/初始
22、化 OK 第36页,本讲稿共70页vDrawGLScene()改动为:()改动为:添加语句添加语句glBindTexture(GL_TEXTURE_2D,texture0);/选择选择纹理纹理 在绘制正方形的在绘制正方形的 glBegin(GL_QUADS);中粘帖纹理,以前面中粘帖纹理,以前面 为例为例/前面前面 glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f,1.0f);/纹理和四纹理和四边形的左下边形的左下 glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,-1.0f,1.0f);/纹理和纹理和四边形的右下四边形
23、的右下 glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,1.0f);/纹纹理和四边形的右上理和四边形的右上 glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,1.0f,1.0f);/纹理和四边形的左上纹理和四边形的左上 第37页,本讲稿共70页v程序完成后效果v参考程序第38页,本讲稿共70页试验7 光照效果v使用两种不同的光。v第一种称为环境光。环境光来自于四面八方。所有场景中的对象都处于环境光的照射中。v第二种类型的光源叫做漫射光。漫射光由特定的光源产生,并在您的场景中的对象表面上产生反射。处于漫射光直接照射下的任何
24、对象表面都变得很亮,而几乎未被照射到的区域就显得要暗一些。这样在所创建的木板箱的棱边上就会产生的很不错的阴影效果。第39页,本讲稿共70页v创建光源的过程和颜色的创建完全一致。前三个参数分别是RGB三色分量,最后一个是alpha通道参数。vGLfloat LightAmbient=0.5f,0.5f,0.5f,1.0f;/环境光参数,得到的是半亮(0.5f)的白色环境光。如果没有环境光,未被漫射光照到的地方会变得十分黑暗。第40页,本讲稿共70页vGLfloat LightDiffuse=1.0f,1.0f,1.0f,1.0f;/漫射光参数生成最亮的漫射光。所有的参数值都取成最大值1.0f。它
25、将照在木板箱的前面,看起来挺好。第41页,本讲稿共70页v最后保存光源的位置。前三个参数和glTranslate中的一样。依次分别是XYZ轴上的位移。由于想要光线直接照射在木箱的正面,所以XY轴上的位移都是0.0f。第三个值是Z轴上的位移。为了保证光线总在木箱的前面,所以我们将光源的位置朝着观察者挪出屏幕。通常将屏幕也就是显示器的屏幕玻璃所处的位置称作Z轴的0.0f点。所以Z轴上的位移最后定为2.0f。假如您能够看见光源的话,它就浮在您显示器的前方。GLfloat LightPosition=0.0f,0.0f,2.0f,1.0f;/光源位置 第42页,本讲稿共70页v启用光源。没有启用GL_
26、LIGHTING是看不见任何光线。记住:只对光源进行设置、定位、甚至启用,光源都不会工作。glEnable(GL_LIGHT1);/启用一号光源 第43页,本讲稿共70页v程序完成效果v参考程序第44页,本讲稿共70页试验8 移动图像v把场景沿Y轴旋转。如果旋转90度的话,X轴不再是自左至右的了,他将由里向外穿出屏幕。假想您站在房子中间。再设想左侧的墙上写着-x,前面的墙上写着-z,右面墙上就是+x,身后的墙上则是+z。加入整个房子向右转90度,但您没有动,那么前面的墙上将是-x而不再是-z了。所有其他的墙也都跟着移动。-z出现在右侧,+z出现在左侧,+x出现在您背后。glRotatef(st
27、arloop.angle,0.0f,1.0f,0.0f);/旋转至当前所画星星的角度 第45页,本讲稿共70页v沿x轴移动一个正值。通常x轴上的正值代表移向了屏幕的右侧,但这里由于绕y轴旋转了坐标系,x轴的正向可以是任意方向。如果我们转180度的话,屏幕的左右侧就镜像反向了。因此,当我们沿 x轴正向移动时,可能向左,向右,向前或向后。glTranslatef(starloop.dist,0.0f,0.0f);/沿X轴正向移动 第46页,本讲稿共70页v采用逆序来抵消旋转希望星星永远正面朝着我们,而不管屏幕如何旋转或倾斜。在绘制星星之前,采用逆序来抵消旋转。也就是以当前角度的负值来旋转星星。例如
28、将星星旋转了10度的话,又将其旋转-10度来使星星在那个轴上重新面对屏幕。抵消了沿y轴的旋转。抵消掉沿x轴的屏幕倾斜。需要将屏幕再旋转-tilt倾角。glRotatef(-starloop.angle,0.0f,1.0f,0.0f);/取消当前星星的角度 glRotatef(-tilt,1.0f,0.0f,0.0f);/取消屏幕倾斜 第47页,本讲稿共70页v程序运行效果v参考程序第48页,本讲稿共70页试验9 3D世界v每个3D世界基本上可以看作是sector(区段)的集合。一个sector(区段)可以是一个房间、一个立方体、或者任意一个闭合的区间。typedef struct tagSEC
29、TOR/创建Sector区段结构 int numtriangles;/Sector中的三角形个数 TRIANGLE*triangle;/指向三角数组的指针 SECTOR;/命名为SECTOR 第49页,本讲稿共70页v一个sector(区段)包含了一系列的多边形,本实验采用三角形。typedef struct tagTRIANGLE/创建Triangle三角形结构 VERTEX vertex3;/VERTEX矢量数组,大小为3 TRIANGLE;/命名为 TRIANGLE 第50页,本讲稿共70页v三角形本质上是由一些(两个以上)顶点组成的多边形,顶点同时也是我们的最基本的分类单位。顶点包含了
30、OpenGL真正感兴趣的数据。我们用3D空间中的坐标值(x,y,z)以及它们的纹理坐标(u,v)来定义三角形的每个顶点。typedef struct tagVERTEX/创建Vertex顶点结构 float x,y,z;/3D 坐标 float u,v;/纹理坐标 VERTEX;/命名为VERTEX 第51页,本讲稿共70页v允许用户在这个世界中游走和遍历 根据用户的指令旋转并变换镜头位置。围绕原点,以与镜头相反的旋转方向来旋转世界。(让人产生镜头旋转的错觉)以与镜头平移方式相反的方式来平移世界(让人产生镜头移动的错觉)。第52页,本讲稿共70页v程序实现效果v参考程序第53页,本讲稿共70页
31、试验10 飘动的旗帜v#include /引入数学函数库中的Sin v旗帜是由由44格44格的小方格子依次组成。使用points数组来存放网格各顶点独立的x,y,z坐标。float points 45 45 3;/Points网格顶点数组 第54页,本讲稿共70页/沿X平面循环 for(int x=0;x45;x+)/沿Y平面循环 for(int y=0;y45;y+)/向表面添加波浪效果 pointsxy0=float(x/5.0f)-4.5f);pointsxy1=float(y/5.0f)-4.5f);pointsxy2=float(sin(x/5.0f)*40.0f)/360.0f)*
32、3.141592654*2.0f);第55页,本讲稿共70页v绘制组成旗帜的4444个小网格,形成旗帜第一帧glBegin(GL_QUADS);/四边形绘制开始四边形绘制开始 for(x=0;x 44;x+)/沿沿 X 平面平面 0-44 循环循环(45点点)for(y=0;y 44;y+)/沿沿 Y 平面平面 0-44 循环循环(45点点)float_x=float(x)/44.0f;/生成生成X浮点值浮点值 float_y=float(y)/44.0f;/生成生成Y浮点值浮点值 float_xb=float(x+1)/44.0f;/X浮点值浮点值+0.0227f float_yb=floa
33、t(y+1)/44.0f;/Y浮点值浮点值+0.0227fglTexCoord2f(float_x,float_y);/第一个纹理坐标第一个纹理坐标(左下角左下角)glVertex3f(pointsxy0,pointsxy1,pointsxy2);glTexCoord2f(float_x,float_yb);/第二个纹理坐标第二个纹理坐标(左上角左上角)glVertex3f(pointsxy+10,pointsxy+11,pointsxy+12);glTexCoord2f(float_xb,float_yb);/第三个纹理坐标第三个纹理坐标(右上角右上角)glVertex3f(pointsx+
34、1y+10,pointsx+1y+11,pointsx+1y+12);glTexCoord2f(float_xb,float_y);/第四个纹理坐标第四个纹理坐标(右下角右下角)glVertex3f(pointsx+1y0,pointsx+1y1,pointsx+1y2);glEnd();/四边形绘制结束四边形绘制结束 第56页,本讲稿共70页v不断更新绘制小网格。形成旗帜飘动效果/用来降低波浪速度(每隔2帧一次)if(wiggle_count=2)for(y=0;y 45;y+)/沿Y平面循环 hold=points0y2;/存储当前左侧波浪值存储当前左侧波浪值 for(x=0;x 44;x
35、+)/沿沿X平面循环平面循环 /当前波浪值等于其右侧的波浪值当前波浪值等于其右侧的波浪值 pointsxy2=pointsx+1y2;points44y2=hold;/刚才的值成为最左侧的波浪值刚才的值成为最左侧的波浪值 wiggle_count=0;/计数器清零 wiggle_count+;/计数器加一 第57页,本讲稿共70页v程序运行效果v参考程序第58页,本讲稿共70页试验11 二次几何体v/绘制圆柱体 glTranslatef(0.0f,0.0f,-1.5f);v/绘制圆锥 gluCylinder(quadratic,1.0f,0.0f,3.0f,32,32);(顶面半径为0 的特殊
36、圆柱体)参数1(1.0F)是圆柱体的底面半径,参数2(1.0F)是圆柱体的饿顶面半径,参数3(3.0F)是圆柱体的高度。参数4(32)是纬线(环绕Z轴有多少细分),参数5(32)是经线(沿着Z轴有多少细分)。细分越多该对象就越细致。我们可以用增加细分的方法来增加对象的多边形数。第59页,本讲稿共70页v/绘制圆盘gluDisk(quadratic,0.5f,1.5f,32,32);参数1(0.5F)是盘子的内圆半径,该参数可以为0,则表示在盘子中间没孔,内圆半径越大孔越大。参数2(1.5F)表示外圆半径,这个参数必须比内圆半径大。参数3(32)是组成该盘子的切片的数量,这个数量可以想象成披萨饼
37、中的切片的数量。切片越多,外圆边缘就越平滑。最后一个参数(32)是组成盘子的环的数量。环很像唱片上的轨迹,一环套一环。这些环从内圆半径细分到外圆半径。第60页,本讲稿共70页v/绘制球 gluSphere(quadratic,1.3f,32,32);参数1是球的半径。如果你无法理解半径/直径等等的话,可以理解成物体中心到物体外部的距离,在这里我们使用1.3F作为半径。接下来两个参数就是细分了,和圆柱体一样,参数2是纬线,参数3是经线。细分越多球看起来就越平滑 第61页,本讲稿共70页v参考程序第62页,本讲稿共70页试验12 贝塞尔曲面v为了做一个贝塞尔曲面,你需要16个控制点,(4*4),和
38、2个变量t,v。你要做的是计算在分量v的沿4条平行曲线的点,再用这4个点计算在分量t的点。计算了足够的这些点,我们可以用三角带连接他们,画出贝塞尔曲面。第63页,本讲稿共70页typedef struct point_3d /3D点的结构点的结构 double x,y,z;POINT_3D;typedef struct bpatch /贝塞尔面片结构贝塞尔面片结构 POINT_3D anchors44;/由由4x4网格组成网格组成 GLuint dlBPatch;/绘制面片的显示列表名称绘制面片的显示列表名称 GLuint texture;/面片的纹理面片的纹理 BEZIER_PATCH;第6
39、4页,本讲稿共70页/计算贝塞尔方程的值/变量u的范围在0-1之间 POINT_3D Bernstein(float u,POINT_3D*p)POINT_3D a,b,c,d,r;a=pointTimes(pow(u,3),p0);b=pointTimes(3*pow(u,2)*(1-u),p1);c=pointTimes(3*u*pow(1-u),2),p2);d=pointTimes(pow(1-u),3),p3);r=pointAdd(pointAdd(a,b),pointAdd(c,d);return r;第65页,本讲稿共70页/生成贝塞尔曲面的显示列表 GLuint genBez
40、ier(BEZIER_PATCH patch,int divs)int u=0,v;float py,px,pyold;GLuint drawlist=glGenLists(1);/创建显示列表创建显示列表 POINT_3D temp4;POINT_3D*last=(POINT_3D*)malloc(sizeof(POINT_3D)*(divs+1);/更具每一条曲更具每一条曲线的细分数,分配相应的内存线的细分数,分配相应的内存 if(patch.dlBPatch!=NULL)/如果显示列表存在则删除如果显示列表存在则删除 glDeleteLists(patch.dlBPatch,1);tem
41、p0=patch.anchors03;/获得获得u方向的四个控制点方向的四个控制点 temp1=patch.anchors13;temp2=patch.anchors23;temp3=patch.anchors33;第66页,本讲稿共70页for(v=0;v=divs;v+)/根据细分数,创建各个分割点额参数根据细分数,创建各个分割点额参数 px=(float)v)/(float)divs);/使用使用Bernstein函数求的分割点的坐标函数求的分割点的坐标 lastv=Bernstein(px,temp);glNewList(drawlist,GL_COMPILE);/创建一个新的显示列表
42、创建一个新的显示列表 glBindTexture(GL_TEXTURE_2D,patch.texture);/邦定纹理邦定纹理 for(u=1;u=divs;u+)py=(float)u)/(float)divs);/计算计算v方向上的细分点的参数方向上的细分点的参数 pyold=(float)u-1.0f)/(float)divs);/上一个上一个v方向上的细分点的参数方向上的细分点的参数 temp0=Bernstein(py,patch.anchors0);/计算每个细分点计算每个细分点v方向上贝塞尔曲方向上贝塞尔曲面的控制点面的控制点 temp1=Bernstein(py,patch.a
43、nchors1);temp2=Bernstein(py,patch.anchors2);temp3=Bernstein(py,patch.anchors3);glBegin(GL_TRIANGLE_STRIP);/开始绘制三角形带开始绘制三角形带 第67页,本讲稿共70页for(v=0;v=divs;v+)px=(float)v)/(float)divs);/沿着沿着u轴方向顺序绘制轴方向顺序绘制 glTexCoord2f(pyold,px);/设置纹理坐标设置纹理坐标 glVertex3d(lastv.x,lastv.y,lastv.z);/绘制一个顶点绘制一个顶点 lastv=Bernst
44、ein(px,temp);/创建下一个顶点创建下一个顶点 glTexCoord2f(py,px);/设置纹理设置纹理 glVertex3d(lastv.x,lastv.y,lastv.z);/绘制新的顶点绘制新的顶点 glEnd();/结束三角形带的绘制结束三角形带的绘制 glEndList();/显示列表绘制结束显示列表绘制结束 free(last);/释放分配的内存释放分配的内存 return drawlist;/返回创建的显示列表返回创建的显示列表 第68页,本讲稿共70页/设置贝塞尔曲面的控制点设置贝塞尔曲面的控制点 void initBezier(void)mybezier.anch
45、ors00=makePoint(-0.75,-0.75,-0.50);/设置贝塞尔曲面的控制点设置贝塞尔曲面的控制点 mybezier.anchors01=makePoint(-0.25,-0.75,0.00);mybezier.anchors02=makePoint(0.25,-0.75,0.00);mybezier.anchors03=makePoint(0.75,-0.75,-0.50);mybezier.anchors10=makePoint(-0.75,-0.25,-0.75);mybezier.anchors11=makePoint(-0.25,-0.25,0.50);mybezi
46、er.anchors12=makePoint(0.25,-0.25,0.50);mybezier.anchors13=makePoint(0.75,-0.25,-0.75);mybezier.anchors20=makePoint(-0.75,0.25,0.00);mybezier.anchors21=makePoint(-0.25,0.25,-0.50);mybezier.anchors22=makePoint(0.25,0.25,-0.50);mybezier.anchors23=makePoint(0.75,0.25,0.00);mybezier.anchors30=makePoint(-0.75,0.75,-0.50);mybezier.anchors31=makePoint(-0.25,0.75,-1.00);mybezier.anchors32=makePoint(0.25,0.75,-1.00);mybezier.anchors33=makePoint(0.75,0.75,-0.50);mybezier.dlBPatch=NULL;/默认的显示列表为默认的显示列表为0 第69页,本讲稿共70页v程序效果v参考程序第70页,本讲稿共70页