第一件事情我想你知道的是,在Flash里,并不存在真正的3D,或者我應該說,Flash
CS3并不支持3D繪制。我們所做的是運用Flash里的2D繪制方法去模擬3D繪制,Flash并不知道3D是什么也不知道如何去處理3D對象。但是好
消息是所有的3D處理和3D計算都是建立在數學計算的基礎上的,加上Flash知道如何的處理數學計算。太好了,這些工具足以使我們創造出自己的動畫了。
這并不是說Flash里的3D編程要簡單,與其相反,如果你打算深入去探索的話你會發現你會進行很大一部分的Low level
Programming。不管怎樣,即使你沒有3D編程經驗,只要有讀文章和多多動手聯系,我相信你也能快速的學會這些看似深奧的東西。另外,雖然文中數
學占很大一部分比例,但是文章中我會用最大的努力把數學部分變得簡單易懂,如果實在有問題的話,你可以找一本數學資料參考。
在Flash里,有兩種3D處理方式,一種是提前處理好3D模型,另外一種是在程序運行時通過數學計算處理3D圖形。運用第一種方法,可以提前處理好一系 列的圖形,然后通過對禎或者是時間操作進行動畫播放,以達到3D效果,這一種方法對美工的要求比較高。第二種方法是通過大量的數學計算對物體進行操作,實 時計算出物體的頂點的位置,方向,旋轉角度等等變量,并且繪制出圖形,這也是在這篇文章里所關心的。
3D繪制工具
如今你在互聯網上搜索3D Flash你會找到很多的工具和程序,比如Swift,利用這些程序你可以繪制一些3D圖形并導出你需要的格式,甚至完全使用在你的項目里。基本上你可以 不必操心如何繪制3D圖形。但是,這些程序給你提供的都是提前做好的模版,不能夠作太多的runtime處理,有一定的局限性。于是,我們發現自己也有大 腦,也可以制作3D的運動動畫,還可以制作復雜的3D繪制引擎,最重要的是能夠探索其中的奧秘,學習為什么在OpenGL里使用glVertex3f函數 就可以定義一個空間點。這并不像我們在使用OpenGL時那么得心應手,你要做的是去實現glVertex3f這個函數而不是去利用它。一切3D的物體都 要自己動腦動手加上數學運算進行繪制,肯定會增加一些數學上的挑戰。不過我認為,這對你來說應該不是問題,其實使用Flash作3D圖形常常會給你帶來你 意想不到的樂趣,那么開始吧!
3D空間坐標系
從技術角度而言,Flash中并不存在3D,也就是說z軸并不存在,所以所謂的z軸是由你來制作的,利用縮放物體讓大家產生3D的錯覺。那么也就是說,對于一個3D虛擬空間,z軸與你看進顯示器的方向重合,x軸和y軸分別為橫向和縱向。

