一、功能
基本功能
三個球體、一個表示太陽、一個表示地球、一個表示月亮;地球不停地繞太陽旋轉,月亮繞地球旋轉,期間它們三者都發生自轉。
擴展功能
地球有兩個月亮,畫上軌道線,使軌道傾斜,放縮效果
自己完成的效果圖
二、思路
基本功能的實現
首先搭好程序框架:
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: