三维图形学论文

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

2006级数字媒体技术《三维图形学》
数字媒体技术
《三维图形学》
期末考查
考查要求
根据教材第三章、第五章、第六章、第七章、第八章的大作业要求,综合运用几何建模、投影变换、模型变换、颜色绘制、光照绘制、纹理绘制以及事件交互等图形学知识,使用OpenGL实现房子漫游场景。

二○○九年六月
第1章系统功能
通过截图展示系统的各个功能,并配有必要的文字说明。

突出具有创新性和技术难度的功能。

该小房子系统主要有以下功能:
1.实现门和窗的贴图(如下图)功能,增加了门和窗的真实性。

这里主要分为四个步骤进行:(1)定义数据,建立内部纹理图(texImage),在init()函数中使用glEnable()允许使用2D纹理映射,(2)将文件读入纹理数组中,(3)建立OpenGL函数,定义如何使用纹理图,(4)绘制带纹理图的平面。

2.实现通过控制键盘键进行小房子四周旋转漫游的功能,这里我主要定义了六个键:q,w,a,s,z,x。

q/w分别控制绕X轴进行旋转,a/s分别控制绕Y轴进行旋转,z/x分别控制绕Z轴进行旋转。

旋转角度ANGLE设置为2.
图示:
绕x轴旋转——〉再绕y轴旋转——〉继续绕z轴旋转3.实现通过控制键盘键进行走动漫游的功能,从而可以进行房子。

这里其实和上面的旋转漫游原理一样,设置了六个键:e,r,d,f,c,v。

e/r分别控制在X轴方向上的移动,
d/f分别控制在Y轴方向上的移动,c/v分别控制在Z轴方向上的移动。

移动单位Len设置为0.3。

图示:
沿x轴移动沿y轴移动沿z轴移动下图为结合旋转漫游和走动漫游进入屋内的一个位置。

通过旋转漫游和走动漫游进入小房子内部
4.实现通过键盘控制门的旋转功能,设置了f,g两个键盘键,分别控制门的向里开还是向外开,且向里和向外各开到120角度。

效果如下:
向里开向外开
5.实现通过菜单回调函数来改变房子房顶颜色和复原颜色的功能。

采用了两个函数来创建选项菜单和增加菜单项:glutCreateMenu()和glutAddMenuEntry().菜单和选择后效果如下:
左键菜单
选择Green时选择复原时
6.实现直接通过鼠标进行小房子在XZ空间绕Y轴的360度旋转。

这里主要用到鼠标回调函数,定义鼠标键回调函数mouse()和鼠标移动回调函数motion()。

绕Y轴随意旋转
7.实现通过菜单控制灯光的开启和关闭功能。

这跟5中的功能实现过程差不多,在myinit函数中定义了红色,绿色,蓝色三个光源,在回调函数menu中增加了两个if语句供选择,菜单和选择后的效果如下:
右键菜单
开启红色光源开启蓝色光源开启绿色光源
8.实现通过菜单回调函数进行屋内自动漫游和停止漫游。

这里用到了空闲事件回调函数idle ,声明animate()函数来获取坐标,在display()中实现移动和旋转。

9.实现了通过绘制点来建模桌子。

10.实现视点的切换和窗户的切换。

滚轮菜单
切换视点前 切换视点后
切换窗户前 切换窗户后
11.实现解释系统如何操作的文本。

第2章系统实现
结合图形学知识和OpenGL函数解释说明系统主要功能实现的思路和细
节,并附核心代码说明。

1.实现门和窗的贴图(如下图)功能,增加了门和窗的真实性。

这里主要用到了几个函数:setTexture(),glEnable(),glGenTextures(),glBindTexture(),glTexEnvi(), glTexParameteri(),glTexImage2D().主要分为四个步骤进行:(1)定义数据,建立内部纹理图(texImage),在init()函数中使用glEnable()允许使用2D纹理映射,(2)将文件读入纹理数组中,(3)建立OpenGL函数,定义如何使用纹理图,(4)绘制带纹理图的平面。

核心代码如下:
//通过setTexture函数为门、窗、墙等定义贴图
void setTexture(void)
{
FILE *fd;
GLubyte ch;
int i,j,k;
fd = fopen("3.pbm", "rb");
for(i=0; i<TEX_WIDTH; i++) // for each row
{
for (j=0; j<TEX_HEIGHT; j++) // for each column
{
for (k=0; k<3; k++) // read RGB components of the pixel {
fread(&ch, 1, 1, fd);
texImage1[i][j][k] = (GLubyte) ch;
}
}
}
fclose(fd);
}
//在drawHouse函数中实现贴图,并且在drawHouse中画出整个房子
void drawHouse(void){
glGenTextures(1, texName1); //生成一系列纹理名
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D,texName1[0]); //绑定纹理名和纹理目标 //定义目标纹理以及要定义的纹理属性并制定属性值
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
//说明纹理图像
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB8,TEX_WIDTH,TEX_HEIGHT,
0,GL_RGB,GL_UNSIGNED_BYTE,texImage1);
glBegin(GL_QUADS);//men
glNormal3fv(normals[3]);
glTexCoord2f(1.0, 1); glVertex3f(1.5,-1.0,-0.4);
glTexCoord2f(1, 0.0);glVertex3f(1.5,0.4,-0.4);
glTexCoord2f(0,0.0);glVertex3f(1.5,0.4,0.4);
glTexCoord2f(0.0,1);glVertex3f(1.5,-1.0,0.4);
glEnd();
glDeleteTextures(1, texName1);
2.实现通过控制键盘键进行小房子四周旋转漫游的功能,该功能主要在keyboard()函数中定义键盘键,并且在display()函数中进行旋转的实现。

