「有些自閉症兒童偏愛旋轉的東西,不管是玻璃瓶或銅板,他們常會拿來轉;」
前言
這個寒假,由於專題剛剛結束,但留下了一些圖學設計概念的部分尚未完成,甚至是完成了一半就有成品交差了。為此感到有些可惜,因此藉由這個長假,對這一部分稍稍做了一點研究,希望在此做些筆記,並且分享出來供大家參考。
建立 3D 空間的第一步 : 確立你的座標系
許多人覺得踏入 3D 圖形程式設計很困難,因為他們不知道怎麼在一個2D的顯示器上,去表達一個3D的模型。事實上,目前的所有PC顯示器,都是一個2D的實體,而我們如何在一個2D的顯示器上,去顯示一個3D的圖形,就是3D圖學引擎設計實作所要面臨的主要問題。
上面說到的這個問題似乎很複雜,但是並不難辦到。目前達成這個方法的座標系有「左手座標系」和「右手座標系」,而其中又以左手座標系受到歡迎。
【圖1】左手座標系
以往2D圖形只有兩個軸,分別是X軸和Y軸。而這兩個軸只要和螢幕上的兩個軸相符合即可,不需特別花心思去實做。
而要作出3D圖形,則是要思考如何在螢幕上表達「並不存在的第三個軸 - Z軸」
以上圖左手座標系的處理方式,即是將 X 軸 或 Y軸 旋轉45度,就可以得到 Z 軸。
(如果選擇Y軸,是將其向右旋轉45度得到Z軸;如果選擇X軸,則是將其向左旋轉45度得到Z軸。)
有了 Z 軸之後,我們就好辦事了。
【圖2】針對 (1,0,0) (0,1,0) (0,0,1) 三個向量的繪圖
當然,如果你的顯示器本身就是三維的,那麼就不必煩惱這個問題了。
邏輯座標系 與 實體坐標
如果我們依據螢幕的實體坐標,會得到上面那個樣子
沒有辦法實做出負數座標
因此我們要把各點 x,y,z 各加上一定的數值
才能做到
例如我們想要讓 x 顯示出 大於 -10 的點
那麼 我們就要針對 所有圖形上的 x點 全部加上 10
用這個方法做出 邏輯座標 如此才有辦法顯示出負數點
從上圖我們就可以了解 邏輯的座標 和 實體的座標(即硬體實際上的座標)的差別
唯有用上負數座標 才有可能支援到圖形空間(Space)的八個象限
如上圖所示
繪製線條的兩種方式
在圖學上,要繪製一個圖形無非是從 點 -> 線 -> 面 這個方向依序討論
Vertex -> Edge -> Plane
方才我們討論座標系,乃是決定3D圖形的「點」
而兩點可以決定一條「線」
而決定一條線的方式,主要有兩種,而各有利弊
以下分述之
第一種:海龜繪圖法
海龜繪圖法顧名思義,就是模擬一隻拿著畫筆的海龜
走過的地方就會留下痕跡,而那痕跡就是我們要的線條
實做方法是
先決定海龜走路的起點
然後決定海龜下一個位置要走到哪裡
例如海龜原本在 (0,0)
指定他走到 (0,1) 就可以決定一條線 , 即是 (0,0) - (0,1)
而這個方法的特色是
只要每指定多一點
就可以多決定一條線
例如 原點在 (0,0) 然後指定分別走到 (1,0) (0,1)
就可以得到 (0,0) - (1,0) 和 (1,0) - (0,1) 兩條線
由此我們知道
如果採用這個方法
有 n 個點 就可以決定 n-1 條線
是蠻有效率的一個做法
然而
因為海龜每走過的地方都會留下線條
如果遇到複雜的圖形
對程式設計師而言
用這個方法繪圖 是一個蠻大的負擔
往後要修改,也不好維護
因此還有第二種做法
第二種:明確指出各線條頂點和終點
此方法
就是把每一條線的 起點 終點 都指定出來
如此一來,每一條線走向都清清楚楚
然而
這種做法的效率較差
如果有 n 條線 需要 2n 個點來決定
程式設計者可依據需求 從這兩種作法中選擇一種
(不過,兩者做法的時間複雜度Time Complexity是一樣的,不必太擔心後者的效率問題)
達成動畫的方法 -- 線性轉換 (Linear Transformation)
在一個3D圖學引擎中
圖形不可能是靜止不動的
起碼在網路遊戲中
按住滑鼠右鍵轉視角的動作
其實就是動畫的一種 (旋轉)
無論是對圖形做什麼改變
都是要針對圖形的每一個頂點(Vertex)去做運算
而變化矩陣就是如同上圖這麼回事
如果圖形上有 n 個頂點
每做一格移動
就要坐上面的矩陣乘法 n 次
這也是為什麼圖形越複雜的時候
運算的速度越慢
而不同的線性轉換 要乘上不同的矩陣
上面這個就是縮放矩陣
針對圖形的 x y z 倍率做不同的大小變換
可以使圖形達到 變高、變瘦 的效果
此外更為重要的就是 旋轉矩陣
針對 X軸 Y軸 Z軸 做旋轉 會達到不同的效果
有時候一次要針對兩個軸旋轉 才能完成我們要的效果
是否要變更原始資料?
如果是做動畫,那麼我們的圖形肯定不只經過一次 線性轉換
換句話說就是 不可能只移動一格
此時有一個有趣的問題值得討論
假如一個圖形往右旋轉兩次 10度
那麼,第二次旋轉的時候,有兩種做法
第一種是,把第一次旋轉的成果 再往右旋轉一次 10度
第二種是,把原本的,沒有旋轉過的圖形,一次往右轉20度 (10+10=20)
究竟哪一種方法比較好呢?
首先,我們要知道,因為電腦的數線是一個「離散」(Discreet)的
所以小數點沒有辦法精確到很後面的位數
因此,每次作線性轉換,都有誤差。
如果我們使用第一種方法
因為每轉十度都有誤差
如果把十度轉36次
理論上因為轉了360度,會和原本的圖形重合
但是因為轉了36次,每次都有誤差,因此實際上沒有重合。
所以,
第二種方法,在圖學引擎的設計上,是比較會被採用的。
結語
3D圖學的門檻在於
你要如何建立你的座標系
以及你要如何決定你的 點 線 面
還有動畫的細節要如何處理
銘謝 與參考書目
感謝 繪製台北大學校徽的 Yipo 讓我們有示範的模型可以用
參考書目
1. 深入淺出 DirectX 程式設計
2. Java 2D/3D 繪圖 程式設計實例應用
※本文歡迎各類專題論文參考引用,唯須註明出處為 Frank's 資訊科技潮流站,謝謝。