计算机图形学试验汇总课件_第1页
计算机图形学试验汇总课件_第2页
计算机图形学试验汇总课件_第3页
计算机图形学试验汇总课件_第4页
计算机图形学试验汇总课件_第5页
已阅读5页,还剩76页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

计算机图形学试验刘赏OpenGL的基本语法——相关库2OpenGL核心库:glOpenGL实用程序库:gluOpenGL编程辅助库:auxOpenGL实用程序工具包(OpenGLutilitytoolkit,GLUT):glutWindows专用库:wglOpenGL的基本语法——命名规则3OpenGL函数都遵循一个命名约定,即采用以下格式:<库前缀><根命令><可选的参数个数><可选的参数类型>例如函数glColor3f(…),gl表示这个函数来自库gl.h,color表示该函数用于颜色设定,3f表示这个函数采用了三个浮点数参数。OpenGL的基本语法——数据类型4OpenGL数据类型内部表示法定义为C类型C字面值后缀GLbyte8位整数signedcharBGLshort16位整数shortSGLint,GLsizei32位整数longLGLfloat,GLclampf32位浮点数floatFGLdouble,GLclampd64位浮点数doubleDGLubyte,GLboolean8位无符号整数unsignedcharUbGLshort16位无符号整数unsignedshortUsGLuint,GLenum,GLbitfield32位无符号整数unsignedlongUi表2.1OpenGL的数据结构OpenGL程序实例——头文件包含5利用OpenGL实现图形绘制,首先要引入OpenGL核心库以及其他需要使用的库的头文件。GLUT保证了gl.h和glu.h被正确包含。#include<gl/glut.h>#include<windows.h>OpenGL程序实例——窗口管理6初始化(

glutInit

)创建窗口(glutCreateWindow)设定窗口的显示模式(glutInitDisplayMode)指定窗口的位置和大小(glutInitWindowPosition和glutInitWindowSize

)指定窗口的显示内容函数(glutDisplayFunc)运行框架(glutMainLoop)OpenGL程序实例——绘制图形7指定窗口背景色(

glClearColor)颜色管理,使用RGB颜色模型。一种颜色用红、绿、蓝三种颜色成分混合而成,每种颜色成分使用0.0到1.0之间的任意有效浮点数来表示颜色值。OpenGL程序实例——绘制图形8混合色红色成分(R)绿色成分(G)蓝色成分(B)黑0.00.00.0红1.00.00.0绿0.01.00.0黄1.01.00.0蓝0.00.01.0紫1.00.01.0青0.01.01.0深灰0.250.250.25浅灰0.750.750.75棕0.600.400.12南瓜橙0.980.6250.12粉红0.980.040.70紫红0.600.400.70白1.01.01.0表2.2OpenGL的一些常用混合色OpenGL程序实例——绘制图形9刷新窗口的缓冲区(

glClear)设定投影参数

glMatrixMode(GL_PROJECTION);gluOrtho2D(0.0,200.0,0.0,150.0);绘制图形

glRectf(50.0f,100.0f,150.0f,50.0f);试验1:创建一个OpenGL窗口

打开VC然后创建一个新工程,创建一个新的Win32程序(不是console控制台程序)链接OpenGL库文件,Project->Settings,(工程—>设置)然后单击LINK标签:增加OpenGL32.libGLu32.lib和GLaux.lib

后单击OK按钮。

代码的前3行包括了我们使用的每个库文件的头文件。如下所示:

#include<windows.h>//Windows的头文件#include<glew.h>//包含最新的gl.h,glu.h库#include<glut.h>//包含OpenGL实用库完成程序的开发。如下图所示参考程序试验2:绘制简单图形glLoadIdentity(),重置当前的模型观察矩阵,将当前点移到了屏幕中心,X坐标轴从左至右Y坐标轴从下至上,Z坐标轴从里至外。OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。glTranslatef(x,y,z)沿着X,Y和Z轴移动。

glTranslatef(-1.5f,0.0f,-6.0f);//左移1.5单位,并移入屏幕6.0glBegin(GL_TRIANGLES);//绘制三角形glVertex3f(0.0f,1.0f,0.0f);//上顶点glVertex3f(-1.0f,-1.0f,0.0f);//左下顶点glVertex3f(1.0f,-1.0f,0.0f);//右下顶点glEnd();//三角形绘制结束0.0f,1.0f,0.0f-1.0f,-1.0f,0.0f1.0f,-1.0f,0.0fglBegin(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();//正方形绘制结束-1.0f,1.0f,0.0f1.0f,1.0f,0.0f1.0f,-1.0f,0.0f-1.0f,-1.0f,0.0f在在第一实验的基础上,在完成程序的DrawGLScene()过程中增加代码:

glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);//清除屏幕及深度缓存glLoadIdentity();//重置当前的模型观察矩阵

glTranslatef(-1.5f,0.0f,-6.0f);//左移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();

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);//右上

glVertex3f(1.0f,-1.0f,0.0f);//左下glVertex3f(-1.0f,-1.0f,0.0f);//右下

glEnd();//正方形绘制结束画完三角形后,我们要移到右半部分来画正方形。否则两个图形会相互重叠完成程序的开发。如下图所示参考程序试验3着色glColor3f(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)蓝色修改实验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);//右下

glEnd();修改实验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();//正方形绘制结束完成程序的开发。如下图所示参考程序试验4旋转glRotatef(Angle,Xvector,Yvector,Zvector)负责让对象绕某个轴旋转。Xvector,Yvector

和Zvector

三个参数则共同决定旋转轴的方向。比如(1,0,0)所描述的矢量经过X坐标轴的1个单位处并且方向向右。(-1,0,0)所描述的矢量经过X坐标轴的1个单位处,但方向向左。

X轴-您正在使用一台台锯。锯片中心的轴从左至右摆放(就像OpenGL中的X轴)。尖利的锯齿绕着X轴狂转,看起来要么向上转,要么向下转。取决于锯片开始转时的方向。这与我们在OpenGL中绕着X轴旋转什么的情形是一样的。Y轴-假设您正处于一个巨大的龙卷风中心,龙卷风的中心从地面指向天空(就像OpenGL中的Y轴)。垃圾和碎片围着Y轴从左向右或是从右向左狂转不止。这与我们在OpenGL中绕着Y轴旋转什么的情形是一样的。Z轴-您从正前方看着一台风扇。风扇的中心正好朝着您(就像OpenGL中的Z轴)。风扇的叶片绕着Z轴顺时针或逆时针狂转。这与我们在OpenGL中绕着Z轴旋转什么的情形是一样的。在实验3中画三角形的语句前添加

glRotatef(rtri,0.0f,1.0f,0.0f);//绕Y轴旋转三角形在屏幕的左面画了一个彩色渐变三角形,并绕着Y轴从左向右旋转。在实验3中画正方形的前面加上语句:glRotatef(rquad,1.0f,0.0f,0.0f);//绕X轴旋转四边形完成程序,后效果如下:参考程序试验5三维图形给三角形增加一个左侧面,一个右侧面,一个后侧面来生成一个金字塔(四棱锥)。计算好坐标,绘制其它侧面三角形的方法相同。注意所有的面-三角形都是逆时针次序绘制的给正方形增加左、右、上、下及背面生成一个立方体。计算好坐标,绘制其它侧面正方形的方法相同。所有的四边形都以逆时针次序绘制。在3D空间创建对象的方法。必须将OpenGL屏幕想象成一张很大的画纸,后面还带着许多透明的层。差不多就是个由大量的点组成的立方体。这些点从左至右、从上至下、从前到后的布满了这个立方体。如果您能想象的出在屏幕的深度方向,应该在设计新3D对象时没有任何问题。程序完成的,效果如下:参考程序微分的思想:画圆是由很多个小的三角形组成glBegin(GL_TRIANGLE_FAN);glVertex3f(0,0,0.0f);for(i=0;i<=360;i+=30){floatp=(float)(i*3.14/180);glVertex3f((float)sin(p),(float)cos(p),0.0f);}

glEnd();画圆柱试验6纹理映射在第一实验代码开始处增加新代码:#include<stdio.h>在ReSizeGLScene()之前,增加了下面这一段代码。用来加载位图文件AUX_RGBImageRec*LoadBMP(char*Filename)//载入位图图象{FILE*File=NULL;//文件句柄

if(!Filename)//确保文件名已提供{returnNULL;//如果没提供,返回NULL}File=fopen(Filename,“r”);//尝试打开文件

if(File)//文件存在么?{

fclose(File);//关闭句柄

returnauxDIBImageLoad(Filename);//载入位图并返回指针

}returnNULL;//如果载入失败,返回NULL涉及到的函数glGenTextures(1,&texture[0])告诉OpenGL想生成一个纹理名字(如果想载入多个纹理,加大数字)。glBindTexture(GL_TEXTURE_2D,texture[0])告诉OpenGL将纹理名字texture[0]绑定到纹理目标上。2D纹理只有高度(在Y轴上)和宽度(在X轴上)。主函数将纹理名字指派给纹理数据。glBindTexture(GL_TEXTURE_2D,texture[所使用纹理对应的数字])选择要绑定的纹理。当您想改变纹理时,应该绑定新的纹理。有一点值得指出的是,您不能在glBegin()和glEnd()之间绑定纹理,必须在glBegin()之前或glEnd()之后绑定。glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[0]->sizeX,TextureImage[0]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data);告诉OpenGL此纹理是一个2D纹理(GL_TEXTURE_2D)。参数“0”代表图像的详细程度,通常就由它为零去了。参数三是数据的成分数。因为图像是由红色数据,绿色数据,蓝色数据三种组分组成。TextureImage[0]->sizeX

是纹理的宽度。如果您知道宽度,您可以在这里填入,但计算机可以很容易的为您指出此值。TextureImage[0]->sizey

是纹理的高度。参数零是边框的值,一般就是“0”。

GL_RGB告诉OpenGL图像数据由红、绿、蓝三色数据组成。

GL_UNSIGNED_BYTE意味着组成图像的数据是无符号字节类型的。最后...TextureImage[0]->data告诉OpenGL纹理数据的来源。此例中指向存放在TextureImage[0]记录中的数据。glTexParameteri()告诉OpenGL在显示图像时,当它比放大得原始的纹理大(GL_TEXTURE_MAG_FILTER)或缩小得比原始得纹理小(GL_TEXTURE_MIN_FILTER)时OpenGL采用的滤波方式。通常这两种情况下都采用GL_LINEAR。

为了将纹理正确的映射到四边形上,您必须将纹理的右上角映射到四边形的右上角,纹理的左上角映射到四边形的左上角,纹理的右下角映射到四边形的右下角,纹理的左下角映射到四边形的左下角。如果映射错误的话,图像显示时可能上下颠倒,侧向一边或者什么都不是。glTexCoord2f的第一个参数是X坐标。0.0f是纹理的左侧。0.5f是纹理的中点,1.0f是纹理的右侧。glTexCoord2f的第二个参数是Y坐标。0.0f是纹理的底部。0.5f是纹理的中点,1.0f是纹理的顶部。所以纹理的左上坐标是X:0.0f,Y:1.0f,四边形的左上顶点是X:-1.0f,Y:1.0f。其余三点依此类推。测试glTexCoord2f的X,Y坐标参数。把1.0f改为0.5f将只显示纹理的左半部分,把0.0f改为0.5f将只显示纹理的右半部分。

int

LoadGLTextures()//载入位图(调用上面的代码)并转换成纹理{

intStatus=FALSE;//状态指示器

AUX_RGBImageRec*TextureImage[1];//创建纹理的存储空间

memset(TextureImage,0,sizeof(void*)*1);//将指针设为NULL//载入位图,检查有无错误,如果位图没找到则退出if(TextureImage[0]=LoadBMP("Data/NeHe.bmp")){Status=TRUE;//将Status设为TRUE glGenTextures(1,&texture[0]);//创建纹理//使用来自位图数据生成的典型纹理