这里我主要定义了六个键:q,w,a,s,z,x。

q/w分别控制绕X轴进行旋转,a/s分别控制绕Y轴进行旋转,z/x分别控制绕Z轴进行旋转。

旋转角度ANGLE设置为2.
//声明键盘控制进行旋转控制
void display( void )
{
#ifdef ALL
gluLookAt(13, 0.0, 0.0, 0, 0., 0., 0.0, 1.0, .0);
#endif
//定义各方向轴上的旋转角度
glRotatef(xAngle, 1.0, 0.0, 0.0);
glRotatef(yAngle, 0.0, 1.0, 0.0);
glRotatef(zAngle, 0.0, 0.0, 1.0);
if (ch != ' ') { // 键盘声明角度旋转
switch(ch) {
case 'q':
case 'o':
xAngle += ANGLE;
glRotatef( ANGLE, 1.0, 0.0, 0.0); break;
case 'w':
case 'p':
xAngle -= ANGLE;
glRotatef(-ANGLE, 1.0, 0.0, 0.0); break;
…………
}
}
ch = ' ';
}
//实现键盘控制进行旋转控制
void keyboard(unsigned char key, int x, int y)
{
ch = ' ';
switch (key)
{
case 'q' : // 绕X轴旋转,q为正向, w为反向
ch = key; break;
case 'w' :
ch = key; break;
……
……
}
glutPostRedisplay();
}
3.实现通过控制键盘键进行走动漫游的功能,从而可以进行房子。

这里其实和上面的旋转漫游原理一样,设置了六个键:e,r,d,f,c,v。

e/r分别控制在X轴方向上的移动,d/f分
别控制在Y轴方向上的移动,c/v分别控制在Z轴方向上的移动。

移动单位Len设置为0.3。

//在keyboard()函数中声明
ch1 = ' ';
switch (key)
{
case'e' : // rotate around X; q = positive, w = negative
xLen += Len;ch1 = key; break;
case'r' :
xLen -= Len;ch1 = key; break;
case'd' : // rotate around Y; q = positive, s = negative
yLen += Len;ch1 = key; break;
case'f' :
yLen -= Len;ch1 = key; break;
case'c' : // rotate around Z; z = positive, x = negative
zLen += Len;ch1 = key; break;
case'v' :
zLen -= Len;ch1 = key; break;
}
//在display()函数中实现
if (ch1 != ' ') {
switch(ch1) {
case'e':
glTranslatef( Len, 0.0, 0.0); break;
case'r':
glTranslatef( -Len, 0.0, 0.0); break;
case'd':
glTranslatef( 0.0, Len, 0.0); break;
case'f':
glTranslatef( 0.0, -Len, 0.0); break;
case'c':
glTranslatef( 0.0, 0.0, Len); break;
case'v':
glTranslatef( 0.0, 0.0, -Len); break;
}
}
ch1= ' ';
4.实现通过键盘控制门的旋转功能,设置了g,h两个键盘键,分别控制门的向里开还是向外开,且向里和向外各开到120角度。

//在keyboard()函数中定义键盘键
case'g' :
doorAngle -= ANGLE;
if(doorAngle<-120)
doorAngle=-120; break;
case'h' :
doorAngle += ANGLE;
if(doorAngle>120)
doorAngle=120; break;
//在drawHouse()函数中实现rotate
glRotatef(doorAngle, 0.0, 1.0, 0.0);
drawDoor();
5.实现通过菜单回调函数来改变房子房顶颜色和复原颜色的功能。

采用了两个函数来创建选项菜单和增加菜单项:glutCreateMenu()和glutAddMenuEntry().glutCreateMenu()中需要一个回调函数作为参数,这里我设置了一个名为menu的回调函数,它用来记录当菜单打开并有选项被选中后所选中的菜单项对应的编号。

//根据菜单选择设置颜色
GLfloat color[4];
if(inputname==White){
color[0]=1;color[1]=1;color[2]=1;color[3]=1;}
if(inputname==Red){
color[0]=1;color[1]=0;color[2]=0;color[3]=1;}
if(inputname==Green){
color[0]=0;color[1]=1;color[2]=0;color[3]=1;}
if(inputname==Blue){
color[0]=0;color[1]=0;color[2]=1;color[3]=1;}
if(inputname==Yellow){
color[0]=1;color[1]=1;color[2]=0;color[3]=1;}
glBegin(GL_QUADS);
glColor4f(color[0],color[1],color[2],color[3]);
glVertex3f(-1.5,2,-1.6);
glVertex3f(-1.5,2,2.4);
glVertex3f(0,1,2.4);
glVertex3f(0,1,-1.6);
glEnd();
//在main()函数中创建菜单
glutCreateMenu(menu);//创建选项菜单
glutAddMenuEntry("更改房顶颜色为White",White);//增加菜单项
glutAddMenuEntry("更改房顶颜色为Red",Red);
glutAddMenuEntry("更改房顶颜色为Green",Green);
glutAddMenuEntry("更改房顶颜色为Blue",Blue);
glutAddMenuEntry("更改房顶颜色为Yellow",Yellow);
6.实现直接通过鼠标进行小房子在XY空间的360度旋转。