對于z軸的解釋
在現實中,當一個物體離你遠去,那么對你的眼睛來說,它所看到的是物體越來越小。當然并不只有物體的大小在改變,物體離你的距離也在增大。可以假定,在3D空間里,離得人眼越遠的物體,它的大小就越小,那么它在x和y軸上的移動就越緩慢。很簡單對吧?很好。
注意:
如果你用過OpenGL,那么你應該知道y軸的正方向是指向上方,z軸正方向指向屏幕外,然而文章中的Flash 3D空間的y軸和z軸是相反的。
原點
Flash中3D空間是圍繞坐標系原點的,原點的坐標我們用Point(x, y, z), (0, 0, 0) 來表示。在Flash 2D中,原點存在于程序的左上角Point(0, 0),那么對于3D來說,原點也自然存在于程序的左上角,也許你會發現,如果原點在左上角的話,那么你所在的位置肯定是成一定角度(仰看)來觀察程序中 3D空間中的物體的。當然可以把3D空間的原點向右再向下移動,因為圍繞原點繪制物體的時候會發現方便很多。
敘述了這么多,到底用什么方法來表達3D空間呢?
縮放物體
離人眼越近,那么物體就越大,反之物體就越小。物體縮放的比率以及移動速率與物體z的大小成反比。現在我用一個實例給說明如何制造3D動畫效果,在這個例
子中,我手工繪制了幾個小球,作為虛擬的3D的物體,讓它們沿著z軸在舞臺上來回移動,以制造3D效果。雖然很基本,不過別擔心,把這些簡單的東西掌握好
是深入探索的基礎。注意:從第一到第六篇文章中都不涉及3D物體的概念,例子中使用的小球(小P)是2D矢量圖,這樣做的目的是讓你在不關心物體的情況下
鍛煉空間感。
小球與3D空間(無層次)
動畫制作步驟
1.
第一步,用Flash畫出一個你喜歡的物體,任何物體都可以。在這個例子中我畫了一個藍色的小球。當然可以導入你喜歡的圖片,不過不要忘記在
Library里創建的物體上點擊右鍵,選擇Linkage,然后在Export For Actionscript上打勾。
2. 下一步,詳細解說一下代碼。當然一開始要設置一些變量,原點和焦距(攝像機)。Focal length(焦距)確定了攝像機(在本例子中為人眼的)的凸透鏡的焦距,值越大,那么物體的扭曲就會越小。把它設為400,這是一個在本例子中適中的數值。
origin.x = stage.stageWidth/2;
origin.y = stage.stageHeight/2-80;
this.addChild(scene);
scene.x = origin.x;
scene.y = origin.y;
4. 然后要在舞臺上添加一些我們繪制好的小球。在這個例子中我們繪制3個,分別在左中右。把它們的x_3d, y_3d, z_3d,也就是它們的3D空間的x,y,z的值設為相應的數值,我把它們排為一排。每一個都添加一個direction屬性,1代表向屏幕方向移 動,-1 代表向我們的方向移動。然后設置它們的移動速度,并且添加到舞臺上。這時你如果編譯的話,你會看到有3個球在舞臺上,那么下一步就讓小球運動起來。
{
var sphere = new Sphere();
sphere.x_3d = -190+i*160;
sphere.y_3d = 80;
sphere.z_3d = i*100;
sphere.direction = 1;
sphere.speed = 6;
scene.addChild(sphere);
}
5. 下面這個函數,在每一次執行,都會把小球移動到相應的位置,并且對小球進行縮放。當小球的z大于600時,讓它向相反的方向移動。當小球的z_3d值變化 后,計算小球當前的大小和位置,把小球移動到相應的位置然后對其進行縮放,這樣在一連串的函數執行后,就會得到動畫效果。代碼里scale代表物體應該縮 放的比率,因為當物體沿z軸移動的時候,物體的大小以及x和y值都會改變。所以要計算出這個比率,那么我們才能把物體縮放到合適的大小,并且把物體移動到 相應的2D空間位置。
{
for (var i = 0; i < scene.numChildren; i++)
{
scene.getChildAt(i).z_3d += scene.getChildAt(i).speed*scene.getChildAt(i).direction;
if (scene.getChildAt(i).z_3d > 600)
{
scene.getChildAt(i).z_3d = 600;
scene.getChildAt(i).direction = -1;
}
else if (scene.getChildAt(i).z_3d < 0)
{
scene.getChildAt(i).z_3d = 0;
scene.getChildAt(i).direction = 1;
}
var scale = focal_length/(focal_length+scene.getChildAt(i).z_3d);
scene.getChildAt(i).x = scene.getChildAt(i).x_3d*scale;
scene.getChildAt(i).y = scene.getChildAt(i).y_3d*scale;
scene.getChildAt(i).scaleX = scene.getChildAt(i).scaleY = scale;
}
}
6. 最后,在舞臺上添加一個函數循環響應時間。讓第5步寫的函數循環執行。編譯看一下,現在小球在3D舞臺上移動了。
Hooray!你的第一個Flash3D程序完成了。總結一下,其實并沒有使用任何高深的技巧,只不過是利用了變化物體的x和y以及小球的縮放來制造3D效果。對你來說太簡單?好,那我們繼續。
層疊
在Flash中表現3D空間,僅有縮放是不夠的,還需要另外一個技巧,層疊。它的基本概念是,離人眼較近的物體會在離人眼較遠的物體之上顯示。
在上一個例子里面,我們縮放小球,以達到3D效果。可是你會發現,3個小球之間的x距離都很大,那么你也許會想如果3個小球離得很近的話,會出現什么現象呢?
注意
嘗試把上面例子中小球之間的x距離變小,看看有什么變化?這時會發現,不管小球離我們多遠,右邊的小球始終在最上面。即使中間的小球應該蓋過右邊小 球的時候,右邊的小球還會在上面。這是因為在把小球添加到舞臺上的時候,已經給了小球層次,也就是說最后添加的小球(右邊的小球)就在最上面。
小球3D空間(無層次)位置不對了!
看起來應該設計一種方法實現小球的層次感,當小球離我們遠的時候,那么它的層次就比較靠后,以此類推。換句話說,需要利用小球的z值給小球們分開層次,這也是即將要做的。在下面這個例子中,我們使用7個小球的運動來說明是如何實現層次的。
小球3D空間(有層次)好多了!
動畫制作步驟
1. 和上次的例子一樣,重復6個步驟。不同的是初始化7個小球,并且把它們的x距離縮短。
{
var sphere = new Sphere();
sphere.x_3d = -150+i*40;
sphere.y_3d = 80;
sphere.z_3d = Math.random()*(0-600)+600;
sphere.direction = 1;
sphere.speed = Math.random()*(5-12)+12;
scene.addChild(sphere);
}
2. 利用Bubble Sort算法,在每一次對小球x,y和大小設置后,對所有的小球在舞臺上的層次進行操作。這里使用的理論是最小的z值的小球,它所在層次就應該在最上面。 不要小看我寫的這短短幾行代碼哦!它可以把所有的小球分配到相應的層次!只要你的CPU夠塊,不管多少小球都可以。
{
for (var i = 0; i < container.numChildren - 1; i++)
{
for (var j = container.numChildren - 1; j > 0; j--)
{
if (Object(container.getChildAt(j-1)).z_3d < Object(container.getChildAt(j)).z_3d)
{
container.swapChildren(container.getChildAt(j-1), container.getChildAt(j));
}
}
}
}
3. 然后在循環函數里的最后加上
本文章旨在討論如何在Flash中實現3D動畫,對于一些算法,比如這一節中使用到的冒泡排序算法,我就不再多說了。當然你可以選擇使用插入排序 (運算起來比較快40%?!)。你可以完全拷貝我寫的代碼去使用,但是請務必注明出處。如果是排序的話,google或者百度一下,我相信你會找到更詳細 的說明文字來解釋冒泡排序。
一個簡單Particle System例子
這是一個使用縮放的基本概念的例子,可以使用鍵盤上下左右鍵移動你的觀看位置,按下W鍵加速前進,按下S鍵減速。由于涉及到攝像機,在這篇文章中就不再講 解。源文件在本文的下載中可以找到,你可以嘗試改變星星的數量,星星很多的話,移動攝像機,應該會看到一個很長的星帶(題外話:在我的電腦里運行2000 個 星星就有些慢了,Dual Core 2.0GHZ,如果你有更強大的CPU的話,那你看到星空要比我的漂亮的多)。
3D星空,簡單的Particle System,WASD移動觀看位置,K鍵加速,L鍵減速
OK,你已經學會了如果使用縮放和一些簡單的設置產生3D效果的動畫。在后面的幾篇中,我們會逐漸深入探討更有趣的內容。加油!
相關文章: