Bezier曲面.doc
《Bezier曲面.doc》由会员分享,可在线阅读,更多相关《Bezier曲面.doc(8页珍藏版)》请在冰点文库上搜索。
8
一、设计实验目的
通过实验可以更了解Bezier曲线曲面的概念,理解Bezier曲面生成的原理,加深对Bezier生成算法的理解,加强理论的学习,锻炼对知识的运用能力和实践能力;进一步对OpenGL强大功能的认识,并对一些函数如display()、makeImage()、init()、reshape(intw,inth)等的功能的运用又进一步的了解,为以后的学习打下基础。
二、设计实验要求
呈现Bezier曲面,并使其能够旋转和平移
三、实验原理
本程序用VisualC++Win32ConsoleApplicstion(32控制台应用程序)创建一个应用程序,再添加一个c++程序源—Bezier曲面。
绘制Bezier曲面主要运用多个多边形逼近而成,,并通过少数几个控制点对其进行描述。
通过定义曲面和均匀网格绘制一个具有光照和明暗处理效果的Bezier曲面,并实现曲面的放大和缩小,绕x轴,y轴,z轴旋转
四、算法分析:
下面给出程序中主函数中各函数功能说明:
glutInit(&argc,argv)初始化GLUT,用来接收来自main函数的参数,程序可以具体实现相关方式来使用这些参数。
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH)颜色缓存的缓存模式,用于显示图形的颜色;
glutInitWindowSize(1000,600)函数功能是创建一个窗口大小为(1000,600);
glutInitWindowPosition(30,40)函数是所创建的窗口的(0,0)坐标在电脑窗口(30,40)出显示出来;
glutCreateWindow(argv[0])函数的功能实在屏幕上创建一个窗口;
glutDisplayFunc(display)函数display在每次对窗口重绘时使用;
glutReshapeFunc(reshape)函数主要是改变窗口大小的操作进行重绘;
glutMainLoop()是程序进入无限事件处理循环计算函数,该函数的调用应为main函数最后一条语句出现。
下面是各函数中的组成函数功能说明:
定义控制点坐标数组:
GLfloatctrlpoints[4][4][3]
绘制曲面(包含的代码描述了所要绘制的Bezier曲面)函数:
display()
生成图形的纹理函数:
makeImage()
负责状态变量初始化的函数:
init()
改变窗口大小的操作进行重绘的函数:
reshape()
程序进入无限事件处理循环计算函数:
glutMainLoop()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)主要定义窗口底面颜色voidglEvalMesh2(GLenummode,GLintp1,GLintp2,GLintq1,GLintq2)的mode参数除了可以是GL_POINT和GL_LINE外,也可以是GL_FILL(生成填充空间曲面)。
voidglMap2{fd}(GLenumtarget,TYPEu1,TYPEu2,GLintustride,GLintuorder,TYPEv1,TYPEv2,Glintvstride,GLintvorder,TYPEpoints);
这里target的意义与在glMap1*()中的意义相同;(u1,u2),(v1,v2)是二维曲面坐标;其他参数如uorder,vorder,ustride和vstride等的定义都类似于在曲线中的定义;points为控制点坐标。
对曲面任意一点的计算可通过函数
voidglEvalCoord2{fd}[v](TYPEu,TYPEv);
来完成,通过在定义域内的曲线坐标值u,v来计算曲面内任意一点的世界坐标位置。
对于曲面,也可以象曲线一样通过函数来定义均匀间隔的曲面坐标值:
voidglMapGrid2{fd}(GLenumnu,TYPEu1,TYPEu2,GLenumnv,TYPEv1,TYPEv2);
该函数定义曲面参数空间均匀网格,从u1到u2分为等间隔nu步,从v1到v2分为等间隔nv步,然后由glEvalMesh2()将此网格应用到已经启动的曲面计算上。
一般来说,纹理图像为正方形或长方形。
但当它映射到一个多边形或曲面上并变换到屏幕坐标时,纹理的单个纹素很少对应于屏幕图像上的象素。
根据所用变换和所用纹理映射,屏幕上单个象素可以对应于一个纹素的一小部分(即放大)或一大批纹素(即缩小)。
下面用函数glTexParameteri()说明放大和缩小的方法:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
实际上,第一个参数可以是GL_TEXTURE_1D或GL_TEXTURE_2D,即表明所用的纹理是一维的还是二维的;第二个参数指定滤波方法,其中参数值GL_TEXTURE_MAG_FILTER指定为放大滤波方法,GL_TEXTURE_MIN_FILTER指定为缩小滤波方法。
若选择GL_NEAREST则采用坐标最靠近象素中心的纹素,这有可能使图像走样;若选GL_LINEAR则采用最靠近象素中心的四个象素的加权平均值。
GL_NEAREST所需计算比GL_LINEAR要少,因而执行得更快,但GL_LINEAR提供了比较光滑的效果。
GLfloatambient[4]={0.8,0.6,0.4,1.0}定义初始化光照、材质的过程
GLfloatposition[4]={0.0,1.0,3.0,1.0}为定义一个黄色光源
GLfloatmat_diffuse[4]={0.8,0.2,0.1,1.0}是定义特定颜色的镜面反射
GLfloatmat_specular[4]={0.8,0.6,0.3,1.0}是定义镜面反射的光亮度
GLfloatmat_shininess[1]={60.0}为光源发光的角度
五、源程序:
#include
#include
#include
GLfloatctrlpoints[4][4][3]={//控制点坐标
{{-1.5,-1.5,4.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,-0.5,3.0},{0.5,-0.5,0.0},{1.5,-0.5,-1.0}},
{{-1.5,0.5,4.0},{-0.5,0.5,0.0},{0.5,0.5,3.0},{1.5,0.5,4.0}},
{{-1.5,1.5,-2.0},{-0.5,1.5,-2.0},{0.5,1.5,0.0},{1.5,1.5,-1.0}}
};
GLfloattheta[3]={0.0,0.0,0.0};
GLfloatd=0;
GLfloattexpts[2][2][2]={{{0.0,0.0},{0.0,1.0}},{{1.0,0.0},{1.0,1.0}}};
voiddisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glColor3f(1.0,1.0,1.0);
glEvalMesh2(GL_FILL,0,20,0,20);
glFlush();
glutSwapBuffers();
}
#define imageWidth64
#define imageHeight64
GLbyteimage[3*imageWidth*imageHeight];
voidmakeImage(void)
{
inti,j;
floatti,tj;
for(i=0;iti=2.0*3.14159265*i/imageWidth;
for(j=0;jtj=2.0*3.14159265*j/imageHeight;
image[3*(imageHeight*i+j)]=(GLubyte)127*(1.0+sin(ti));
image[3*(imageHeight*i+j)+1]=(GLubyte)127*(1.0+cos(2*tj));
image[3*(imageHeight*i+j)+2]=(GLubyte)127*(1.0+cos(ti+tj));
}
}
}
voidinit(void)
{
glClearColor(0.0,0.0,0.0,1.0);//清屏
glEnable(GL_DEPTH_TEST);//激活深度比较
glMap2f(GL_MAP2_VERTEX_3,0,1,3,4,0,1,12,4,&ctrlpoints[0][0][0]);//定义曲面
glMap2f(GL_MAP2_TEXTURE_COORD_2,0,1,2,2,0,1,4,2,&texpts[0][0][0]);
glEnable(GL_MAP2_TEXTURE_COORD_2);//启动曲面
glEnable(GL_MAP2_VERTEX_3);
glEnable(GL_MAP2_VERTEX_3);//启用曲面
glEnable(GL_AUTO_NORMAL);//启用曲面法向向量计算
glEnable(GL_NORMALIZE);//启用法向归一化
glMapGrid2f(20,0.0,1.0,20,0.0,1.0);//定义参数空间的均匀网格
GLfloatambient[4]={0.8,0.6,0.4,1.0};//初始化光照、材质的过程
GLfloatposition[4]={0.0,1.0,3.0,1.0};//定义一个黄色光源
GLfloatmat_diffuse[4]={0.8,0.2,0.1,1.0};//定义特定颜色的镜面反射
GLfloatmat_specular[4]={0.8,0.6,0.3,1.0};//定义镜面反射的光亮度
GLfloatmat_shininess[1]={60.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);
//makeImage();
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,imageWidth,imageHeight,0,
GL_RGB,GL_UNSIGNED_BYTE,image);//定义一个二维纹理映射
glEnable(GL_DEPTH_TEST);
}
staticvoidmouse(intbutton,intstate,intx,inty)
{
if(state==GLUT_DOWN&&button==GLUT_LEFT_BUTTON)
{
d=1.2;
glScalef(d,d,d);
glutPostRedisplay();
}
if(state==GLUT_DOWN&&button==GLUT_RIGHT_BUTTON)
{
d=0.8;
glScalef(d,d,d);
glutPostRedisplay();
}
}
voidkeyboard(unsignedcharkey,intx,inty)
{
switch(key){
case't':
case'T':
glutPostRedisplay();
break;
case27:
exit(0);
break;
case'x':
case'X':
theta[0]+=5;
if(theta[1]>360)theta[0]-=360;
glRotatef(theta[0],1.0,0.0,0.0);
glutPostRedisplay();
break;
case'y':
case'Y':
theta[1]+=5;
if(theta[1]>360)theta[1]-=360;
glRotatef(theta[1],0.0,10.0,0.0);
glutPostRedisplay();
break;
case'z':
case'Z':
theta[2]+=5;
if(theta[2]>360)theta[2]-=360;
glRotatef(theta[2],0.0,0.0,1.0);
glutPostRedisplay();
break;
default:
break;
}
}
voidreshape(intw,inth)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<=h)
glOrtho(-4.0,4.0,-4.0*(GLfloat)h/(GLfloat)w,
4.0*(GLfloat)h/(GLfloat)w,-4.0,4.0);
else
glOrtho(-4.0*(GLfloat)w/(GLfloat)h,
4.0*(GLfloat)w/(GLfloat)h,-4.0,4.0,-4.0,4.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(85.0,1.0,1.0,1.0);
}
intmain(intargc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(800,600);
glutInitWindowPosition(50,40);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutIdleFunc(NULL);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutReshapeFunc(reshape);
glutMainLoop();
return0;
}
六、实验输出结果显示