2011年11月4日 星期五

9. 空間轉換 - OpenGL FAQ

9.001 我搞不定空間轉換啦。我可以去哪兒學習了解矩陣這東西?

基本矩陣數學與線性代數的詳細解說已經超出了本FAQ的範圍,這些內容美國的高中課程會教。如果你已經學過了,只是現在有點混淆 (這是老手也有的常見問題),去讀 Steve Baker 的矩陣觀念複習尤拉角度的文章

這兒有向量、矩陣、四元數運算的 Delphi 基本演示代碼

9.005 OpenGL 矩陣是 column-major 還是 row-major 呢?

以編程觀點來看,OpenGL矩陣是個陣列,有16個數值,四個基底向量依序地擺放在記憶體中。陣列的索引值編號為 1~16,其中位移分量(Translate Component) 佔據了16值的陣列的第13、14、15號元素,這些內容都寫在 OpenGL 2.1 規格書的 2.11.2 小節。

Column-major 與 Row-major 表示法純粹只是慣例上的差別。請注意,把向量乘在 column-major 矩陣的後頭,跟把向量乘在 row-major 矩陣的前頭,產生的結果完全相同。OpenGL規格書與OpenGL參考手冊雙雙採用了 column-major 表示法。只要夠明確,你用任何一種表示法都行。

但不幸地,規格書跟藍皮書中的 columr-major 格式造成了 OpenGL社群無止盡的混淆。因為 Column-major 表示法與一般編程人員預期的記憶體布局不相同。

9.010 OpenGL坐標系使用什麼長度單位呢?

短答案: 你想要單位是什麼就是什麼。

依據於你的幾何資料,應用程式可以把OpenGL座標單位視為毫米(millimeter) / 秒差距 (parsec) 或者任意更大或更小的長度單位,端賴哪個對你比較方便。

OpenGL也允許你指定不同的坐標系單位。比方說,你覺得這樣做比較方便,飛機控制以公分為單位,但是機身使用單位公尺,翱翔在單位是公里的世界天空中。OpenGL 的 ModelView 矩陣可以隨意縮放不同的座標系統,最後落於同一個眼空間座標中。

建立適切的投影矩陣跟ModelView矩陣是應用程式的責任,確保觀看者有適當的距離、視角、而且近平面跟遠平面都位於適當的範圍。比方說,一個展示微米尺度級的分子應用程式的鏡頭就不該放在10呎遠,且視角60度寬。

9.020 如何只對場景裡的單一物體作空間轉換,或者賦予每個物體它自己的空間轉換?

對此 OpenGL 特別提供了矩陣堆疊 (matrix stacks) 。在這個狀況下,我們採用 ModelView 矩陣堆疊。

典型的 OpenGL 應用程式會先呼叫 glMatrixMode(GL_MODELVIEW) 來設定矩陣模式,之後或許會呼叫 gluLookAt() 來載入視圖轉換。更多關於 gluLookAt() 的資訊

接著呢,將繪圖代碼的前後用 glPushMatrix() 以及 glPopMatrix() 兩個函數包夾起來,那場景中的每個物體的繪製,就只會套用他的自己的空間轉換了,例子如下:

glPushMatrix();
glRotatef(90., 1., 0., 0.);
gluCylinder(quad,1,1,2,36,12);
glPopMatrix();


上面的代碼繪製了一個以X軸為轉軸旋轉了90度的圓柱體。呼叫 glPopMatrix() 之後,ModelView矩陣會回復到呼叫 glPushMatrix() 之前的值。Similar call sequences can render subsequent objects in the scene.