2010/2/23

教學:3D選單

多年前教書用的教案,轉貼過來
課程目標
-學習用 Action Script 虛擬3D空間
-利用3D技術擴展視覺效果
-製作3D選單




00.課前準備知識
Flash本身是2D多媒體開發工具,其座標系統只有X及Y兩個座標軸。但3D空間需要X、Y及Z三個軸向才可實現,因此首要任務便是利用Action Script在Flash中虛擬一個3D空間,讓每個物件皆包含X、Y及Z三個座標值。

設定好3D座標後,便要考慮如何將3D座標投影至電腦畫面上的2D座標,此為虛擬3D技術的第一個重點。

以下圖說明之:


Viewpoint指的是觀賞者視點。
Projection plane 是指投影平面,也可說是電腦螢幕。
d 是視點到投影平面的距離。
z 是視點到虛擬物的距離
仔細看X1及X2字下方的黑點,假設虛擬空間中存在一個黑點(point in space),它在虛擬空間中的x座標為X2,當觀賞者透過螢幕看這個黑點時,黑點的影向是投射在螢幕上(point projected on projection plane)的x座標為X2。

透過上述原理,再利用斜率一致的特性,可知:
X1/d=X2/z
得 X1=X2*(d/z)
同理 Y1=Y2*(d/z)

X2、Y2都是虛擬空間中的座標,因此只要乘以(d/z)即可知道投影到畫面上的X1及Y2。
z是物體的z座標,由我們自訂。
而d是視點到投影平面的距離,d也可由我們自訂,不過不同的d值會有不同的效果,就像鏡頭前進或後退的差異,可在開發過程中視狀況調整。

除了x、y需要設定外,還需要設定_xscale、_yscale,以表現近大遠小的縮放效果。_xscale及_yscale的縮放原理就跟x、y換算一樣,利用(d/z) 來計算。

_xscale = _yscale=100*(d/z);

整理上述,可歸納如下:



接下來我們只要設定好物體在虛擬空間中的x、y、z,不論位在何處,皆可換算出它投影到螢幕上的座標及大小。



01.產生3D投影
首先任意畫一個圓形圖案,可加入少許立體效果,畫好後轉換成MC,並設好Linkage名稱”ball"

主場景上不放任何物件,在Frame上撰寫AS:

cx、cy是畫面中心點,各是stage長寬(550x400)的一半。
eyeD是視點到投影平面的距離,此範例設500,學員可自行調整看效果差界,但記得不要設為負數。
setBallPos函式則是上一節所得到的換算公式。
最後產生球體,以attachMovie產生,同時設定它的x、y、z。此範例以亂數設定,學員也可自行設定到特定位置,並發佈測試比較不同位置呈現的效果。

單純把球體畫在畫面上,可能感受不到明顯的立體效果,若是球體能在空間中移動,應該就能觀察出空間感。

我們加入簡單的移動功能,以方向鍵及「-」「+」鍵來控制球的六方向移動:


關於鍵盤控制,在此不多贅述,但請記得每次移動球體後,都要做setBallPos(ball)的動作,畫面上的球體才會更新位置大小。

發佈測試結果,以鍵盤控制球體,觀察球體移動及大小的變化。
檔案:01_產生3D投影.fla



02.產生多個球體
利用上一節的原理,試試一次產生多個球體:

程式碼如下:

與上一節範例十分類似,唯一不同在一開始多了個sum變數,決定要產生幾個球體,setBallPos函式與上節範例相同,而最後產生球的部份改以for廻圈產生sum設定的球體數量。

發佈測試結果
檔案:02_產生3D投影多捄.fla



03.旋轉
在01的範例中,我們試著用鍵盤控制六方向移動,但都是直線行進;若是能弧形移動,則更能表現虛擬空間的立體感。

假設我們知道物體離圓心的距離,也知道旋轉的角度,那該如何算出它的x、y位置?

sinθ=y/r
cosθ=x/r
y=r* sinθ
x=r* cosθ



透過上述原理,瞭解三角函數與座標計算的關係。

下圖表示一個座標值以弧形移動的狀況


(x,y,0)是第一個位置,它是位在角度a的位置上,接著它以z為軸心,向上移動了角度b,來到(x’,y’,0)的位置。

x= r * cos(a)
y= r * sin(a)
z=0

x’= r * cos(a+b)
y’= r * sin(a+b)
z’=0

根據三角函數公式,可再換算成:
x’= r * cos(a+b) = r * (cos(a)*cos(b) – sin(a)*sin(b)) = x * cos(b) – y * sin(b)
y’= r * sin(a+b) = r * (sin(a)*cos(b) + cos(a) *sin(b)) = y * cos(b) + x * sin(b)
z’=0

以上是以z軸旋轉的公式,整理三個軸向公式如下:

X軸旋轉
x’=x
y’=y*cosθ+z*sinθ
z’=z*cosθ-y*sinθ

Y軸旋轉
x’=x*cosθ-z*sinθ
y’=y
z’=z*cosθ+x*sinθ

Z軸旋轉
x’=x*cosθ-y*sinθ
y’= y*cosθ+x*sinθ
z’=z


利用上述原理,我們實作一個沿x軸旋轉的範例,每次旋轉5度。

檔案:03_多球單軸自轉.fla



04.手動旋轉
上一節學會了旋轉的原理,接下來可試著將旋轉功能轉變成手動旋轉。這一節與上一節大致相同,唯一不同是利用滑鼠位置來設定旋轉角度。

檔案:04_多球單軸手動轉x.fla



05. Y軸轉動
同樣之前的做法,改以Y軸轉動。

檔案:05_多球單軸手動轉y.fla



06. 多軸向旋轉
利用之前介紹的公式,即可設定X軸及Y軸的旋轉,不過要注意當雙軸同時轉動時,必需先計算一個軸向,再以此結果套入第二個軸向的公式。
可以視為先轉其一再轉其二來看待。



檔案:055_多球雙軸手動轉xy.fla
檔案:06_大球體旋轉.fla



07. 3D旋轉選單
利用上述所學,可以輕鬆做出如下3D選單。

檔案:07_球體選單.fla




08. 無限飛行
除了弧形旋轉外,也可累加z值,以製造無限Zoom in 的效果

檔案:08_zoomIn飛行.fla



09. Zoom In 選單
上一節的飛行效果,也可製作成選單,以滑鼠點選黑球來控制鏡頭前進。
檔案:09_zoomIn選單.fla


drawTriangles+UV貼圖筆記


寫給自己的筆記,很粗淺。

昨天研究了一下drawTriangles,直接google這關鍵字可查到最基本的官方教材
關於使用 drawTriangles()
接著也會看到這篇
UV 對應

照著UV對應這篇很快就能弄出一個3D旋轉的範例,如下
.Demo:Spinning3dOcean.swf

這個旋轉教學很簡單,但也有點小複雜,因為他同時使用了3D投影及triangle UV貼圖兩件事。原因是Flash的UV貼圖功能是包含了3D透視比例(就是裏面那個T變數)。所以這篇教學才需要一次介紹這麼多。


不過我個人偏好把東西再分得清楚些,且有很多時候我需要UV變形,但不見得同時也需要3D座標。

所以,以下我先不管3D座標,所有T值都帶1,單純把UV變形的部份練習一下。如下

.Demo: UVT_test_0.swf

這個測試是從上面的官方教學修改而來,並加入線條顯示,及四角控制點。拖拉四個角,可任意變形圖片。唯一問題是變形會像是兩個三角面在折來折去,而不是很smooth的3D傾斜,原因就在我前面說的T值目前都帶1,暫時不考慮3D因素所致。(關於3D問題,將補充說明在最後面)

.Source code



上面的練習只切了兩片三角面,接著我就想試多切幾面的效果,先試試切8片的效果:

.Demo: UVT_test_1.swf

切愈多面可使變形效果較smooth,不過仍與套用3D T值的效果不太相同,目前這種會比較像是2D的網面效果
.Source code



上面的練習是用手動的方式key入9個節點,很弱,所以接下來要設計成用迴圈自動運算節點座標的方式:

.Demo: UVT_test_2.swf

不過demo裏我沒有再做一個UI介面讓人動態去改切割數了,太花時間了。有興趣的人,在source code裏去調整slice這個變數即可。

.Source code



練習至此,就可以利用drawTriangles及UV貼圖的技巧來做許多事了,例如以下的精靈效果:

.Demo: UVT_genie.swf


關於3D的補充說明
使用UV貼圖時,那個T變數,最佳的解決方式就是用3D座標的方式來算,就如同最上面那個官方範例一樣。這點對已熟知3D投影算法的人來說,並不是什麼大問題。也因此這篇筆記才沒對此特別著墨。

而有興趣瞭解3D投影的人,可參考這篇:3D選單教學裏最前面的原理說明部份。

除了直接算出3D標座外,也有神人提出別種解法,請看這篇The best drawPlane/distortImage method, ever
文中作者用兩條對角線,再配合很神妙的公式,算出合理的3D T值,而不用透過真實的3D座標計算。
比較可惜是作者並沒有說明這公式的導出原理。(可能是硬湊出來的,因為他說他花了很多時間try & error & beer XD)
且這方式只能用在只有四個頂點的UV變形裏。其他狀況就完全不適用了。

所以我個人的結論是,單純要做UV變形的話,我會先不考慮T值,能弄出需要的效果就好。假若遇到需要實際3D表現的話,再視情況寫一個3D座標系統配合使用。而上面神人導出的奇妙公式,有出現剛好的使用時機才會考慮使用了。