这里主要用到鼠标回调函数,定义鼠标键回调函数mouse()和鼠标移动回调函数motion(),mouse()得到鼠标键第一次按下时的位置信息,motion()用来得到更新的位置信息,然后再display()中实现场景按在motion中得到的整型坐标来进行的旋转。

void mouse(int button,int state,int mouseX,int mouseY)
{ //获取鼠标位置信息
curX=mouseX;
curY=mouseY;
}
void motion(int xPos, int yPos)
{ //获取更新的位置信息
spinX = (GLfloat)(curX-xPos);
spinY = (GLfloat)(curY-yPos);
myX= curX;
myY=curY;
glutPostRedisplay();
}
7.实现通过菜单控制灯光的开启和关闭功能。

这跟5中的功能实现过程差不多,在myinit 函数中定义了红色,绿色,蓝色三个光源,在回调函数menu中增加了if语句:
if(inputname==OPENLIGHT0){
glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glDisable(GL_LIGHT1);glDisable(
GL_LIGHT2);
}
if(inputname==OPENLIGHT1){
glEnable(GL_LIGHTING);glDisable(GL_LIGHT0);glEnable(GL_LIGHT1);glDisable( GL_LIGHT2);}
if(inputname==OPENLIGHT2){
glEnable(GL_LIGHTING);glDisable(GL_LIGHT0);glDisable(GL_LIGHT1);glEnable( GL_LIGHT2);}
if(inputname==CLOSELIGHT){glDisable(GL_LIGHTING);}
//在初始设置函数myinit()函数中设置光源
void myinit(void){
//定义光源颜色和位置
GLfloat light0_position[]= { 1.0, 5.0, -5.0, 1.0 };
GLfloat light0_color[]= { 1.0, 0.0, 0.0, 1.0 };//红色光源
GLfloat ambient0_color[]= { 0.3, 0.0, 0.0, 1.0 };
GLfloat light1_position[]= { 1.0, 5.0,-5.0, 1.0 };
GLfloat light1_color[]= { 0.0, 1.0, 0.0, 1.0 };//绿色光源
GLfloat ambient1_color[]= { 0.0, 0.3, 0.0, 1.0 };
GLfloat light2_position[]= { -5.0, 5.0,3.0, 1.0 };
GLfloat light2_color[]= { 0.0, 0.0, 1.0, 1.0 };//蓝色光源
GLfloat ambient2_color[]= { 0.0, 0.0, 0.3, 1.0 };
//定义光源属性和光照模型
glLightfv(GL_LIGHT0, GL_POSITION, light0_position );
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0_color );
glLightfv(GL_LIGHT0, GL_SPECULAR, light0_color );
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_color );
glLightfv(GL_LIGHT1, GL_POSITION, light1_position );
glLightfv(GL_LIGHT1, GL_AMBIENT, ambient1_color );
glLightfv(GL_LIGHT1, GL_SPECULAR, light1_color );
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_color );
glLightfv(GL_LIGHT2, GL_POSITION, light2_position );
glLightfv(GL_LIGHT2, GL_AMBIENT, ambient2_color );
glLightfv(GL_LIGHT2, GL_SPECULAR, light2_color );
glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_color );
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1);//双面
8.实现通过菜单回调函数进行屋内自动漫游和停止漫游。

这里用到了空闲事件回调函数idle ,声明animate()函数来获取坐标,在display()中实现移动和旋转。

//声明空闲回调函数
void animate(void){
time +=deltaTime;
cubez=-time;if(cubez<=-2){cubez=-2;cubex=time+1;}
if(cubex>=5){cubex=6;angley=time-10;}
glutPostRedisplay();
}
//声明当鼠标点击菜单中的停止漫游时执行的函数
void stopanimate(void){
cubex=6;cubez=-2;angley=-10;
}
//在menu()函数中实现
if(inputname==play){glutIdleFunc(animate);}
if(inputname==stop){glutIdleFunc(stopanimate);}
9.实现了通过绘制点来建模桌子。

首先定义数组,分别比表示桌面/桌角的点线面和法线,然后再再drawdesk()函数中实现点线面的结合。

typedef GLfloat point[3];
typedef int edge[2];
typedef int face[4];
//定义桌面的点,线,面和法线
point vertices[8]={{-2.9,-0.5,-0.6},
{-2.9,-0.5,0.4},
{-2.9,-0.4,-0.6},
{-2.9,-0.4,0.4},
{-1.9,-0.5,-0.6},
{-1.9,-0.5,0.4},
{-1.9,-0.4,-0.6},
{-1.9,-0.4,0.4}};
point normals[6]={{0.0,0.0,1.0},
{-1.0,0.0,0.0},
{0.0,0.0,-1.0},
{1.0,0.0,0.0},
{0.0,-1.0,0.0},
{0.0,1.0,0.0}};
edge edges[24]={{0,1},{1,3},{3,2},{2,0},
{0,4},{1,5},{3,7},{2,6},
{4,5},{5,7},{7,6},{6,4},
{1,0},{3,1},{2,3},{0,2},
{4,0},{5,1},{7,3},{6,2},
{5,4},{7,5},{6,7},{4,6}};
face cube[6]={{0,1,2,3},{5,9,18,13},
{14,6,10,19},{7,11,16,15},
{4,8,17,12},{22,11,20,23}};
void drawdesk(void){
int face,edge;
glBegin(GL_QUADS);
glColor3f(0.3,0.3,0.3);
for(face=0;face<6;face++){
glNormal3fv(normals[face]);
for(edge=0;edge<4;edge++)
glVertex3fv(vertices[edges[cube[face][edge]][0]]);
}
glEnd();
glDeleteTextures(1, texName2);
}
10.实现视点的切换和窗户的切换。