glBindTexture(GL_TEXTURE_2D,texture[0]);//生成纹理

glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[0]->sizeX,TextureImage[0]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//线形滤波glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//线形滤波

if(TextureImage[0])//纹理是否存在{ if(TextureImage[0]->data)//纹理图像是否存在{ free(TextureImage[0]->data);//释放纹理图像占用的内存

} free(TextureImage[0]);//释放图像结构

}InitGL(GLvoid)改动为:int

InitGL(GLvoid)//此处开始对OpenGL进行所有设置{if(!LoadGLTextures())//调用纹理载入子例程{returnFALSE;//如果未能载入,返回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);//真正精细的透视修正returnTRUE;//初始化OK}DrawGLScene

()改动为:添加语句glBindTexture(GL_TEXTURE_2D,texture[0]);//选择纹理在绘制正方形的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);//纹理和四边形的右下glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,1.0f);//纹理和四边形的右上glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,1.0f,1.0f);//纹理和四边形的左上程序完成后效果参考程序试验7光照效果使用两种不同的光。第一种称为环境光。环境光来自于四面八方。所有场景中的对象都处于环境光的照射中。第二种类型的光源叫做漫射光。漫射光由特定的光源产生,并在您的场景中的对象表面上产生反射。处于漫射光直接照射下的任何对象表面都变得很亮,而几乎未被照射到的区域就显得要暗一些。这样在所创建的木板箱的棱边上就会产生的很不错的阴影效果。创建光源的过程和颜色的创建完全一致。前三个参数分别是RGB三色分量,最后一个是alpha通道参数。GLfloat

LightAmbient[]={0.5f,0.5f,0.5f,1.0f};//环境光参数,得到的是半亮(0.5f)的白色环境光。如果没有环境光,未被漫射光照到的地方会变得十分黑暗。GLfloat

LightDiffuse[]={1.0f,1.0f,1.0f,1.0f};//漫射光参数生成最亮的漫射光。所有的参数值都取成最大值1.0f。它将照在木板箱的前面,看起来挺好。最后保存光源的位置。前三个参数和glTranslate中的一样。依次分别是XYZ轴上的位移。由于想要光线直接照射在木箱的正面,所以XY轴上的位移都是0.0f。第三个值是Z轴上的位移。为了保证光线总在木箱的前面,所以我们将光源的位置朝着观察者挪出屏幕。通常将屏幕也就是显示器的屏幕玻璃所处的位置称作Z轴的0.0f点。所以Z轴上的位移最后定为2.0f。假如您能够看见光源的话,它就浮在您显示器的前方。GLfloat

LightPosition[]={0.0f,0.0f,2.0f,1.0f};//光源位置启用光源。没有启用GL_LIGHTING是看不见任何光线。记住:只对光源进行设置、定位、甚至启用,光源都不会工作。glEnable(GL_LIGHT1);//启用一号光源程序完成效果参考程序试验8移动图像把场景沿Y轴旋转。如果旋转90度的话,X轴不再是自左至右的了,他将由里向外穿出屏幕。假想您站在房子中间。再设想左侧的墙上写着-x,前面的墙上写着-z,右面墙上就是+x,身后的墙上则是+z。加入整个房子向右转90度,但您没有动,那么前面的墙上将是-x而不再是-z了。所有其他的墙也都跟着移动。-z出现在右侧,+z出现在左侧,+x出现在您背后。glRotatef(star[loop].angle,0.0f,1.0f,0.0f);//旋转至当前所画星星的角度沿x轴移动一个正值。通常x轴上的正值代表移向了屏幕的右侧,但这里由于绕y轴旋转了坐标系,x轴的正向可以是任意方向。如果我们转180度的话,屏幕的左右侧就镜像反向了。因此,当我们沿x轴正向移动时,可能向左,向右,向前或向后。

