2011年4月21日 星期四

2011年4月4日 星期一

[OpenGL] HW2 Solar System 的 Scene Graph 和 Pseudocode


這篇文章首先會提到太陽系系統的概念,利用這個基礎的概念
先規劃出Scene Graph,再寫出Psudocode
不會詳細敘述該如何在OpenGL實現(就是Full Code啦~)
如果有錯誤歡迎留言指正

Vincent Chen
太陽系(Solar System)
How The System Work ?
太陽 - 地球 - 月球系統,為了簡化問題,運行軌道皆為正圓
以太陽為原點來說 (在此不考慮宇宙擴張、太陽繞著銀河系中心)
  1. 太陽不會動
  2. 地球繞著太陽公轉
  3. 地球自轉
  4. 月球繞著地球公轉
Scene Graph
接著找出他們的Transformation的關係
進而畫出Scene Graph
於是Base on 前一個Section所提到的來繼續發展
  1. 太陽不會動:
    這會是T1,整個系統的原點(Root),接著T1會分出T2和Sun兩個節點
  2. 地球繞著太陽公轉
    T2: 負責地球公轉的部分,有Rotate和Translate
    由於這個node的pivote會在系統的原點,所以會先移動軌道半徑的距離,再旋轉
    但是以OpenGL(或是Computer Graphic)的執行方式
    所以步驟上會倒過來: R() -> T()
    後面Pseudocode的部分會再把過程詳細寫一次
  3. 地球自轉
    T3: 負責地球自轉的部分,當然只有Rotate囉
    由於這個node的pivote已經透過T2的T()移到離中心軌道半徑距離的軌道上了
    所以只需要旋轉就好
  4. 月球繞著地球公轉
    T4: 負責月球繞著地球公轉,方式和T2地球繞太陽轉一樣
    R() -> T()
  5. 在這裡T3和T4會是T2的sub-node(or children),因為在月球公轉的時候,不能被地球自轉所影響,因此T3和T4會是分開的,但都受T2影響(T2 將pivot移到軌道上)
接著來看圖 (若有錯誤,歡迎指正!!)

Pseudocode
接下來,Base on Scene Graph,寫出Pseudocode
這樣離撰寫出完整的OpenGL code也不遠了!!
根據Scene Graph,先列出三個物件的Matrix的運算過程:
  1. T1[Sun]
  2. T1[T2[T3[Earth]]]
  3. T1[T2[T4[Moon]]]
不過,根據上一個Section,T2和T4都可以在分解為R() -> T()
於是先把它們轉換一下 (之後的Psudocode還是會先以T2和T4代替,這個步驟只是讓要寫Code會比較清楚):
  1. T1[Sun]
  2. T1[T2R[T2T[T3[Earth]]]]
  3. T1[T2R[T2T[T4R[T4T[Moon]]]]]
(這三行覺得看了會頭暈趕快跳過,這裡只是要把過程再寫得更詳細)

接著會用到的就是gl library 的 Pop 和 Push Matrix的兩個Functions:
  1. glPushMatrix()
  2. glPopMatrix()
為了簡化Pseudocode
會以Push()和Pop()來代替,會比較清楚易讀
01 | T1();
02 | push();
03 |  Sun();
04 | pop();
05 | push();
06 |  T2();
07 |  push();
08 |   T3();
09 |   Earth();
10 |  pop();
11 |  push();
12 |   T4();
13 |   Moon();
14 |  pop();
15 | pop();
大致上是這樣,這裡我有作巢狀的測試,結果是work的
至於2~4行只有Sun的那個push-pop要不要加就見仁見智了,
嚴謹上來說,他屬於T1 node的另一個分支,加上去在code的維護上會比較清晰
在這之前有個錯誤的測試也拿出來檢討一下:
01 | T1();
02 | push();
03 |  Sun();
04 | pop();
05 | push();
06 |  T2();
07 |  T3();
08 |  Earth();
09 |  T4();
10 |  Moon();
11 | pop();
根據老師上課教的pop-push方式會變成這樣
那時候有和小柔討論這樣T3不會影響到只需要T4的Moon嗎?
測試結果是會的,有興趣想知道老師上課是怎麼說這段的
我筆記都有全部寫下來,可以跟我借去看看

