posts - 241,  comments - 116,  trackbacks - 0

          第一件事情我想你知道的是,在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軸分別為橫向和縱向。

           2D與3D坐標系

          對于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,這是一個在本例子中適中的數值。

          var origin = new Object();
          origin.x 
          = stage.stageWidth/2;
          origin.y 
          = stage.stageHeight/2-80;
          var focal_length = 400;
          3. 創建一個舞臺,并且把它的x和y設置為原點,這樣在在舞臺上創建物體時,就會默認原點在程序窗口的中央了。
          var scene = new Sprite();
          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個球在舞臺上,那么下一步就讓小球運動起來。

          for (var i = 0; i < 3; i++)
          {
              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空間位置。

          function run(e:Event)
          {
              
          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距離縮短。

          for (var i = 0; i < 7; i++)
          {
              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夠塊,不管多少小球都可以。

          function swap_depth(container:Sprite)
          {
              
          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. 然后在循環函數里的最后加上

          swap_depth(scene);


          本文章旨在討論如何在Flash中實現3D動畫,對于一些算法,比如這一節中使用到的冒泡排序算法,我就不再多說了。當然你可以選擇使用插入排序 (運算起來比較快40%?!)。你可以完全拷貝我寫的代碼去使用,但是請務必注明出處。如果是排序的話,google或者百度一下,我相信你會找到更詳細 的說明文字來解釋冒泡排序。



          一個簡單Particle System例子

          這是一個使用縮放的基本概念的例子,可以使用鍵盤上下左右鍵移動你的觀看位置,按下W鍵加速前進,按下S鍵減速。由于涉及到攝像機,在這篇文章中就不再講 解。源文件在本文的下載中可以找到,你可以嘗試改變星星的數量,星星很多的話,移動攝像機,應該會看到一個很長的星帶(題外話:在我的電腦里運行2000 個 星星就有些慢了,Dual Core 2.0GHZ,如果你有更強大的CPU的話,那你看到星空要比我的漂亮的多)。



          3D星空,簡單的Particle System,WASD移動觀看位置,K鍵加速,L鍵減速

          OK,你已經學會了如果使用縮放和一些簡單的設置產生3D效果的動畫。在后面的幾篇中,我們會逐漸深入探討更有趣的內容。加油!


          相關文章:

          1. Flash與3D編程學習(三)- 攝像機(Camera
          2. Flash與3D編程學習(八)- 3D物體著色基礎
          3. Flash與3D編程學習(五)- 攝像機旋轉和移
          4. Flash與3D編程學習(二)- 靜態長方體
          5. Flash與3D編程學習(四)- 攝像機旋轉基礎
          6. Flash與3D編程學習(六)- 全方位旋轉攝像
          7. Flash與3D編程學習(七)- 3D物體框架
          posted on 2008-12-29 10:56 墻頭草 閱讀(614) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          人人游戲網 軟件開發網 貨運專家
          主站蜘蛛池模板: 嘉义市| 高要市| 庄河市| 长子县| 中西区| 晋州市| 奈曼旗| 大洼县| 宜兴市| 静乐县| 准格尔旗| 资溪县| 普陀区| 嘉兴市| 平顺县| 武安市| 华蓥市| 永新县| 礼泉县| 上杭县| 彩票| 锦屏县| 芜湖县| 黔江区| 枣强县| 仪陇县| 和田市| 正镶白旗| 固始县| 甘洛县| 门源| 平潭县| 汕头市| 望城县| 广安市| 拉萨市| 克拉玛依市| 莱西市| 栾城县| 勐海县| 封开县|