glTranslatef(star[loop].dist,0.0f,0.0f);//沿X轴正向移动采用逆序来抵消旋转希望星星永远正面朝着我们,而不管屏幕如何旋转或倾斜。在绘制星星之前,采用逆序来抵消旋转。也就是以当前角度的负值来旋转星星。例如将星星旋转了10度的话,又将其旋转-10度来使星星在那个轴上重新面对屏幕。抵消了沿y轴的旋转。抵消掉沿x轴的屏幕倾斜。需要将屏幕再旋转-tilt倾角。glRotatef(-star[loop].angle,0.0f,1.0f,0.0f);//取消当前星星的角度glRotatef(-tilt,1.0f,0.0f,0.0f);//取消屏幕倾斜程序运行效果参考程序试验93D世界每个3D世界基本上可以看作是sector(区段)的集合。一个sector(区段)可以是一个房间、一个立方体、或者任意一个闭合的区间。typedef

struct

tagSECTOR//创建Sector区段结构{

int

numtriangles;//Sector中的三角形个数

TRIANGLE*triangle;//指向三角数组的指针

}SECTOR;//命名为SECTOR一个sector(区段)包含了一系列的多边形,本实验采用三角形。typedef

struct

tagTRIANGLE//创建Triangle三角形结构

{VERTEXvertex[3];//VERTEX矢量数组,大小为3}TRIANGLE;//命名为TRIANGLE三角形本质上是由一些(两个以上)顶点组成的多边形,顶点同时也是我们的最基本的分类单位。顶点包含了OpenGL真正感兴趣的数据。我们用3D空间中的坐标值(x,y,z)以及它们的纹理坐标(u,v)来定义三角形的每个顶点。typedef

struct

tagVERTEX//创建Vertex顶点结构{floatx,y,z;//3D坐标floatu,v;//纹理坐标}VERTEX;//命名为VERTEX允许用户在这个世界中游走和遍历根据用户的指令旋转并变换镜头位置。围绕原点,以与镜头相反的旋转方向来旋转世界。(让人产生镜头旋转的错觉)以与镜头平移方式相反的方式来平移世界(让人产生镜头移动的错觉)。程序实现效果参考程序试验10飘动的旗帜#include<math.h>//引入数学函数库中的Sin

旗帜是由由44格×44格的小方格子依次组成。使用points数组来存放网格各顶点独立的x,y,z坐标。floatpoints[45][45][3];//Points网格顶点数组//沿X平面循环

for(intx=0;x<45;x++){//沿Y平面循环

for(inty=0;y<45;y++){//向表面添加波浪效果points[x][y][0]=float((x/5.0f)-4.5f);points[x][y][1]=float((y/5.0f)-4.5f);points[x][y][2]=float(sin((((x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f));}}绘制组成旗帜的44×44个小网格,形成旗帜第一帧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.0227ffloat_yb=float(y+1)/44.0f;//Y浮点值+0.0227fglTexCoord2f(float_x,float_y);//第一个纹理坐标(左下角)glVertex3f(points[x][y][0],points[x][y][1],points[x][y][2]);glTexCoord2f(float_x,float_yb);//第二个纹理坐标(左上角)glVertex3f(points[x][y+1][0],points[x][y+1][1],points[x][y+1][2]);glTexCoord2f(float_xb,float_yb);//第三个纹理坐标(右上角)glVertex3f(points[x+1][y+1][0],points[x+1][y+1][1],points[x+1][y+1][2]);glTexCoord2f(float_xb,float_y);//第四个纹理坐标(右下角)glVertex3f(points[x+1][y][0],points[x+1][y][1],points[x+1][y][2]);}}glEnd();//四边形绘制结束不断更新绘制小网格。形成旗帜飘动效果//用来降低波浪速度(每隔2帧一次)if(wiggle_count==2){for(y=0;y<45;y++)//沿Y平面循环{

hold=points[0][y][2];//存储当前左侧波浪值

for(x=0;x<44;x++)//沿X平面循环{//当前波浪值等于其右侧的波浪值points[x][y][2]=points[x+1][y][2]; }points[44][y][2]=hold;//刚才的值成为最左侧的波浪值

}wiggle_count=0;//计数器清零

}wiggle_count++;//计数器加一

程序运行效果参考程序试验11二次几何体//绘制圆柱体glTranslatef(0.0f,0.0f,-1.5f);//绘制圆锥gluCylinder(quadratic,1.0f,0.0f,3.0f,32,32);

(顶面半径为0的特殊圆柱体)参数1(1.0F)是圆柱体的底面半径,参数2(1.0F)是圆柱体的饿顶面半径,参数3(3.0F)是圆柱体的高度。参数4(32)是纬线(环绕Z轴有多少细分),参数5(32)是经线(沿着Z轴有多少细分)。细分越多该对象就越细致。我们可以用增加细分的方法来增加对象的多边形数。//绘制圆盘gluDisk(quadratic,0.5f,1.5f,32,32);

参数1(0.5F)是盘子的内圆半径,该参数可以为0,则表示在盘子中间没孔,内圆半径越大孔越大。参数2(1.5F)表示外圆半径,这个参数必须比内圆半径大。参数3(32)是组成该盘子的切片的数量,这个数量可以想象成披萨饼中的切片的数量。切片越多,外圆边缘就越平滑。最后一个参数(32)是组成盘子的环的数量。环很像唱片上的轨迹,一环套一环。这些环从内圆半径细分到外圆半径。//绘制球gluSphere(quadratic,1.3f,32,32);

参数1是球的半径。如果你无法理解半径/直径等等的话,可以理解成物体中心到物体外部的距离,在这里我们使用1.3F作为半径。接下来两个参数就是细分了,和圆柱体一样,参数2是纬线,参数3是经线。细分越多球看起来就越平滑参考程序试验12贝塞尔曲面为了做一个贝塞尔曲面,你需要16个控制点,(4*4),和2个变量t,v。你要做的是计算在分量v的沿4条平行曲线的点,再用这4个点计算在分量t的点。计算了足够的这些点,我们可以用三角带连接他们,画出贝塞尔曲面。

typedef

structpoint_3d{//3D点的结构

doublex,y,z;}POINT_3D;typedef

struct

bpatch{//贝塞尔面片结构POINT_3Danchors[4][4];//由4x4网格组成GLuint

dlBPatch;//绘制面片的显示列表名称GLuinttexture;//面片的纹理}BEZIER_PATCH;//计算贝塞尔方程的值//变量u的范围在0-1之间

POINT_3DBernstein(floatu,POINT_3D*p){POINT_3Da,b,c,d,r;a=pointTimes(pow(u,3),p[0]);b=pointTimes(3*pow(u,2)*(1-u),p[1]);c=pointTimes(3*u*pow((1-u),2),p[2]);d=pointTimes(pow((1-u),3),p[3]);r=pointAdd(pointAdd(a,b),pointAdd(c,d));returnr;}//生成贝塞尔曲面的显示列表

GLuint

genBezier(BEZIER_PATCHpatch,int

divs){intu=0,v;floatpy,px,pyold;

GLuint

drawlist=glGenLists(1);//创建显示列表POINT_3Dtemp[4];POINT_3D*last=(POINT_3D*)malloc(sizeof(POINT_3D)*(divs+1));//更具每一条曲线的细分数,分配相应的内存

if(patch.dlBPatch!=NULL)//如果显示列表存在则删除

glDeleteLists(patch.dlBPatch,1);temp[0]=patch.anchors[0][3];//获得u方向的四个控制点

temp[1]=patch.anchors[1][3];temp[2]=patch.anchors[2][3];temp[3]=patch.anchors[3][3];for(v=0;v<=divs;v++){//根据细分数,创建各个分割点额参数

px=((float)v)/((float)divs);//使用Bernstein函数求的分割点的坐标last[v]=Bernstein(px,temp);}

glNewList(drawlist,GL_COMPILE);//创建一个新的显示列表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方向

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论