这也是菜单的选择项,与上面的菜单项选择声明定义和实现差不多,视点切换中主要定义了两个视点:
if(inputname==v1){
gluLookAt(-2, 1.0, -2, -1.5, 0., 0., 0.0, 1.0, .0);
}
else{
gluLookAt(6.0, 0.0, 0.0, 0, 0., 0., 0.0, 1.0, .0);
}
11.实现解释系统如何操作的文本。

这里主要用到了doRasterString()函数来显示字符,在
display()函数中实现。

具体代码如下:
void doRasterString( float x, float y, float z, char *s)
{
char c;
glRasterPos3f(x,y,z);
for ( ; (c = *s) != '\0'; s++ )
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, c); }
//在display()函数中调用
doRasterString(0,-2.5,3.,"rotate around X:q/w");
doRasterString(0,-2.5,1.,"rotate around Y:a/s");
doRasterString(0,-2.5,-1.,"rotate around Z:z/x");
doRasterString(0,-2.75,3.,"translate around X:e/r");
doRasterString(0,-2.75,1.,"translate around Y:d/f");
doRasterString(0,-2.75,-1.,"translate around Z:c/v");
doRasterString(0,-2.25,3.,"door:g/h");
第3章系统展望
描述未完成或还有缺陷的一些功能,并展望今后可以继续完善或增加的功能。

未完成或缺陷的功能:
1.在这个系统中对于菜单中的更改房顶颜色的几个选项,我本来想做成子菜单形式的,可是没有完成.
2.菜单中的跟视点有关的选项的效果并不好,当先通过键盘键改变房子的位置后再选择菜单中的切换视点选项或室内漫游选项所得出的结果不是原先设定的效果了.
3.菜单中有些选项不能一起选择来产生叠加的效果.如选择视点改变房子的观看位置之后,再选择切换窗户的选项时,房子的观看位置又重新回到了初始位置,反过来也是一样.
4.不会改变门的旋转轴,所以只能让它围绕Y轴中心旋转,最终只能将整个房子向Y轴移动。

继续完善和增加的功能:
以上四个缺陷都有待完善。

还可以增加当鼠标处于房子的哪部分之后点击右键就会弹出相应的菜单来更改它的颜色(如当鼠标放置在前面的墙时,点击右键就会弹出更改其颜色的菜单,选择相应的选项后前面的墙就更改为选中的颜色),这样的话,就可以自己为整个房子的每个部分配自己喜欢的颜色了,感觉这应该是拾取方面的,不过现在还不会成功完成。

看了书上的MUI工具之后,感觉还可以运用一些按钮,滑动条等工具来完善整个系统。

