版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
OpenGL高级编程
&
可视化系统开发广东工业大学图学与数字媒体系罗立宏第六章星空的模拟6.2编程实例二
6.2.1程序说明模拟太阳系中各大星体的运动,对太阳系进行可视化6.2.2使用到的技术绘图坐标的变换
注意glPushMatrix,glPopMatrix,glTranslate,glRotate的使用纹理的应用
二次曲面纹理的应用
raw格式纹理的使用
6.2.3程序阅读本程序使用了第二章做的OpenGL单文档模板,在此基础上开发而成3.2.2.1绘图部分代码绘图的程序绘图的工作都是在视图类的OnDraw()函数中开始的。因此,可以从OnDraw开始入手,找出绘图相关的函数:◆CMySolarsysView::RenderScene()◆
CMySolarsysView::DrawSun()◆
CMySolarsysView::DrawAllOrbits()◆
CMySolarsysView::DrawPlanets()◆
CMySolarsysView::DrawComet()(1)CMyTerrain1View::RenderScene()//////////////////////////////////////////////////////////// 场景绘制与渲染//////////////////////////////////////////////////////////BOOLCMySolarsysView::RenderScene(){ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glTranslatef(globalPosition.fPosX,0.0,0.0); glTranslatef(0.0,globalPosition.fPosY,0.0); LightPosition[0]=LightPosition[0]+globalPosition.fPosX;//第一个光源LightPosition[1]=LightPosition[1]+globalPosition.fPosX; LightPosition2[0]=LightPosition2[0]+globalPosition.fPosX;//第二个光LightPosition2[1]=LightPosition2[1]+globalPosition.fPosX; glLightfv(GL_LIGHT1,GL_POSITION,LightPosition); glLightfv(GL_LIGHT2,GL_POSITION,LightPosition2);
globalPosition.fPosX =0; globalPosition.fPosY =0; DrawSun(); //绘制太阳
DrawAllOrbits();
//绘制所有轨道
DrawPlanets();
//绘制所有行星
DrawComet();//绘制彗星 ::SwapBuffers(m_pDC->GetSafeHdc()); //交互缓冲区
returnTRUE;}(2)CMySolarsysView::DrawSun()//绘制太阳voidCMySolarsysView::DrawSun(){ glPushMatrix(); glutSolidSphere(0.05,10,10); glPopMatrix();}(3)CMySolarsysView::DrawAllOrbits()//绘制行星轨道voidCMySolarsysView::DrawAllOrbits(){ DrawOrbit(mercury); DrawOrbit(venus); DrawOrbit(earth); DrawOrbit(mars); DrawOrbit(jupiter); DrawOrbit(saturn); DrawOrbit(uranus); DrawOrbit(neptune); DrawOrbit(pluto);}(4)voidCMySolarsysView::DrawOrbit()//绘制行星轨道voidCMySolarsysView::DrawOrbit(Planetplanet){ glDisable(GL_LIGHTING); glColor3f(0.7,0.7,0.7);
glBegin(GL_LINE_LOOP); for(inti=0;i<360;i++) { glVertex3f(cos(DEG2RAD(i))*planet.posZ,0,sin(DEG2RAD(i))*planet.posZ); } glEnd(); glEnable(GL_LIGHTING);}(5)CMySolarsysView::DrawPlanets()//绘制9大行星voidCMySolarsysView::DrawPlanets(){ glEnable(GL_TEXTURE_2D);
DrawPlanet(mercury); DrawPlanet(venus); DrawPlanet(earth); DrawPlanet(mars); DrawPlanet(jupiter); DrawPlanet(saturn); DrawPlanet(uranus); DrawPlanet(neptune); DrawPlanet(pluto); glDisable(GL_TEXTURE_2D);}(6)CMySolarsysView::DrawPlanet()//绘制一个行星voidCMySolarsysView::DrawPlanet(Planetplanet){ glPushMatrix(); glRotatef(planet.SolarAngle,0,-1,0); glTranslatef(planet.posX,planet.posY,planet.posZ); glRotatef(planet.OwnAxisAngle,0,-1,0); glRotatef(90.0,1.0,0.0,0.0);
glBindTexture(GL_TEXTURE_2D,texture_id[planet.TextureID]); GLUquadricObj*q=gluNewQuadric();//新建一个二次曲面对象
gluQuadricDrawStyle(q,GLU_FILL);
//绘图风格
gluQuadricNormals(q,GLU_SMOOTH);//指定法线方式gluQuadricTexture(q,GL_TRUE);
//设置使用纹理
gluSphere(q,planet.size,planet.sections,planet.sections);//绘制球体
gluDeleteQuadric(q);
//删除二次曲面对象
glPopMatrix();}绘图坐标系变换过程:开始绘图坐标系在世界坐标系的原点,图中红色为x,绿色为y,蓝色为z0//公转。绕y轴(绿色)旋转,如45°
glRotatef(planet.SolarAngle,0,-1,0);12//沿z轴(蓝色)移动,如(0,0,5)glTranslatef(planet.posX,planet.posY,planet.posZ);3//自转。绕y轴(绿色)旋转,如30°
glRotatef(planet.SolarAngle,0,-1,0);4//把z轴转为向上,使行星北极朝上。绕x轴转90°glRotatef(90.0,1.0,0.0,0.0);5//在当前绘图坐标系绘制球体(行星)gluSphere(q,planet.size,planet.sections,planet.sections);(7)CMySolarsysView::DrawComet()//绘制彗星voidCMySolarsysView::DrawComet(){ glPushMatrix(); glRotatef(iCometAngle,0,0,1); glTranslatef(1,0,0); glutSolidSphere(0.02,20,20); glPopMatrix();}3.2.2.2动画的实现动画的实现一般靠OnTimer()改变绘图参数,然后刷新屏幕。重新画图时由于数据不一样,就画出了与刚才不一样的图,就产生了动画。OnTimer()中发现改变参数的函数是:◆CMySolarsysView::rotate()(1)CMySolarsysView::rotate()voidCMySolarsysView::rotate(){ if(globalPosition.bRotationOn) { //comet iCometAngle+=2; if(iCometAngle>=360) {
iCometAngle-=360; } //solarrotation mercury.SolarAngle+=1.6*ROTATION_SPEED; if(mercury.SolarAngle>=360){mercury.SolarAngle-=360;}
……
//金星至海王星省略
……
pluto.SolarAngle+=0.01*ROTATION_SPEED; if(pluto.SolarAngle>=360) {pluto.SolarAngle-=360;} //axisrotation mercury.OwnAxisAngle+=0.1; if(mercury.OwnAxisAngle>=360) {mercury.OwnAxisAngle-=360;}
……
//金星至海王星省略 ……
pluto.OwnAxisAngle+=3; if(pluto.OwnAxisAngle>=360) {pluto.OwnAxisAngle-=360;} }}3.2.2.3初始化代码查看一下程序常用于初始化的地方(如App类的InitInstance()、视图类的OnCreate()等)有没有额外的初始化代码,发现有:◆CMySolarsysView::Init()◆CMySolarsysView::InitPlanets()
这些函数应包括了各星体数据的初始化(1)CMySolarsysView::Init()voidCMySolarsysView::Init(void){ glLightfv(GL_LIGHT1,GL_AMBIENT,LightAmbient); glLightfv(GL_LIGHT1,GL_DIFFUSE,LightDiffuse); glLightfv(GL_LIGHT1,GL_POSITION,LightPosition); glEnable(GL_LIGHT1);//启用1号光源
glLightfv(GL_LIGHT2,GL_AMBIENT,LightAmbient2); glLightfv(GL_LIGHT2,GL_DIFFUSE,LightDiffuse2); glLightfv(GL_LIGHT2,GL_POSITION,LightPosition2); glEnable(GL_LIGHT2);//启用2号光源
glClearColor(0,0,0,0);//设置清屏颜色
glShadeModel(GL_SMOOTH);//设置面着色模式为平滑模式
glEnable(GL_DEPTH_TEST);//启用深度测试
glEnable(GL_LIGHTING);
//启用光照功能
glEnable(GL_CULL_FACE);//启用无用面剔除功能
m_Textures.LoadTextures(texture_id,MAX_NO_TEXTURES); globalPosition.fPosX=0; globalPosition.fPosY=0; globalPosition.iDegreesX=20;
globalPosition.iDegreesY=25; globalPosition.bRotationOn=true;//等于true才不断旋转 //旋转绘图坐标系,让用户看到太阳系的全貌。配合OnSize()中//的glTranslatef(0.0,0.0,-5.0)就能得到观察的效果
glRotatef(globalPosition.iDegreesX,0.0,1.0,0.0); glRotatef(globalPosition.iDegreesY,1.0,0.0,0.0);}观察位置的设置0图中为绘图坐标系1//绘图坐标系绕y轴旋转20°glRotatef(globalPosition.iDegreesX,0.0,1.0,0.0);2//绘图坐标系绕x轴旋转25°glRotatef(globalPosition.iDegreesY,1.0,0.0,0.0);3//在OnDraw()中画了整个太阳系4//把原始的观察坐标系画出来,它是左手系5//在OnSize中有以下代码,把观察坐标系向z负向移动了5glMatrixMode(GL_PROJECTION);glTranslatef(0.0,0.0,-5.0);6//把视点移至观察坐标系来看,发现看的东西是这样的:(2)CTextures::LoadTextures()//加载9个行星的纹理voidCTextures::LoadTextures(GLuint*texture_id,intMaxNrOfTextures){ glPixelStorei(GL_UNPACK_ALIGNMENT,1);//对齐像素字节glGenTextures(MaxNrOfTextures,texture_id);//生成9个纹理对象
//加载水星纹理
glBindTexture(GL_TEXTURE_2D,texture_id[0]);//纹理准备加载到0号
//以下load_texture()函数封装了加载raw图像的方法,以后需要使用raw//格式图像时大家可直接使用
if(load_texture("mercury.raw",640,320,3,GL_RGB,GL_NEAREST)) { MessageBox(NULL,TEXTURE_LOAD_ERROR,"Error",MB_OK); exit(1); }
…………
glBindTexture(GL_TEXTURE_2D,texture_id[8]); if(load_texture("pluto.raw",640,320,3,GL_RGB,GL_NEAREST)) { MessageBox(NULL,TEXTURE_LOAD_ERROR,"Error",MB_OK); exit(1); }}(3)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论