基于opengl的3D天体运动模型设计方案 精品.docx
《基于opengl的3D天体运动模型设计方案 精品.docx》由会员分享,可在线阅读,更多相关《基于opengl的3D天体运动模型设计方案 精品.docx(14页珍藏版)》请在冰豆网上搜索。
![基于opengl的3D天体运动模型设计方案 精品.docx](https://file1.bdocx.com/fileroot1/2023-4/2/7e0aa17e-ab9c-4132-9e9e-884bf931b128/7e0aa17e-ab9c-4132-9e9e-884bf931b1281.gif)
基于opengl的3D天体运动模型设计方案精品
基于opengl的3D天体运动模型
设计方案
学生:
____?
?
?
___
学号:
************
指导老师:
___?
?
?
___
一、背景简介
1.1设计概述
本3D建模设计运用Win32程序设计的基本原理,基于OpenGL接口函数,以MicrosoftVisualStudio2008为开发工具,以C++语言为开发语言,设计了一个星空背景下的太阳—地球—月球公转自转运动模型,模拟了太阳的光照效果,并实现了可以加速和减速地球和月球的自转、公转速度,而且还可以调整视图的远近和方位,方便各方面的观察。
1.2OpenGL的基本特点
OpenGL即开放图形库(OpenGraphicsLibrary),是一个三维的计算机图形和模型库。
OpenGL作为一个性能优越的图形应用程序设计接口,适用于广泛的计算机环境。
从个人计算机到工作站和超级计算机,OpenGL都能实现高性能的三维图形功能。
OpenGL是一个与硬件图形发生器的软件接口,它包括了100多个图形操作函数,开发者可以利用这些函数来构造景物模型、进行三维图形交互软件的开发。
正如上一章所述,OpenGL是一个高性能的图形开发软件包。
OpenGL支持网络,在网络系统中用户可以在不同的图形终端上运行程序显示图形。
OpenGL作为一个与硬件独立的图形接口,它不提供与硬件密切相关的设备操作函数,同时,它也不提供描述类似于飞机、汽车、分子形状等复杂形体的图形操作函数。
用户必须从点、线、面等最基本的图形单元开始构造自己的三维模型。
当然,像OpenInventor那样更高一级的基于OpenGL的三维图形建模开发软件包将提供方便的工具。
因此OpenGL的图形操作函数十分基本、灵活。
它具有如下特点。
(1)图形质量好、性能高。
无论是三维动画、CAD,还是视觉模拟、可视化计算等,都利用了OpenGL高图形质量、高性能的特点。
这个特点使得程序开发者在广播、CAD/CAM/CAE、娱乐、医学图像和虚拟现实等领域中创造和显示出难以想象的2D和3D图形。
(2)行业标准。
OpenGLARB作为独立的联合委员会,制定规范文档(Specification)。
随着业内厂商的支持,OpenGL成为唯一真正开放的、独立于供应商的、跨平台的标准。
(3)稳定性。
OpenGL能够在各种平台上执行,而且OpenGL高版本兼容低版本,保证了已经开发的应用程序不会失效。
(4)可移植性和可靠性。
利用OpenGL技术开发的应用图形软件与硬件无关,只要硬件支持OpenGLAPI标准就行了,也就是说,OpenGL应用程序可以运行在支持OpenGLAPI标准的任何硬件上。
但是,硬件是不断变化的,OpenGL如何保持可移植性呢?
OpenGL扩展(OpenGLExtension)正是为这一目的而设计的。
厂商只要提供OpenGL扩展,就可以轻松实现硬件特有的功能。
利用OpenGL扩展,OpenGL实现者(OpenGLImplementer)也可以添加新的处理算法。
(5)可扩展性。
OpenGL是低级的图形API,它具有充分的可扩展性。
许多OpenGL开发商在OpenGL核心技术规范的基础上,增强了许多图形绘制功能,从而使OpenGL能紧跟最新硬件发展和计算机图形绘制算法的发展。
对于硬件特性的升级可以体现在OpenGL扩展机制以及OpenGLAPI中,一个成功的OpenGL扩展会被融入在未来的OpenGL版本之中。
通过这种方法,程序开发者和硬件厂商能够在正常的产品周期中组合出新的产品。
(6)可适应性。
基于OpenGLAPI的图形应用程序可以运行在许多系统上,包括各种用户电子设备、PC、工作站以及超级计算机。
由此,OpenGL应用程序可以适应开发人员选择的各种目标平台。
(7)易用性。
OpenGL具有良好的结构、直观的设计和逻辑命令。
与其他图形程序包相比,OpenGL只有很少的代码,因此执行速度快。
另外,OpenGL封装了有关基本硬件的信息,使得开发者无须针对具体的硬件特征进行设计。
二、概要设计
2.1程序流程
图1程序运行流程图
本节将对程序具体的实现进行说明。
开始之前要引用程序要求的头文件:
#include//Windows的头文件
#include//OpenGL32库的头文件
#include//Glu32库的头文件
#include//Glaux库的头文件
#include//标准输入/输出库的头文件
#include//math函数库
要加入程序要求的库到链接器中:
#pragmacomment(lib,"opengl32.lib")//链接时查找OpenGL32.lib
#pragmacomment(lib,"glu32.lib")//链接时查找glu32.lib
#pragmacomment(lib,"glaux.lib")//链接时查找glaux.lib
2.1.1注册窗口RegisterWindowClass(Application*application)
(1)定义窗口类:
WNDCLASSEXwindowClass;//窗口类;
(2)清空内存:
ZeroMemory(&windowClass,sizeof(WNDCLASSEX));//清空内存;
(3)设置窗口类的属性;
窗口类的大小:
windowClass.cbSize=sizeof(WNDCLASSEX);//窗口类的大小;
重绘:
windowClass.style=CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
//在窗口移动,改变大小的时候重绘;
绑定处理消息的函数:
windowClass.lpfnWndProc=(WNDPROC)(WindowProc);//用WindowProc函数处理消息;
设置实例:
windowClass.hInstance=application->hInstance;//设置实例
画刷颜色:
windowClass.hbrBackground=(HBRUSH)(COLOR_APPWORKSPACE);//类背景的画刷颜色;
鼠标指针:
windowClass.hCursor=LoadCursor(NULL,IDC_ARROW);//载入鼠标指针;
设置类名:
windowClass.lpszClassName=application->className;//设置应用程序的类名;
(4)如果注册失败,返回失败消息。
2.1.2创建窗口CreateWindowGL(GL_Window*window)
(1)设置窗口样式:
DWORDwindowStyle=WS_OVERLAPPEDWINDOW;
设置窗口扩展样式:
DWORDwindowExtendedStyle=WS_EX_APPWINDOW;
(2)设置像素格式描述符:
PIXELFORMATDESCRIPTORpfd;
(3)定义窗口大小:
RECTwindowRect={0,0,window->init.width,window->init.height};
(4)保存像素格式:
GLuintPixelFormat;
(5)开始创建OpenGL窗口,取得程序类名,传入应用程序实例:
window->hWnd=CreateWindowEx(windowExtendedStyle,//窗口扩展样式
window->init.application->className,//应用程序类名
window->init.title,//窗口标题
windowStyle,//窗口样式
0,0,//窗口的XY坐标位置
windowRect.right-windowRect.left,//窗口宽度
windowRect.bottom-windowRect.top,//窗口高度
HWND_DESKTOP,//父窗口为桌面
0,//无菜单
window->init.application->hInstance,//传入应用程序实例
window);
(6)如果创建失败,返回失败消息;//以下代码略
(7)如果未得到设备描述符,销毁窗口,句柄清零,返回失败消息;
(8)如果选择兼容的像素格式失败,释放设备描述符,设备描述符清零,销毁窗口,句柄清零,返回失败消息;
(9)如果未获得绘制描述表,释放设备描述表,设备描述表清零,销毁窗口,句柄清零,返回失败消息;
(10)显示窗口,清空键盘缓冲区。
2.1.3初始化OpenGLInitialize(GL_Window*window,Keys*keys)
(1)设置全局变量;
(2)建立时钟
(3)初始化绘制场景
清屏:
glClearColor(0.0f,0.0f,0.0f,0.5f);//清屏为黑色
设置深度缓存:
glClearDepth(1.0f);
深度测试:
glDepthFunc(GL_LEQUAL);//选择深度测试方式
glEnable(GL_DEPTH_TEST);//开启深度测试
阴暗处理:
glShadeModel(GL_SMOOTH);//阴暗处理采用平滑方式
透视计算:
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);//最精细的透视计算
2D纹理:
LoadTextureGL()//载入纹理
glEnable(GL_TEXTURE_2D);//开启D纹理映射
设置环境光:
glLightfv(GL_LIGHT1,GL_AMBIENT,LightAmbient);
设置漫反射光:
glLightfv(GL_LIGHT1,GL_DIFFUSE,LightDiffuse);
建立一个曲面对象指针:
quadric=gluNewQuadric();
建立纹理坐标:
gluQuadricTexture(quadric,GLU_TRUE);
用面填充:
gluQuadricDrawStyle(quadric,GLU_FILL);
打开光照:
glEnable(GL_LIGHTING);
开光源1:
glEnable(GL_LIGHT1);
设置雾的各种参数:
glFogi(GL_FOG_MODE,GL_LINEAR);//雾的类型
glFogfv(GL_FOG_COLOR,fogColor);//雾的颜色
glFogf(GL_FOG_DENSITY,0.6f);//雾的浓度
glHint(GL_FOG_HINT,GL_DONT_CARE);//雾的渲染方式
glFogf(GL_FOG_START,1.0f);//雾的开始深度
glFogf(GL_FOG_END,30.0f);//雾的终止深度
glEnable(GL_FOG);//启用雾
用于显示提示文字:
BuildFontGL();
2.1.4处理事件WindowProc(HWNDhWnd,UINTuMsg,WPARAMwParam,LPARAMlParam)
(1)取得窗口信息:
GL_Window*window=(GL_Window*)(GetWindowLong(hWnd,GWL_USERDATA));
(2)取得Window的消息并做相应处理:
switch(uMsg)//取得Window的消息
{
case……
default:
break;
}
returnDefWindowProc(hWnd,uMsg,wParam,lParam);//将本程序不处理的消息传给DefWindowProc
}
(3)截取系统命令:
caseWM_SYSCOMMAND:
(4)创建窗口:
caseWM_CREATE:
(5)TIMER事件:
caseWM_TIMER:
(6)PAINT消息处理,在此处绘图:
caseWM_PAINT:
(7)关闭窗口:
caseWM_CLOSE:
(8)窗口大小变化:
caseWM_SIZE:
(9)按键按下时更新键盘缓冲:
caseWM_KEYDOWN:
(10)按键松开时更新键盘缓冲:
caseWM_KEYUP:
(11)开关全屏模式:
caseWM_TOGGLEFULLSCREEN:
(12)将本程序不处理的消息传给DefWindowProc(hWnd,uMsg,wParam,lParam);
2.1.5扫尾处理Deinitialize(void)
(1)释放时钟KillTimer(OGL_window->hWnd,TIMER1);
(2)删除字体KillFontGL();
2.1.6销毁窗口,注销窗口类
DestroyWindowGL(&window);//销毁窗口
UnregisterClass(application.className,application.hInstance);//注销窗口类
2.2关键算法
2.2.1绘制模型DrawSceneGL(void)
voidDrawSceneGL(void)//绘制场景
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清除颜色和深度缓存
glLoadIdentity();//重置当前矩阵
//设置观察视点
rad=(float)(PI*s_angle/180.0f);
centerx=(float)(eyex+100*cos(rad));
centerz=(float)(eyez+100*sin(rad));
gluLookAt(eyex,eyey,eyez,
centerx,centery,centerz,
upx,upy,upz);
//在此处添加代码进行绘制:
//在屏幕上显示字体
glPushMatrix();
glTranslatef(-2.0,0.0,-4.0);//移入屏幕.0f
glDisable(GL_LIGHTING);//禁用光照
glDisable(GL_TEXTURE_2D);//禁用纹理
glColor3f(1.0f,1.0f,1.0f);
glRasterPos2f(0.7f,1.7f);
glPrint("3DEarthAndMoonModel--------PressUp/Down/Left/RightButtontomovethegraph");
glColor3f(1.0f,1.0f,1.0f);
glRasterPos2f(0.7f,1.5f);
glPrint("'space'--speedup");
glRasterPos2f(0.7f,1.3f);
glPrint("'Delete'--Backwardshifting");
glColor3f(1.0f,1.0f,1.0f);
glRasterPos2f(0.7f,1.1f);
glPrint("3DEarthAndMoonModel--------PressF1buttontotoggleFullScreen,Esctoexit");
glEnable(GL_LIGHTING);//启用光照
glEnable(GL_TEXTURE_2D);//启用纹理
glPopMatrix();
glTranslatef(0.0f,0.0f,-5.0f);//将坐标系移入屏幕.0f
glRotatef(10,1.0f,0.0f,0.0f);//将坐标系绕x轴旋转度
glEnable(GL_LIGHT0);//打开光源
/******************************绘制星空背景********************************/
glPushMatrix();//当前模型矩阵入栈
glTranslatef(-10.0f,3.0f,0.0f);
glRotatef(angle_Z,0.0f,0.0f,1.0f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,texture[1]);//绑定星空纹理
glBegin(GL_QUADS);
glNormal3f(0.0f,0.0f,1.0f);
glTexCoord2f(0.0f,0.0f);glVertex3f(-20.0f,-20.0f,-5.0f);
glTexCoord2f(6.0f,0.0f);glVertex3f(20.0f,-20.0f,-5.0f);
glTexCoord2f(6.0f,6.0f);glVertex3f(20.0f,20.0f,-5.0f);
glTexCoord2f(0.0f,6.0f);glVertex3f(-20.0f,20.0f,-5.0f);
glEnd();
glPopMatrix();//当前模型矩阵出栈
/********************************绘制太阳**********************************/
glBindTexture(GL_TEXTURE_2D,texture[2]);//绑定纹理
glEnable(GL_BLEND);//开启混合
glDisable(GL_DEPTH_TEST);//关闭深度测试
//绘制太阳光晕
glDisable(GL_LIGHTING);//关闭光照
glBlendFunc(GL_SRC_ALPHA,GL_ONE);//基于源象素alpha通道值的半透明混合函数
glColor4f(1.0f,1.0f,1.0f,0.4f);//设置RGBA值
glBegin(GL_QUADS);
glNormal3f(0.0f,0.0f,1.0f);
glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f,0.0f);
glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,-1.0f,0.0f);
glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,0.0f);
glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,1.0f,0.0f);
glEnd();
glDisable(GL_BLEND);//关闭混合
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);//关闭纹理
glEnable(GL_LIGHTING);//开启光照
glLightfv(GL_LIGHT1,GL_POSITION,LightPosition);//设置光源的当前位置
gluSphere(quadric,0.3f,32,32);//绘制太阳球体
/********************************绘制地球*********************************/
glDisable(GL_LIGHT0);
glRotatef(ep_Angle,0.0f,1.0f,0.0f);//将坐标系绕Y轴旋转ep_Angle角度控制地球公转
glRotatef(-90.0f,1.0f,0.0f,0.0f);//将坐标系绕X轴旋转-90度
glEnable(GL_TEXTURE_2D);//开启纹理
glTranslatef(2.0f,0.0f,0.0f);//将坐标系右移.0f
glBindTexture(GL_TEXTURE_2D,texture[0]);//绑定纹理
glPushMatrix();//当前模型视图矩阵入栈
glRotatef(es_Angle,0.0f,0.0f,1.0f);//将坐标系绕Z轴旋转es_Angle角度控制地球自转
gluSphere(quadric,0.2f,32,32);//地球球体
glPopMatrix();//当前模型视图矩阵出栈
/*******************************绘制月亮*********************************/
glRotatef(mp_Angle,0.0f,0.0f,1.0f);//将坐标系绕Z轴旋转mp_Angle角度控制月亮公转
glBindTexture(GL_TEXTURE_2D,texture[3]);//绑定纹理
glTranslatef(0.5f,0.0f,0.0f);//右移.5f
glRotatef(ms_Angle,0.0f,0.0f,1.0f);//将坐标系绕Z轴旋转ms_Angle角度控制月亮自转
gluSphere(quadric,0.05,32,32);//绘制月亮星体
//变量更新控制模型活动
ep_Angle+=ep_velocity;
es_Angle+=es_velocity;
mp_Angle+=mp_velocity;
ms_Angle+=ms_velocity;
angle_Z+=0.1f;
glFlush();//刷新GL命令队列
};
2.2.2切换视角