OpenGL變換順序的理解

該文轉自百度空間Rocky的避風港,原文鏈接:

http://hi.baidu.com/rocky_ly/item/21225b271a3f4d14087508c2

關於變換操作順序的問題

在OpenGL書籍當中,討論變換操作時都會涉及到函數調用的順序問題。大體有兩種說法:

一種是:

          正向順序;

              即是函數調用順序和預想的操作順序是相同的,變換結果同預想的結果相同。

          逆向順序:

              即是函數調用順序應該和預想的操作順序是相反的,這樣變換的結果才能和預想的結果相同。

看起來這兩種說法截然相反,實則不然

如何建立關聯而使這兩種觀點統一化呢?

如果將兩種觀點建立在不同的參考系下,分別討論其意義,然後再討論兩種參考系的關係,就可以將兩種觀點統一起來,其實在進行編程的過程中,運用那種觀點來指導編程都是可以的,看對那種觀點掌握的更好,使用得更得心應手吧!

一、首先討論第二種逆向順序的觀點,爲什麼呢?因爲絕大多數書籍資料都支持這個觀點,把OpenGL中的函數提供的矩陣運算視爲逆向於預想順序,而且這種觀點因爲其建立在最容易理解的座標系統下,卻看起來最不容易理解,所以先行討論之!

三維圖形即立體圖形,只要是立體的都應該對應存在三個維,即x,y,z三個座標軸,這三個座標軸構成的座標系成爲笛卡爾座標系。在三維圖形學研究中,笛卡爾座標系是重要的工具。

在OpenGL編程過程中,我們希望我們繪製的模型按照我們的規劃出現在視覺座標系的指定位置,恰好OpenGL系統中的笛卡爾座標系可以被我們利用來在其中安排模型。於是,一些變換的操作我們很自然的希望可以在這個座標系中看到直接的效果,即變換的過程和結果都是以這個座標系爲參照的。

無論是平移、旋轉還是縮放,我們都直接以視覺座標系作爲參考。

按照平移、旋轉和縮放這些操作的規定,我們在編寫程序時希望通過組合這些操作來把模型安排在座標系中的理想位置上。

通過平移,我們希望把模型挪動到指定座標;

通過旋轉,我們希望物體以某種角度放置;

通過縮放,我們希望物體以某種比例縮放成我們想要的大小。

可是,似乎我們還是不能直接按照我們的思維定勢來設計各種變換的組合來達到我們的目的。

OpenGL系統通過矩陣運算來實現變換操作,OpenGL爲我們維護了三個矩陣用來完成不同的變換操作,它們分別是:模型視圖矩陣,投影矩陣和紋理矩陣。

通過把空間中的點的座標(向量)拿來同相應的變換矩陣進行相乘操作,來實現變換操作,從而將向量轉換成同視覺座標相符的向量。拿模型視圖矩陣舉例:

現在,我們想對點v進行三次變換操作,分別是A,B,C。對應的變換矩陣分別是A,B,C。

我們的設計是:

                        變換A

                        變換B

                        變換C

                        繪製點v

對應的矩陣操作應該是:C(B(A*v))             矩陣操作是左乘的,即對應的變換矩陣要左乘頂點向量。

然而如果我們在程序中按照如下的順序編寫,結果將恰好相反

                (僞代碼)

                glMutiMatrix(A);

                glMutiMatrix(B);

                glMutiMatrix(C);

                glBegin(point);

                     glVertex(v);

                glEnd();

                glFlush();

上面代碼通過glMutiMatrix(A)函數將A操作對應的A矩陣乘以了當前矩陣。相應的其他矩陣也按照此規則乘以了當前矩陣,最後得到的當前矩陣是ABC,而後左乘頂點向量v得到ABCv爲變換後的頂點座標。變換效果上看,與程序中的調用順序相反。故此,如果希望按照某種順序對模型進行變換,需要以相反的順序調用相應的變換函數。

二、討論正向的觀點,其實無論正向或是逆向,無非是認爲函數的調用順序同變換過程的順序是相同還是相反,其實寫同樣的代碼當然不可能產生兩種截然相反的結果,自然同樣的代碼變換結果是完全相同的,那又怎麼會產生兩種相反的觀點呢。其實,這和思考的方式是有關係的。

先來說一下正向的觀點。與逆向的觀點不同,持正向的觀點的程序員認爲,在固定的世界座標系之外還有一個座標系,這個座標系是伴隨着模型的變換而不斷變換的,稱之爲模型座標系,即模型座標系在變換髮生之前始終保持原點與模型中心重合的狀態。而發生變換時,這個座標系成爲固定座標系,一個新的模型座標系,又跟隨着模型一起移動到了新的位置。

如果這樣考慮模型的變換,那麼無論是函數調用順序還是預想的變換順序都是同向的了。

舉例說明:

現在要在原點繪製一個正方體,然後先在x軸上,向正向平移5個單位,然後繞z軸逆時針旋轉45度。採用逆向觀點,需要在調用函數的時候,先調用旋轉函數後調用平移函數,這樣實際上就是先進行的平移矩陣操作,然後進行的旋轉變換矩陣的操作。這樣的情況下,我們認爲,正方體首先平移到x軸5的位置,然後繞z軸旋轉45度。採用正向觀點的時候,調用函數的順序一樣,不過是理解方法不同,先調用旋轉函數,正方體繞z軸旋轉45度,然後調用平移函數,這時,平移函數不再是在視覺座標系的x軸正向將旋轉後的立方體平移5個單位,而是在旋轉後的模型座標系x軸正向將立方體平移了5個單位。結果同逆向考慮時一樣。

可見,無論是認爲實際順序同調用順序是逆向的,還是認爲實際順序同調用函數的順序是同向的,其實最終結果都是一樣的,不過是理解的方式以及思考不同,採用的參照系不同而已。只要能夠記得清楚,無論那種理解方式都可以,條條大路通羅馬!

P.S. 在思考變換操作的過程中會出現很多令人頭疼的問題,有時候我們希望我們的變換操作可以以更直觀的視覺座標系(即固定在屏幕上的座標系)爲參照,但是逆向的思維有時候並不是我們的強項。其實平移操作對於座標系的依賴不那麼強,無論我們把平移理解爲是座標系平移還是模型本身的平移,其實看起來沒什麼差別,正如物體遠離鏡頭同鏡頭遠離物體看起來是完全一樣的。只不過當出現旋轉操作的時候會有一些問題出現。多次不同角度的旋轉,旋轉和平移的綜合變換,這些都會令問題顯得不那麼容易解決,至少不是我們想象的那麼直接就可以解決的。

就舉一個例子,如果想使用OpenGL做出類似CS遊戲那樣的視覺效果(指的是使用W,A,S,D鍵移動,用鼠標旋轉視角),就不那麼容易!網友們都在學的NeHe的OpenGL教程裏給出的漫遊代碼,其實也沒有實現這個功能。編譯運行NeHe給出的代碼,我們會發現我們只能朝一個方向行動,而不是始終朝着我們面對着的方向向前。就是說,旋轉看起來只好像是坐在火車上的我們時不時看看窗外,火車卻一直向前。

這個問題我一直在研究,剛纔下載了唐明理的教程,希望可以得到一些提示!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章