Pull Back~ 回到正題
接著把Pseudocode再寫詳細一點,將T2和T4分解:

01 | T1();
02 | push();
03 |  Sun();
04 | pop();
05 | push();
06 |  T2R();
07 |  T2T();
08 |  push();
09 |   T3();
10 |   Earth();
11 |  pop();
12 |  push();
13 |   T4R();
14 |   T4T();
15 |   Moon();
16 |  pop();
17 | pop();
一整個就長這樣子,因為這個case是要做動畫
所以在Display List的結尾記得加glutSwapBuffers();
至於glFlush()的話在這裡就不用了,
因為glutSwapBuffers()本身就有take care glFlush()了 (Ref: glFinish and glFlush)

最後要給的建議就是,在做巢狀display list的時候
養成習慣縮排註解,在修改的時候會比較清楚,
而不會不小心修一修就修壞了
另外像這個case中,T2T4皆可再分解
有兩個Solution可以讓Code更加Well Organized
  1. 在分解後的的幾行Code頭尾用/* T2 Begin */、 /* T2 End */ 圍起來(以T2為例):
    (pserdocode)
    /* T2 Begin */
    T2R();
    T2T();
    /* T2 End */

  2. 或是另外寫一個T2/T4的call back Function,在dispaly list裡直接call back:
    (pseudocode)
    void transform2(void){
     R();
     T();
    }
到這裡就完成太陽系的動畫
在加上Enable Depth Test,當轉動到太陽後面就會被擋住
下一篇是如何切換鏡頭~

寫錯須更正有問題發問都歡迎在下面留言
我會很認真的回覆大家的~!

2011年4月3日 星期日

[LIFE] 家中食記 - 橙汁咖哩洋菇燴麵

最近常常煮東西
有時候會突發奇想的試試看一些沒做過的做法
--
今天的菜色是「橙汁咖哩洋菇燴麵」
做法其實很簡單,去楓康買個咖哩包來弄一弄就可以了
麵是家裡本來就有的麵條
柳橙汁是楓康特價的即期品,順便當餐後飲料
材料總覽,麵再家裡有就不拍了,哈哈

咖哩燴洋菇: $29 我不知道市價多少,不過我可以接受~

便宜原價20圓的柳橙汁 $79,其實我喝柳橙汁的速度還滿快的
所以即期品對我來說沒差~撿到的~ YA

==

接下來開始料理啦~
其實稱不上料理,懶人法一些現成的料包買一買加一加

  1. 拿一束麵先入水燙熟,水不用加太,讓麵慢慢熟
  2. 麵熟了之後把水瀝掉留下麵條 (其實這裡我應該是做錯了)
  3. 麵還是要留一點水,打開咖哩包倒進鍋子裡去,再倒適量的柳橙汁進去翻一翻就可以起鍋了
於是就成為熱騰騰的「橙汁咖哩洋菇燴麵」,搭配一杯柳橙汁

Close Look~ 料有馬鈴薯塊、紅蘿蔔、洋菇和素肉塊
洋菇真的很好吃~我喜歡吃洋菇!!

連哆啦A夢都笑開懷,就一定很好吃


這次做的時候有一些問題,所以在最後稍為檢討一下
  1. 應該要先把麵撈出來,倒到剩一點點水,先把咖哩包拆開放進去熱一下,再放麵下去:這次我是把麵留在鍋裡面慢慢把咖哩擠出來,結果麵就黏鍋底了,洗鍋子和倒麵出來會比較費力XD!!
  2. 希望下次能自己配咖裡,把燴料準備多一點比較有燴麵的感覺~~

這次是繼上次焗烤麵失敗之後再做一個比較特別的午餐,
圖呢,真的太失敗了就不拍所以也沒有圖可以放上來
鈺釤看過~可以去問他
不過真的太失敗了那個,哈哈哈

這次就還滿好吃滿正常的了,喔齁齁~