一、功能
基本功能
三个球体、一个表示太阳、一个表示地球、一个表示月亮;地球不停地绕太阳旋转,月亮绕地球旋转,期间它们三者都发生自转。
扩展功能
地球有两个月亮,画上轨道线,使轨道倾斜,放缩效果
自己完成的效果图
二、思路
基本功能的实现
首先搭好程序框架:
1、 设置显示模式
2、 初始化窗口
3、 创建窗口
4、 设置一系列回调函数
5、 启动主循环
框架设置完毕后,针对display()函数进行编写,关于display函数的编写,即是整个基本功能的绘制,本人刚开始编写的时候,对全局变换和局部变换理解不够透彻,因此我在编写过程中一直采用全局变换的思路,并没有采用的局部变换的思路。
1、创建三个球体,分别为太阳、地球和月亮,并移至对应位置
2、使地球绕太阳转起来
我假设太阳为默认原点位置,地球将在xoz平面围绕太阳进行旋转,绕其旋转,起初,我思考地球位置的改变即为其x,z值的改变,对于一个圆,其x,z值采用极坐标的形式来表达,
earthPosX=earthBound*cos(curTheta*pi);//求地球x
earthPosZ=earthBound*sin(curTheta*pi);//求地球z
因此只要改变坐标,就能使求发生转动,于是通过编写定义定时器回调函数void myTimerFunc(int value)
,在函数中不断增加theda的值,就可以使圆不断转动。
3、使月亮绕地球转起来
月亮围绕地球转,由于我始终是从全局坐标的角度考虑了这个问题,
因此,月亮的坐标也要转换为全局坐标值,假设月球绕地球转动角度为far,则其x,z采用极坐标的形式来表达为
monthPosX = earthPosX + monthBound* cos(curFar * pi);//求月球x
monthPosZ = earthPosZ + monthBound* sin(curFar * pi);//求月球y
同样使其转动,在void myTimerFunc(int value)
中,不断增加far的值即可,具体效果见SunEarthMonth.gif。而其中两个球体的自转,则设定一个自转角度curSpeed来控制,而其值的变化也在定时器回调函数中完成。
扩展功能的实现
1、(扩展功能)实现地球上有两个月亮
对于这个效果,很容易实现,此处简化,只设置月亮B和月亮A在同一平面内,并且两者速度相等,只需要保持轨道半径相等,位置不同即可,而如何做到这一点,仍然可以从圆出发,这里我做的是将另一个月亮和此月亮形成对称,因此使月亮B绕地球的角度比月亮A多180度即可,坐标值如下:
month2PosX = earthPosX + monthBound * cos(curFar * pi+pi);//求月球2x
month2PosZ = earthPosZ + monthBound * sin(curFar * pi+pi);//求月球2z
具体实现效果见下图
2、(扩展功能)画上轨道线
实现地球绕太阳的轨道线描绘的就是以太阳为中心,以地球到太阳的距离为半径画的圆,而在OpenGL中,绘画基本图元没有圆,因此我思考通过不断的画直线来逼近圆,因此使用GL_LINE_LOOP来绘制,线段我一共绘制了7200次。同理,月亮绕地球的轨道线,就是以地球为中心,以月亮到地球的距离为半径画的圆。效果图可见下图:
3、(扩展功能)让轨道倾斜
首先我实现的是地球绕太阳的轨道倾斜,要做的效果实际上就是使xoy平面发生旋转,此处我是使其绕z轴先进行旋转,后续步骤不变即可。需要注意的是此处轨道倾斜,相应的地球和月亮也要随着倾斜。
倾斜代码为:
glRotatef(earthOrbitAngle, 0.0f, 0.0f, 1.0f);//地球轨道倾斜earthOrbitAngle度,轨道沿着Z轴逆时针旋转
对于月亮绕地球的轨道倾斜,其效果就是在地球绕太阳的轨道平面上,再旋转即可,此处我假定月亮绕地球的轨道平面绕地球到月亮的轴线进行旋转。因此先将其变换到地球绕太阳的轨道平面上后,再进行旋转一定角度即可实现。效果图详见:
4、(扩展功能)实现按键控制轨道倾斜与整体图形放大缩小功能
对于轨道倾斜,通过键盘控制函数改变其角度参数值(earthOrbitAngle、monthOrbitAngle)即可,对于放大缩小,通过控制G_fDistance值即可。效果图详见SunEarthMonth4.gif: