太阳系运行动画资料.docx
《太阳系运行动画资料.docx》由会员分享,可在线阅读,更多相关《太阳系运行动画资料.docx(12页珍藏版)》请在冰豆网上搜索。
太阳系运行动画资料
大学
计算机科学与技术学院
课程设计报告
2009—2010学年第二学期
课程名称计算机图形学
设计题目实现太阳系运行动画
学生姓名
学号
专业班级
指导教师
2010年6月29日
第1章设计内容与要求
1.1总体目标和要求
目标:
以图形学算法为目标,深入研究。
继而策划、设计并实现一个能够表现计算机图形学算法原理的或完整过程的演示系统,并能从某些方面作出评价和改进意见。
通过完成一个完整程序,经历策划、设计、开发、测试、总结和验收各阶段,达到:
1)巩固和实践计算机图形学课程中的理论和算法;
2)学习表现计算机图形学算法的技巧;
3)培养认真学习、积极探索的精神。
总体要求:
策划、设计并实现一个能够充分表现图形学算法的演示系统,界面要求美观大方,能清楚地演示算法执行的每一个步骤。
1.2内容与要求
内容:
(1)掌握动画基本原理;
(2)实现三维几何变换及其组合;
功能要求:
(1)利用glutWireSphere创建太阳、地球、月亮三个球体;
(2)编写三维旋转变换矩阵实现“月亮绕着地球转,地球绕着太阳转”的效果;
第2章总体设计
2.1实验原理
设计利用VC+OpenGL作为开发平台设计程序,实现三维几何变换及其组合等各项功能。
OpenGL的基本几何变换函数介绍如下:
(1)平移变换
平移变换函数如下:
voidglTranslate{fd}(TYPEx,TYPEy,TYPEz);
三个函数参数就是目标分别沿三个轴向平移的偏移量。
这个函数表示用这三个偏移量生成的矩阵乘以当前矩阵。
当参数是(0.0,0.0,0.0)时,表示对函数glTranslate*()的操作是单位矩阵,也就是对物体没有影响。
(2)旋转变换
旋转变换函数如下:
voidglRotate{fd}(TYPEangle,TYPEx,TYPEy,TYPEz);
函数中第一个参数是表示目标沿从点(x,y,z)到原点的方向逆时针旋转的角度,后三个参数是旋转的方向点坐标。
这个函数表示用这四个参数生成的矩阵乘以当前矩阵。
当角度参数是0.0时,表示对物体没有影响。
2.2动画实现原理
双缓存技术:
这项技术能使你执行绘图代码时能够在一个屏幕之外的缓冲区内进行渲染,然后用交换命令把图形放到屏幕上。
双缓冲技术有两种用途,第一个是有些复杂的图形可能要花很长的时间绘制,而你又不希望图像绘制的所有步骤都被看见,使用双缓冲技术就可以合成一幅图像并在完成后才显示出来。
用户永远不会看到不完整的图像,只有整幅图像准备就绪之后才会把它在瞬间置于屏幕之上。
双缓冲技术的第二个用处是制作动画。
每一帧都在画面外的缓冲区绘制,完成之后再交换到屏幕上。
OpenGL支持双缓冲,但是并不是真正用来交换前台缓冲区和后台缓冲区的。
实际上,每个OpenGL支持的窗口系统都可以通过一个函数调用glutS();来实现前后缓冲区之间的交换。
本此课程设计使用了双缓存模式,程序在空闲时一直不停的调用display函数,这个函数绘制完图像后,改变旋转的角度,然后交换双缓存,这样,每画完一帧就交换,形成了动画。
另外,使用了深度缓存,激活了深度测试,这样,被遮挡的面就不会显示,大家可以把激活深度缓存的一行去掉看看效果。
大家还可以改变变换的方式,达到不同的效果。
第3章详细设计
3.1球体绘制
绘制球体需要用到Opengl的函数如下:
voidglutWireSphere(GLdoubleradius,GLintslices,GLintstacks);是画线框球函数。
实体绘制函数中,radius表示球体的半径,slices表示球体围绕z轴分割的数目,stacks表示球体沿着z轴分割的数目。
其中太阳、地球和月亮都是用glutWireSphere函数画的。
利用glutWireSphere函数可以画出立体感的线框图。
代码如下:
glutWireSphere(50.f,80,80);绘制太阳
glutWireSphere(20.f,40,40);绘制地球
glutWireSphere(7,10,10);绘制月球
3.2键盘命令
为了更好的实现交互,添加了“↑”、“↓”、“→”和“←”四个键盘命令。
可以以不同的角度来看三个球体的相对运动。
运用SpecialKeys(intkey,intx,inty)函数的参数来控制以太阳为中心的球体的旋转,函数主要代码如下:
if(key==GLUT_KEY_UP)xRot-=5.0f;
if(key==GLUT_KEY_DOWN)xRot+=5.0f;
if(key==GLUT_KEY_LEFT)yRot-=5.0f;
if(key==GLUT_KEY_RIGHT)yRot+=5.0f;
if(xRot>360.0f)xRot=0.0f;
if(xRot<-1.0f)xRot=359.0f;
if(yRot>360.0f)yRot=0.0f;
if(yRot<-1.0f)yRot=359.0f;
当按下四个键中的任何一个时,球体的相应的xRot或yRot加上或减去5.0f的角度,当xRot>360.0f或yRot>360.0f时就表示转了一圈,重新置零;xRot<-1.0f或yRot<-1.0f时就会变回359.0f,可以继续旋转。
3.3旋转功能
程序实现的具体功能:
月亮绕着地球转,地球绕着太阳转。
glRotatef(earthAngle,0,0,1);此函数表示绕着Z轴旋转earthAngle角度,有由当地球旋转角度超过360时会重新置零,代码如下:
earthAngle+=0.1;
if(earthAngle>=360){earthAngle-=360;}
月球绕地球旋转实现函数glRotatef(earthAngle/30.0*360.0,0.0f,0.0f,-1.0f);由于地球绕着太阳转的方向和月球绕着地球转的方向相反所以函数最后一个参数为-1,又月球绕着地球转大概一个月,所以第一个参数为earthAngle/30.0*360.0,月球绕着地球转的速度是地球绕公转的12倍。
3.4球体的显示
当三个球体显示在屏幕上是,在变换窗体的大小时,为了避免显示的图形的变形,所以程序添加了一个ChangeSize(GLsizeiw,GLsizeih)子程序。
在程序中用到有两个比较重要的投影变换函数,glViewport和glOrtho。
glOrtho函数:
glOrtho(left,right,bottom,top,near,far),left表示视景体左面的坐标,right表示右面的坐标,bottom表示下面的,top表示上面的。
glOrtho是创建一个正交平行的视景体。
一般用于物体不会因为离屏幕的远近而产生大小的变换的情况。
假设有一个球体,半径为1,圆心在(0,0,0),那么,我们设定glOrtho(-1.5,1.5,-1.5,1.5,-10,10);就表示用一个宽高都是3的框框把这个球体整个都装了进来。
如果设定glOrtho(0.0,1.5,-1.5,1.5,-10,10);就表示用一个宽是1.5,高是3的框框把整个球体的右面装进来;如果设定glOrtho(0.0,1.5,0.0,1.5,-10,10);就表示用一个宽和高都是1.5的框框把球体的右上角装了进来。
glViewport函数:
glOrtho函数只是负责使用什么样的视景体来截取图像,并不负责使用某种规则把图像呈现在屏幕上。
glViewport主要完成这样的功能。
它负责把视景体截取的图像按照怎样的高和宽显示到屏幕上。
假设用一个正方形截面的视景体截取的图像,但是拉伸到屏幕上显示的时候显示屏变宽了,倒是显示的时候把一个正方形的图像“活生生的给拉宽了”。
就会产生变形。
这样,就需要调整OpenGL显示屏。
因为用的正方形的视景体,所以虽然窗体是那么宽,但是只用其中的长就够了。
实现代码:
GLfloatnRange=250.0f;//大小
if(h==0)h=1;//为窗口尺寸设置视角
glViewport(0,0,w,h);//重设投影映射矩阵堆
glMatrixMode(GL_PROJECTION);//设置当前矩阵为模型视图矩阵
glLoadIdentity();//重置当前指定的矩阵为单位矩阵
if(w<=h)
glOrtho(-nRange,nRange,-nRange*h/w,nRange*h/w,-nRange,nRange);
else
glOrtho(-nRange*w/h,nRange*w/h,-nRange,nRange,-nRange,nRange);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
SetupRC()函数为显示的设置函数,有设置清空颜色,选择平坦或光滑渐变模式,或被遮住的部分不绘制。
3.5程序缺陷
本程序实现的功能是太阳、地球和月亮的旋转问题,虽然程序实现了,但是还有不足之处。
第一:
程序的功能不能实现地球的公转轨道不是真正的公转轨道,月球的也不可以。
第二:
地球的公转周期和月球绕地球转的周期的关系不是很精确。
第三:
地球和月球虽然自转,但是方向是随机的,不能确定。
第4章功能实现
4.1月亮绕着地球转,地球绕着太阳转
4.2键盘命令实现
4.3主要的程序清单
#include"GL/glut.h"
#include
#include
staticGLfloatxRot=100.0f;
staticGLfloatyRot=0.0f;
voidSpecialKeys(intkey,intx,inty);
voidChangeSize(GLsizeiw,GLsizeih);
voidSetupRC();
voidRenderScene()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清空颜色缓冲区,填充的颜色由glClearColor(0,0.0,0.0,1);指定为黑色
glPushMatrix();将当前矩阵压入堆栈
glRotatef(xRot,1.0f,0.0f,0.0f);//x,y,z定义的是转动轴的位置,模型位置和轴位置越远,转的越慢,要是轴穿过模型中心,就是自传
glRotatef(yRot,0.0f,1.0f,0.0f);
//绘制太阳
glColor3f(1.0f,1.0f,0.0f);//黄色
glutWireSphere(50.f,80,80);//画太阳
//绘制地球
staticGLfloatearthAngle=0;
constGLfloatRADIUS=100.f;//绕着太阳转的半径范围
glRotatef(earthAngle,0,0,1);//x,y,z定义的是转动轴的位置,模型位置和轴位置越远,转的越慢,要是轴穿过模型中心,就是自传
glTranslatef(100.f,100.f,0);//物体将在(0.0f,0.0f,0.0f)的位置绘制
glColor3f(0.1f,0.1f,0.7f);//颜色
glutWireSphere(20.f,40,40);
//绘制“月亮”
glColor3f(1.0f,1.0f,1.0f);
glRotatef(earthAngle/30.0*360.0,0.0f,0.0f,-1.0f);
glTranslatef(RADIUS/3,0.0f,0.0f);
glutWireSphere(7,10,10);
//转转转转
earthAngle+=0.1;
if(earthAngle>=360)
{
earthAngle-=360;
}
printf("Angle:
%f\n",earthAngle);
glPopMatrix();弹出先前所压矩阵
glutS();//双缓冲
}
intmain(intargc,char*argv[])
{
glutInit(&argc,argv);//对GLUT进行初始化,本函数必须在GLUT使用之前被调用。
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);//设置显示方式
glutInitWindowSize(1250,700);//设置窗口大小
glutInitWindowPosition(1,1);//设置窗口在屏幕中的位置
glutCreateWindow("计算机-07-4-张坤");//创建窗口,参数作为标题
glutDisplayFunc(RenderScene);
glutIdleFunc(RenderScene);//glutIdleFunc表示在CPU空闲的时间调用某一函数
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
SetupRC();
glutMainLoop();//设置一个消息循环
return1;
}
voidSetupRC()
{
glClearColor(0,0,0,1.0);
glShadeModel(GL_SMOOTH);//选择平坦或光滑渐变模式。
GL_SMOOTH为后者
glEnable(GL_DEPTH_TEST);//被遮住的部分不绘制
}
voidChangeSize(GLsizeiw,GLsizeih)
{
GLfloatnRange=250.0f;//大小
if(h==0)h=1;//为窗口尺寸设置视角
glViewport(0,0,w,h);//重设投影映射矩阵堆
glMatrixMode(GL_PROJECTION);//设置当前矩阵为模型视图矩阵
glLoadIdentity();//重置当前指定的矩阵为单位矩阵
if(w<=h)
glOrtho(-nRange,nRange,-nRange*h/w,nRange*h/w,-nRange,nRange);
else
glOrtho(-nRange*w/h,nRange*w/h,-nRange,nRange,-nRange,nRange);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
voidSpecialKeys(intkey,intx,inty)
{
if(key==GLUT_KEY_UP)xRot-=5.0f;
if(key==GLUT_KEY_DOWN)xRot+=5.0f;
if(key==GLUT_KEY_LEFT)yRot-=5.0f;
if(key==GLUT_KEY_RIGHT)yRot+=5.0f;
if(xRot>360.0f)xRot=0.0f;
if(xRot<-1.0f)xRot=359.0f;
if(yRot>360.0f)yRot=0.0f;
if(yRot<-1.0f)yRot=359.0f;
glutPostRedisplay();//刷新窗口RendeScene()
}
第5章总结
本文通过主要利用VisualC++6.0来实现太阳系运行动画。
并对太阳系运行动画的实现进行简单的分析和介绍,通过本文以达到对Opengl的应用有一个较清晰的认识。
通过本次课程设计,让我学到了很多东西,熟练掌握了使用OpenGL提供的标准库函数,对Opengl有了进一步的了解,同时也让我学会了开发系统的结构理念及一些基本步骤。
不足之处就是有些东西我掌握的还不够牢固和不够深入,我以后还须加倍努力。
参考文献
[1]徐文鹏.计算机图形学[M].北京:
机械工业出版社
[2]唐荣锡,等.计算机图形学教程(修订版)[M].北京:
科学出版社
[3]银红霞,等.计算机图形学[M].北京:
中国水利水电出版社
[4]孔令德,计算机图形学实践教程(VisualC++版)清华大学出版社