附录源代码
附程序所有代码,并增加适当注释说明
#pragma comment(lib,"glut32.lib")
#include"glut.h"
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#undef ALL
#define ALL
#define SEED 13
#define ANGLE 2.0
#define Len 0.3
#define White 1
#define Red 2
#define Green 3
#define Blue 4
#define Yellow 5
#define RESHAPE 7
#define OPENLIGHT0 8
#define OPENLIGHT1 9
#define OPENLIGHT2 10
#define CLOSELIGHT 11
#define v1 12
#define play 14
#define stop 15
#define window1 16
#define TEX_WIDTH 256
#define TEX_HEIGHT 256
#define deltaTime 0.05static GLubyte texImage[TEX_WIDTH][TEX_HEIGHT][3]; static GLubyte texImage1[TEX_WIDTH][TEX_HEIGHT][3];
static GLubyte texImage2[TEX_WIDTH][TEX_HEIGHT][3];
static GLubyte texImage3[TEX_WIDTH][TEX_HEIGHT][3];
static GLuint texName[1];
static GLuint texName1[1];
static GLuint texName2[1];
static GLuint texName3[1];
typedef GLfloat point3[3];
typedef GLfloat point[3];
typedef int edge[2];
typedef int face[4];
typedef GLfloat point1[3];
typedef int edge1[2];
typedef int face1[4];
typedef GLfloat point2[3];
typedef int edge2[2];
typedef int face2[4];
typedef GLfloat point3[3];
typedef int edge3[2];
typedef int face3[4];
typedef GLfloat point4[3];
typedef int edge4[2];
typedef int face4[4];
//定义桌面的点,线,面和法线
point vertices[8]={{-2.9,-0.5,-0.6},
{-2.9,-0.5,0.4},
{-2.9,-0.4,-0.6},
{-2.9,-0.4,0.4},
{-1.9,-0.5,-0.6},
{-1.9,-0.5,0.4},
{-1.9,-0.4,-0.6},
{-1.9,-0.4,0.4}};
point normals[6]={{0.0,0.0,1.0},
{-1.0,0.0,0.0},
{0.0,0.0,-1.0},
{1.0,0.0,0.0},
{0.0,-1.0,0.0},
{0.0,1.0,0.0}};
edge edges[24]={{0,1},{1,3},{3,2},{2,0}, {0,4},{1,5},{3,7},{2,6},
{4,5},{5,7},{7,6},{6,4},
{1,0},{3,1},{2,3},{0,2},
{4,0},{5,1},{7,3},{6,2},
{5,4},{7,5},{6,7},{4,6}};
face cube[6]={{0,1,2,3},{5,9,18,13}, {14,6,10,19},{7,11,16,15},
{4,8,17,12},{22,11,20,23}};
//定义桌角的点,线,面和法线
point1 vertices1[8]={{-2.8,-1,-0.5},
{-2.8,-1,-0.4},
{-2.8,-0.5,-0.5},
{-2.8,-0.5,-0.4},
{-2.7,-1,-0.5},
{-2.7,-1,-0.4},
{-2.7,-0.5,-0.5},
{-2.7,-0.5,-0.4}};
point1 normals1[6]={{0.0,0.0,1.0},
{-1.0,0.0,0.0},
{0.0,0.0,-1.0},
{1.0,0.0,0.0},
{0.0,-1.0,0.0},
{0.0,1.0,0.0}};
edge1 edges1[24]={{0,1},{1,3},{3,2},{2,0}, {0,4},{1,5},{3,7},{2,6},
{4,5},{5,7},{7,6},{6,4},
{1,0},{3,1},{2,3},{0,2},
{4,0},{5,1},{7,3},{6,2},
{5,4},{7,5},{6,7},{4,6}};
face1 cube1[6]={{0,1,2,3},{5,9,18,13}, {14,6,10,19},{7,11,16,15},
{4,8,17,12},{22,11,20,23}};
point2 vertices2[8]={{-2.1,-1,-0.5},
{-2.1,-1,-0.4},
{-2.1,-0.5,-0.5},
{-2.1,-0.5,-0.4},
{-2.0,-1,-0.5},
{-2.0,-1,-0.4},
{-2.0,-0.5,-0.5},
{-2.0,-0.5,-0.4}};
point2 normals2[6]={{0.0,0.0,1.0},
{-1.0,0.0,0.0},
{0.0,0.0,-1.0},
{1.0,0.0,0.0},
{0.0,-1.0,0.0},
{0.0,1.0,0.0}};
edge2 edges2[24]={{0,1},{1,3},{3,2},{2,0}, {0,4},{1,5},{3,7},{2,6},
{4,5},{5,7},{7,6},{6,4},
{1,0},{3,1},{2,3},{0,2},
{4,0},{5,1},{7,3},{6,2},
{5,4},{7,5},{6,7},{4,6}};
face2 cube2[6]={{0,1,2,3},{5,9,18,13},
{14,6,10,19},{7,11,16,15},
{4,8,17,12},{22,11,20,23}};
point3 vertices3[8]={{-2.8,-1,0.2},
{-2.8,-1,0.3},
{-2.8,-0.5,0.2},
{-2.8,-0.5,0.3},
{-2.7,-1,0.2},
{-2.7,-1,0.3},
{-2.7,-0.5,0.2},
{-2.7,-0.5,0.3}};
point3 normals3[6]={{0.0,0.0,1.0},
{-1.0,0.0,0.0},
{0.0,0.0,-1.0},
{1.0,0.0,0.0},
{0.0,-1.0,0.0},
{0.0,1.0,0.0}};
edge3 edges3[24]={{0,1},{1,3},{3,2},{2,0},
{0,4},{1,5},{3,7},{2,6},
{4,5},{5,7},{7,6},{6,4},
{1,0},{3,1},{2,3},{0,2},
{4,0},{5,1},{7,3},{6,2},
{5,4},{7,5},{6,7},{4,6}};
face3 cube3[6]={{0,1,2,3},{5,9,18,13},
{14,6,10,19},{7,11,16,15},
{4,8,17,12},{22,11,20,23}};
point4 vertices4[8]={{-2.1,-1,0.2},
{-2.1,-1,0.3},
{-2.1,-0.5,0.2},
{-2.1,-0.5,0.3},
{-2.0,-1,0.2},
{-2.0,-1,0.3},
{-2.0,-0.5,0.2},
{-2.0,-0.5,0.3}};
point4 normals4[6]={{0.0,0.0,1.0},
{-1.0,0.0,0.0},
{0.0,0.0,-1.0},
{1.0,0.0,0.0},
{0.0,-1.0,0.0},
{0.0,1.0,0.0}};
edge4 edges4[24]={{0,1},{1,3},{3,2},{2,0},
{0,4},{1,5},{3,7},{2,6},
{4,5},{5,7},{7,6},{6,4},
{1,0},{3,1},{2,3},{0,2},
{4,0},{5,1},{7,3},{6,2},
{5,4},{7,5},{6,7},{4,6}};
face4 cube4[6]={{0,1,2,3},{5,9,18,13},
{14,6,10,19},{7,11,16,15},
{4,8,17,12},{22,11,20,23}};
GLfloat xAngle = 0., yAngle = 0., zAngle = 0.,spinX,spinY;
GLfloat xLen = 0., yLen = 0., zLen = 0.,doorAngle=0;
GLfloat cubex=0.0,cubey=0.0,cubez=0.0,time=0.0;
GLfloat anglex=0,angley=0,anglez=0;
int curX,curY,myX,myY;
static char ch; // the character from the keyboard that controls the rotation
static char ch1;
static char inputname,inputname1,inputname2;
void setTexture(void);
void myinit( void );
void scene(void);
void display( void );
void reshape( int, int );
void keyboard(unsigned char, int, int );
void drawHouse(void);
//定义doRasterString()函数来显示字符
void doRasterString( float x, float y, float z, char *s)
{
char c;
glRasterPos3f(x,y,z);
for ( ; (c = *s) != '\0'; s++ )
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, c);
}
//通过setTexture函数为门、窗、墙等定义贴图
void setTexture(void)
{
//为门贴图
FILE *fd;
GLubyte ch;
int i,j,k;
fd = fopen("3.pbm", "rb");
for(i=0; i<TEX_WIDTH; i++) // for each row
{
for (j=0; j<TEX_HEIGHT; j++) // for each column
{
for (k=0; k<3; k++) // read RGB components of the pixel
{
fread(&ch, 1, 1, fd);
texImage1[i][j][k] = (GLubyte) ch;
}
}
}
fclose(fd);
//为窗贴图
fd = fopen("1.pbm", "rb");
for(i=0; i<TEX_WIDTH; i++) // for each row
{
for (j=0; j<TEX_HEIGHT; j++) // for each column
{
for (k=0; k<3; k++) // read RGB components of the pixel
{
fread(&ch, 1, 1, fd);
texImage[i][j][k] = (GLubyte) ch;
}
}
}
//为桌子贴图
fclose(fd);
fd = fopen("12.pbm", "rb");
for(i=0; i<TEX_WIDTH; i++) // for each row
{
for (j=0; j<TEX_HEIGHT; j++) // for each column
{
for (k=0; k<3; k++) // read RGB components of the pixel
{
fread(&ch, 1, 1, fd);
texImage2[i][j][k] = (GLubyte) ch;
}
}
}
//为地面贴图
fclose(fd);
fclose(fd);
fd = fopen("6.pbm", "rb");
for(i=0; i<TEX_WIDTH; i++) // for each row
{
for (j=0; j<TEX_HEIGHT; j++) // for each column
{
for (k=0; k<3; k++) // read RGB components of the pixel
{
fread(&ch, 1, 1, fd);
texImage3[i][j][k] = (GLubyte) ch;
}
}
}
fclose(fd);
}
//初始化函数定义光源
void myinit(void)
{
glClearColor(0.8,0.8,0.8,1);
//定义光源颜色和位置
GLfloat light0_position[]= { 1.0, 5.0, -5.0, 1.0 };
GLfloat light0_color[]= { 1.0, 0.0, 0.0, 1.0 };//红色光源
GLfloat ambient0_color[]= { 0.3, 0.0, 0.0, 1.0 };
GLfloat light1_position[]= { 1.0, 5.0,-5.0, 1.0 };
GLfloat light1_color[]= { 0.0, 1.0, 0.0, 1.0 };//绿色光源
GLfloat ambient1_color[]= { 0.0, 0.3, 0.0, 1.0 };
GLfloat light2_position[]= { -5.0, 5.0,3.0, 1.0 };
GLfloat light2_color[]= { 0.0, 0.0, 1.0, 1.0 };//蓝色光源
GLfloat ambient2_color[]= { 0.0, 0.0, 0.3, 1.0 };
//定义光源属性和光照模型
glLightfv(GL_LIGHT0, GL_POSITION, light0_position );
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0_color );
glLightfv(GL_LIGHT0, GL_SPECULAR, light0_color );
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_color );
glLightfv(GL_LIGHT1, GL_POSITION, light1_position );
glLightfv(GL_LIGHT1, GL_AMBIENT, ambient1_color );
glLightfv(GL_LIGHT1, GL_SPECULAR, light1_color );
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_color );
glLightfv(GL_LIGHT2, GL_POSITION, light2_position );
glLightfv(GL_LIGHT2, GL_AMBIENT, ambient2_color );
glLightfv(GL_LIGHT2, GL_SPECULAR, light2_color );
glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_color );
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,1);//双面
glEnable(GL_DEPTH_TEST); //深度测试
/*glEnable(GL_TEXTURE_2D);
GLfloat mat_specular[]={0.8,0.8,0.8,1.0};
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);*/// allow z-buffer display
//define the texture available to the project
setTexture();
glEnable(GL_TEXTURE_2D);
}
//声明键盘控制进行旋转,移动控制的键盘键
void keyboard(unsigned char key, int x, int y)
{
ch = ' ';
switch (key)
{
case'q' : // rotate around X; q = positive, w = negative
xAngle += ANGLE;ch = key; break;
case'w' :
xAngle -= ANGLE;ch = key; break;
case'a' : // rotate around Y; q = positive, s = negative
yAngle += ANGLE;ch = key; break;
case's' :
yAngle -= ANGLE;ch = key; break;
case'z' : // rotate around Z; z = positive, x = negative
zAngle += ANGLE;ch = key; break;
case'x' :
zAngle -= ANGLE;ch = key; break;
case'g' : // rotate around Y; h = positive, g = negative doorAngle -= ANGLE;
if(doorAngle<-120)
doorAngle=-120; break;
case'h' :
doorAngle += ANGLE;
if(doorAngle>120)
doorAngle=120; break;
}
ch1 = ' ';
switch (key)
{
case'e' : // translate around X; e = positive, r = negative
xLen += Len;ch1 = key; break;
case'r' :
xLen -= Len;ch1 = key; break;
case'd' : // translate around Y; d = positive, f = negative
yLen += Len;ch1 = key; break;
case'f' :
yLen -= Len;ch1 = key; break;
case'c' : // translate around Z; c = positive, v = negative
zLen += Len;ch1 = key; break;
case'v' :
zLen -= Len;ch1 = key; break;
}
glutPostRedisplay();
}
//画门
void drawDoor(void){
point3 normals1[6]={{ 0.0, 0.0, 1.0},
{-1.0, 0.0, 0.0},
{ 0.0, 0.0,-1.0},
{ 1.0, 0.0, 0.0},
{ 0.0,-1.0, 0.0},
{ 0.0, 1.0, 0.0} };
glGenTextures(1, texName1); //生成一系列纹理名
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D,texName1[0]); //绑定纹理名和纹理目标
//定义目标纹理以及要定义的纹理属性并制定属性值
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
//说明纹理图像
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB8,TEX_WIDTH,TEX_HEIGHT,
0,GL_RGB,GL_UNSIGNED_BYTE,texImage1);
glBegin(GL_QUADS);
glNormal3fv(normals1[3]);
glTexCoord2f(1.0, 1); glVertex3f(0,-1.0,0);
glTexCoord2f(1, 0.0);glVertex3f(0,0.4,0);
glTexCoord2f(0,0.0);glVertex3f(0,0.4,0.8);
glTexCoord2f(0.0,1);glVertex3f(0,-1.0,0.8);
glEnd();
glDeleteTextures(1, texName1);
}
//画桌子
void drawdesk(void){
glGenTextures(1, texName2);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D,texName2[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB8,TEX_WIDTH,TEX_HEIGHT,
0,GL_RGB,GL_UNSIGNED_BYTE,texImage2);
int face,edge;
glBegin(GL_QUADS);
glColor3f(0.3,0.3,0.3);
for(face=0;face<6;face++){
glNormal3fv(normals[face]);
for(edge=0;edge<4;edge++)
glVertex3fv(vertices[edges[cube[face][edge]][0]]);
}
glEnd();
glEnd();
int face1,edge1;
glBegin(GL_QUADS);
glColor3f(0.3,0.3,0.3);
for(face1=0;face1<6;face1++){
glNormal3fv(normals1[face1]);
for(edge1=0;edge1<4;edge1++)
glVertex3fv(vertices1[edges1[cube1[face1][edge1]][0]]);
}
glEnd();
int face2,edge2;
glBegin(GL_QUADS);
glColor3f(0.3,0.3,0.3);
for(face2=0;face2<6;face2++){
glNormal3fv(normals2[face2]);
for(edge2=0;edge2<4;edge2++)
glVertex3fv(vertices2[edges2[cube2[face2][edge2]][0]]);
}
glEnd();
int face3,edge3;
glBegin(GL_QUADS);
glColor3f(0.3,0.3,0.3);
for(face3=0;face3<6;face3++){
glNormal3fv(normals3[face3]);
for(edge3=0;edge3<4;edge3++)
glVertex3fv(vertices3[edges3[cube3[face3][edge3]][0]]);
}
glEnd();
int face4,edge4;
glBegin(GL_QUADS);
glColor3f(0.3,0.3,0.3);
for(face4=0;face4<6;face4++){
glNormal3fv(normals4[face4]);
for(edge4=0;edge4<4;edge4++)
glVertex3fv(vertices4[edges4[cube4[face4][edge4]][0]]);
}
glEnd();
glDeleteTextures(1, texName2);
}
//画窗户
void drawWindow(void){
if(inputname1==window1){
glColor4f(0.2,0.2,0.2,1);
glBegin(GL_QUADS);
glVertex3f(-1.9,-0.5,2.4);
glVertex3f(-1.9,-0.45,2.4);
glVertex3f(-1.1,-0.45,2.4);
glVertex3f(-1.1,-0.5,2.4);
glEnd();
glColor4f(0.2,0.2,0.2,1);
glBegin(GL_QUADS);
glVertex3f(-1.9,0.45,2.4);
glVertex3f(-1.9,0.5,2.4);
glVertex3f(-1.1,0.5,2.4);
glVertex3f(-1.1,0.45,2.4);
glEnd();
glColor4f(0.2,0.2,0.2,1);
glBegin(GL_QUADS);
glVertex3f(-1.9,-0.5,2.4);
glVertex3f(-1.9,0.5,2.4);
glVertex3f(-1.85,0.5,2.4);
glVertex3f(-1.85,-0.5,2.4);
glEnd();
glColor4f(0.2,0.2,0.2,1);
glBegin(GL_QUADS);
glVertex3f(-1.15,-0.5,2.4);
glVertex3f(-1.15,0.5,2.4);
glVertex3f(-1.1,0.5,2.4);
glVertex3f(-1.1,-0.5,2.4);
glEnd();
glColor4f(0.2,0.2,0.2,1);
glBegin(GL_QUADS);
glVertex3f(-1.525,-0.5,2.4);
glVertex3f(-1.525,0.5,2.4);
glVertex3f(-1.475,0.5,2.4);
glEnd();
}
else{
glGenTextures(1, texName);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D,texName[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexImage2D(GL_TEXTURE_2D,0,GL_RGB8,TEX_WIDTH,TEX_HEIGHT,
0,GL_RGB,GL_UNSIGNED_BYTE,texImage);
glBegin(GL_QUADS);//窗户
glNormal3fv(normals1[5]);
glTexCoord2f(1.0, 1);glVertex3f(-1.9,-0.5,2.4);
glTexCoord2f(1, 0.0);glVertex3f(-1.9,0.5,2.4);
glTexCoord2f(0,0.0);glVertex3f(-1.1,0.5,2.4);
glTexCoord2f(0.0,1);glVertex3f(-1.1,-0.5,2.4);
glEnd();
glDeleteTextures(1, texName);}
}
//在drawHouse函数中实现贴图,并且在drawHouse中画出整个房子
void drawHouse(void){
//定义材质
GLfloat shininess[]={50.0};
glDisable(GL_TEXTURE_2D);
GLfloat white[]={1.0,1.0,1.0,1.0};
GLfloat mat_specular[]={0.8,0.8,0.8,1.0};
glMaterialfv(GL_FRONT,GL_AMBIENT,white);
glMaterialfv(GL_FRONT,GL_DIFFUSE,white);
glMaterialfv(GL_FRONT,GL_SHININESS,shininess);
glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
//法线
point3 normals[6]={{ 0.0, 0.0, 1.0},
{-1.0, 0.0, 0.0},
{ 0.0, 0.0,-1.0},
{ 1.0, 0.0, 0.0},
{ 0.0,-1.0, 0.0},
{ 0.0, 1.0, 0.0} };
glBegin(GL_TRIANGLES);//前面上
glColor4f(0.3,0.3,0.7,1);
glVertex3f(-3,1.0,2.4);
glVertex3f(-1.5,2.0,2.4);
glVertex3f(0,1.0,2.4);
glEnd();
glBegin(GL_QUADS);//前面下
glColor4f(0.3,0.3,0.7,1);
glVertex3f(-3,-1.0,2.4);
glVertex3f(-3,1.0,2.4);
glVertex3f(-1.9,1.0,2.4);
glVertex3f(-1.9,-1.0,2.4);
glEnd();
glBegin(GL_QUADS);
glColor4f(0.3,0.3,0.7,1);
glVertex3f(-1.9,0.5,2.4);
glVertex3f(-1.9,1.0,2.4);
glVertex3f(-1.1,0.5,2.4);
glEnd();
glBegin(GL_QUADS);
glColor4f(0.3,0.3,0.7,1);
glVertex3f(-1.9,-1.0,2.4);
glVertex3f(-1.9,-0.5,2.4);
glVertex3f(-1.1,-0.5,2.4);
glVertex3f(-1.1,-1.0,2.4);
glEnd();
glBegin(GL_QUADS);
glColor4f(0.3,0.3,0.7,1);
glVertex3f(-1.1,-1.0,2.4);
glVertex3f(-1.1,1.0,2.4);
glVertex3f(0,1.0,2.4);
glVertex3f(0,-1.0,2.4);
glEnd();
glBegin(GL_TRIANGLES);//后面上
glColor4f(0.5,0.3,0.3,1);
glVertex3f(-3,1.0,-1.6);
glVertex3f(-1.5,2.0,-1.6);
glVertex3f(0,1.0,-1.6);
glEnd();
glBegin(GL_QUADS);//后面下
glColor4f(0.5,0.3,0.3,1);
glVertex3f(-3,-1.0,-1.6);
glVertex3f(-3,1.0,-1.6);
glVertex3f(0,1.0,-1.6);
glVertex3f(0,-1.0,-1.6);
glEnd();
GLfloat color[4];
if(inputname2==White){
color[0]=1;color[1]=1;color[2]=1;color[3]=1;} if(inputname2==Red){
color[0]=1;color[1]=0;color[2]=0;color[3]=1;} if(inputname2==Green){
color[0]=0;color[1]=1;color[2]=0;color[3]=1;} if(inputname2==Blue){
color[0]=0;color[1]=0;color[2]=1;color[3]=1;} if(inputname2==Yellow){
color[0]=1;color[1]=1;color[2]=0;color[3]=1;} glBegin(GL_QUADS);//右边上
glColor4f(color[0],color[1],color[2],color[3]);
glVertex3f(-1.5,2,-1.6);
glVertex3f(-1.5,2,2.4);
glVertex3f(0,1,2.4);
glVertex3f(0,1,-1.6);
glEnd();
glBegin(GL_QUADS);//右边下
glColor4f(0.1,0.5,0.3,1);
glVertex3f(0,-1.0,0.8);
glVertex3f(0,1.0,0.8);
glVertex3f(0,1.0,2.4);
glVertex3f(0,-1.0,2.4);
glEnd();
glBegin(GL_QUADS);
glColor4f(0.1,0.5,0.3,1);
glVertex3f(0,0.4,0);
glVertex3f(0,1.0,0);。

相关文档
最新文档