《openGL构造教室》由会员分享,可在线阅读,更多相关《openGL构造教室(39页珍藏版)》请在金锄头文库上搜索。
1、基于openGL的虚拟教室虚拟现实与数据可视化课程作业董元 22011207指导老师:孙立博老师仪器科学与工程学院 2013年12月16日一、 作业要求用openGL制作一个虚拟教室。要求视角可变化,教室里的物品不少于五件。二、 完成情况我的openGL虚拟教室完成情况如下:1、 绘制出的教室里的基本物体:黑板、讲台、投影仪、空调、门窗、音响、九张桌子、九张凳子等。虚拟教室整体看上去接近真实生活中的教室。2、 添加了灯光和纹理效果:门窗以及空调均是用纹理贴出来的。使教室看起来更加生动形象。3、 为教室加上了可用键盘控制的动态效果:可控制灯光亮灭、投影仪收起放下、六块黑板的上下滑动以及音响的开关
2、。4、 引用FMOD音乐引擎,为教室加上可控背景音效(即3中的音响开关)。5、 在输出窗口添加操作提示信息,使界面更加人性化。三、 成果演示1、整体效果图2、改变视角效果3、开灯关灯对比效果图未开灯时:开灯时:4、 投影仪放下效果图:5、黑板移动效果图6、局部细节效果图四、 内容介绍下面我将从代码的角度简单介绍一下我的整个教室程序。代码部分包括一个头文件(MyHeader.h)和一个cpp文件(main.cpp)。为了增加程序的可读性,我将相关的变量定义、函数声明等集中放置在头文件下面。在我的全部代码中,除了主函数外,共定义了19个子函数。如下图所示:主程序部分和一般的openGL程序一样,完
3、成初始化、窗口的绘制、显示回调函数和键盘以及一些特殊事件的响应。主函数如下:初始化部分由函数init()完成,而init中又调用了进行灯光初始化的函数initlight()以及进行纹理图像载入的LoadTexture1()、LoadTexture2()、LoadTexture3()。这主要是因为灯光初始化和载入纹理相关代码较多,这么做是为了使代码看上去更加层次分明绘制教室的工作由回调函数display()完成。而所有子函数中与绘制教室相关的子函数还有DrawRoom()、DrawDesk()、DrawBlackboard()以及Drawotherthings();分别完成教室墙面、黑板、桌椅及
4、其他物体的绘制。其中,整个教室空间有六个大矩形拼接而成;桌椅由梯形不一的长方体拼接而成。可以这样说,整个教室基本上都是由不同的立方体和矩形构成的。所以从这一点上来说,绘制教室并没有使用任何复杂的openGL内置函数。响应按键主要是由OnKeyboard()和OnSpecial()完成的。OnSpecia()函数其实只是响应退出窗口的ECS键,为了从逻辑上区分这一事件与普通按键响应的不同,我把响应这一事件的代码放在了OnSpecia()函数下。而其他响应普通事件的代码则在OnKeyboard()下。而普通事件的响应程序,又调用到了函数InitFMOD(),(响应播放音乐),函数projector
5、_dispaly1()、projector_dispaly2(),(响应投影仪的放下与收起,实质是在对窗口的重新绘制时改变投影仪的相关参数)。五、 收获感想1、对于任何一种编程语言或者是API,当我们在使用它们编程时,都首先要对其基本原理有一个最基本的认识。贸然地调用函数或是凭感觉去编程,往往会造成不可预知的错误。而且一旦错误发生,往往很难解决。在程序的编写过程中,最开始时对openGL了解甚少,在参考示例程序时移植他人的代码往往很难产生自己希望的效果,就是这个道理。而且,在编写整个程序的过程中,出现过一个我一直无法解决的问题:通过编译后程序运行一段时间自己会卡死。在请教了老师以后才知道,该问
6、题出现的原因是我把载入纹理的代码放在了显示回调函数中,这样一来每一次重新绘制窗口,程序都会开辟新的内存用以储存相关信息。因此程序运行一段时间之后内存不足,便会报错。这个问题是我自己很难考虑到的,这也是让我认识到自己对程序的基本理解的不足,这方面需要进一步加强。2、我觉得这次作业给我带来最大的收获就是它起到了一个抛砖引玉的效果。虚拟教室的创立不仅让我对openGL这个图像程序接口产生了很大的兴趣,也让我对虚拟现实技术产生了更多的期待。而且,在编写程序的过程中我又接触到一个有趣的音乐引擎FMOD。这些都让我觉得这门课程的学习妙趣横生。虽然我在这个作业上花费了很多时间,但是收获了很多乐趣。3、在编写
7、程序的过程中,我进一步意识到网络这个公开平台资源的强大。在自学的过程中,别人的经验给了我许多启发。网络上许多达人开放式的共享资源的态度值得我们学习。互联网的发展为打开了巨大的学习空间,而在未来的学习生活中,我想我也会秉承这样一种开源共享的态度,学习知识,并且传播知识。六、 附录(一) 参考书目1Mason Woo Jakie Neider Tom Davis Dave Shreiner/著 吴斌 段海波 薛凤舞/译openGL编程权威指南中国电力出版社2网络资源:Nehe的中文openGL教程 http:/ #include#include#includeMyHeader.h /相关变量和函数
8、定义放入头文件中,增加程序可读性#include fmod.h/ 音频库的头文件#pragma comment(lib, fmodvc.lib)/ 把音频库加入到链接器中#pragma comment(lib, GLAux.lib)#pragma warning(disable:4996) /强制忽略VS2012对于老版本一些函数不安全的警告using namespace std;FSOUND_SAMPLE * handle1;int main(int argc, char * argv)Eye.x = 0.0f;/f代表这个数据是GLfloat类型的常量Eye.y = 0.0f;Eye.z
9、= 18.0f;glutInit(&argc,argv);/对glut进行初始化glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);/指定glutInitWindowSize(700,600);/窗口大小,以像素为单位窗glutInitWindowPosition(650,100);/口左上角的屏幕位置glutCreateWindow(argv0);init();/初始化glutDisplayFunc(display);/显示回调函数glutReshapeFunc(reshape);glutKeyboardFunc(OnKeyboa
10、rd);const GLubyte* test=glGetString(GL_EXTENSIONS);glutSpecialFunc(OnSpecial);glutIdleFunc(OnIdle);PrintInformation();glutMainLoop();/调用来启动程序return 0;/*函数名称:LoadBitmap*函数作用:检查文件能否被正常打开,不能则返回一个空指针*/AUX_RGBImageRec *LoadBitmap(char *Filename)/ 声明一个文件句柄用于打开文件FILE *File=NULL;/ 文件名不能空if (!Filename)return
11、 NULL;/ 以只读方式打开文件测试文件是否能够打开File=fopen(Filename,r);/ 文件是否存在if (File)/ 存在,则关闭文件fclose(File);/ 装入测试过已存在的文件return auxDIBImageLoad(Filename);/ 文件装入失败,返回NULLreturn NULL;/*函数名称:LoadTexture1*函数作用:装入位图文件并作为纹理贴图*/int LoadTexture1()int Status=FALSE;AUX_RGBImageRec *TextureImage=0;glGenTextures(1, &texture0);if
12、 (TextureImage=LoadBitmap(Images6.bmp)Status=TRUE;glBindTexture(GL_TEXTURE_2D, texture0);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 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;/*函数名称:LoadTexture2*函数作用:装入位图文件并作为纹理贴图*/int LoadTexture2()int Status=FALSE;AUX