close

 

flag_rotate.JPG

「有些自閉症兒童偏愛旋轉的東西,不管是玻璃瓶或銅板,他們常會拿來轉;」

ntpu-3d-flag.gif

前言

這個寒假,由於專題剛剛結束,但留下了一些圖學設計概念的部分尚未完成,甚至是完成了一半就有成品交差了。為此感到有些可惜,因此藉由這個長假,對這一部分稍稍做了一點研究,希望在此做些筆記,並且分享出來供大家參考。

 

 

 

建立 3D 空間的第一步 : 確立你的座標系

許多人覺得踏入 3D 圖形程式設計很困難,因為他們不知道怎麼在一個2D的顯示器上,去表達一個3D的模型。事實上,目前的所有PC顯示器,都是一個2D的實體,而我們如何在一個2D的顯示器上,去顯示一個3D的圖形,就是3D圖學引擎設計實作所要面臨的主要問題。

上面說到的這個問題似乎很複雜,但是並不難辦到。目前達成這個方法的座標系有「左手座標系」和「右手座標系」,而其中又以左手座標系受到歡迎。

system.png

【圖1】左手座標系

以往2D圖形只有兩個軸,分別是X軸和Y軸。而這兩個軸只要和螢幕上的兩個軸相符合即可,不需特別花心思去實做。

而要作出3D圖形,則是要思考如何在螢幕上表達「並不存在的第三個軸 - Z軸」

以上圖左手座標系的處理方式,即是將 X 軸 或 Y軸 旋轉45度,就可以得到 Z 軸。

(如果選擇Y軸,是將其向右旋轉45度得到Z軸;如果選擇X軸,則是將其向左旋轉45度得到Z軸。)

有了 Z 軸之後,我們就好辦事了。

3.jpg

【圖2】針對 (1,0,0) (0,1,0) (0,0,1) 三個向量的繪圖

 

當然,如果你的顯示器本身就是三維的,那麼就不必煩惱這個問題了。

 


邏輯座標系 與 實體坐標

x1.jpg

如果我們依據螢幕的實體坐標,會得到上面那個樣子

沒有辦法實做出負數座標

x2.jpg

因此我們要把各點 x,y,z 各加上一定的數值

才能做到

例如我們想要讓 x 顯示出 大於 -10 的點

那麼 我們就要針對 所有圖形上的 x點 全部加上 10

用這個方法做出 邏輯座標  如此才有辦法顯示出負數點

從上圖我們就可以了解 邏輯的座標 和 實體的座標(即硬體實際上的座標)的差別

x3.jpg

唯有用上負數座標 才有可能支援到圖形空間(Space)的八個象限

如上圖所示

 

繪製線條的兩種方式

在圖學上,要繪製一個圖形無非是從   點 -> 線 -> 面   這個方向依序討論

Vertex -> Edge -> Plane

方才我們討論座標系,乃是決定3D圖形的「點」

而兩點可以決定一條「線」

而決定一條線的方式,主要有兩種,而各有利弊

以下分述之


第一種:海龜繪圖法

line1.jpg

海龜繪圖法顧名思義,就是模擬一隻拿著畫筆的海龜

走過的地方就會留下痕跡,而那痕跡就是我們要的線條

實做方法是

先決定海龜走路的起點

然後決定海龜下一個位置要走到哪裡

例如海龜原本在 (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 條線

是蠻有效率的一個做法

 

然而

因為海龜每走過的地方都會留下線條

如果遇到複雜的圖形

對程式設計師而言

用這個方法繪圖 是一個蠻大的負擔

往後要修改,也不好維護

因此還有第二種做法

 


第二種:明確指出各線條頂點和終點

line2.jpg

此方法

就是把每一條線的 起點 終點 都指定出來

如此一來,每一條線走向都清清楚楚

然而

這種做法的效率較差

如果有 n 條線 需要 2n 個點來決定

程式設計者可依據需求 從這兩種作法中選擇一種

(不過,兩者做法的時間複雜度Time Complexity是一樣的,不必太擔心後者的效率問題)


達成動畫的方法 -- 線性轉換 (Linear Transformation)

在一個3D圖學引擎中

圖形不可能是靜止不動的

起碼在網路遊戲中

按住滑鼠右鍵轉視角的動作

其實就是動畫的一種 (旋轉)

 

 

無論是對圖形做什麼改變

都是要針對圖形的每一個頂點(Vertex)去做運算

trans2.jpg

而變化矩陣就是如同上圖這麼回事

如果圖形上有 n 個頂點

每做一格移動

就要坐上面的矩陣乘法 n 次

這也是為什麼圖形越複雜的時候

運算的速度越慢

 

而不同的線性轉換 要乘上不同的矩陣

trans1.jpg

上面這個就是縮放矩陣

針對圖形的 x y z 倍率做不同的大小變換

可以使圖形達到 變高、變瘦 的效果

 

此外更為重要的就是 旋轉矩陣

 rotate.jpg

針對 X軸 Y軸 Z軸 做旋轉 會達到不同的效果

有時候一次要針對兩個軸旋轉 才能完成我們要的效果

to_x.jpg

to_y.jpg

to_z.jpg


 

是否要變更原始資料?

如果是做動畫,那麼我們的圖形肯定不只經過一次 線性轉換

換句話說就是 不可能只移動一格

此時有一個有趣的問題值得討論

假如一個圖形往右旋轉兩次 10度

那麼,第二次旋轉的時候,有兩種做法

第一種是,把第一次旋轉的成果 再往右旋轉一次 10度

r1.jpg

第二種是,把原本的,沒有旋轉過的圖形,一次往右轉20度 (10+10=20)

r2.jpg

究竟哪一種方法比較好呢?

 

首先,我們要知道,因為電腦的數線是一個「離散」(Discreet)的

所以小數點沒有辦法精確到很後面的位數

因此,每次作線性轉換,都有誤差。

如果我們使用第一種方法

因為每轉十度都有誤差

如果把十度轉36次

理論上因為轉了360度,會和原本的圖形重合

但是因為轉了36次,每次都有誤差,因此實際上沒有重合。

r3.jpg

所以,

第二種方法,在圖學引擎的設計上,是比較會被採用的。

 

結語

3D圖學的門檻在於

你要如何建立你的座標系

以及你要如何決定你的 點 線 面

還有動畫的細節要如何處理

 

銘謝 與參考書目

感謝 繪製台北大學校徽的 Yipo 讓我們有示範的模型可以用

參考書目

1. 深入淺出 DirectX 程式設計

2. Java 2D/3D 繪圖 程式設計實例應用

 

※本文歡迎各類專題論文參考引用,唯須註明出處為 Frank's 資訊科技潮流站,謝謝。

 



arrow
arrow
    全站熱搜

    finalfrank 發表在 痞客邦 留言(1) 人氣()