Sealyu

          --- 博客已遷移至: http://www.sealyu.com/blog

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            618 隨筆 :: 87 文章 :: 225 評(píng)論 :: 0 Trackbacks
          眾所周知,flash是一個(gè)二維的動(dòng)畫軟件,是無法完成一些真正的3d效果,但是如果要用它來做一些3d效果也不是不可能,一般來說有以下三種方法.
          第一種方法,借助其它的3d軟件,象swift 3d,Ulead Cool 3d,TrueSpace等一些相對(duì)容易上手的軟件,用它們來完成后再導(dǎo)入到flash中,效果是不錯(cuò),但是導(dǎo)入的大都是位圖系列,所以生成的文件都比較 大,再有一個(gè)特點(diǎn)就是沒有flash所特有的互動(dòng)性,作為flash 并沒有多少工作可做,它只不過是播放的工具而已.
          第二種方法,理論上可以,實(shí)際上是行不通的,就是利用flash 的畫圖工具做成逐幀動(dòng)畫,當(dāng)然簡單的還湊合,復(fù)雜的就根本不行.
          第三種方法,就是我今天所要說的as 3d ,用數(shù)學(xué)方法算出3d來,也就是利用數(shù)學(xué)公式和一些透視的知識(shí)模仿出3d效果來,也稱之為假3d,是一種視覺上的錯(cuò)覺.不過我個(gè)人認(rèn)為在電視上出現(xiàn)的3d 應(yīng)該都是假3d,只不過那些專業(yè)的3d軟件做出來的更逼真,更能欺騙你的眼睛罷了.
          言歸正傳,我們首先認(rèn)識(shí)一下坐標(biāo)問題,因?yàn)橐7氯S效果,必須首先了解坐標(biāo)方面的知識(shí),,因?yàn)?d效果都是三維坐標(biāo),而flash中是二維坐標(biāo),我們應(yīng)該先把三維坐標(biāo)轉(zhuǎn)換二維數(shù)學(xué)坐標(biāo),再把二維坐標(biāo)轉(zhuǎn)換為flash中的坐標(biāo),如圖:

          uploads/200704/30_200810_20070323153949870.gif

          為此我們先畫一個(gè)透視圖,B點(diǎn)是觀察者的眼睛,物體位于三維空間的A點(diǎn),它的坐標(biāo)是(x,y,z),將該點(diǎn)的坐標(biāo)轉(zhuǎn)換為二維坐標(biāo),實(shí)際上就是點(diǎn)A在平面 (電視屏幕)上的投影點(diǎn)C的坐標(biāo),其中CF的長就是該點(diǎn)的X坐標(biāo)值,CE是該點(diǎn)的Y的坐標(biāo)值,假設(shè)觀察點(diǎn)到屏幕的距離BO=d,然后根據(jù)三角形相似原理, 對(duì)應(yīng)邊成比例可以得到d/(d+z)=x1/x,d/(d+z)=y1/y,其中(x1,y1)就是轉(zhuǎn)換后的坐標(biāo),假設(shè)d/(d+z)=ratio,所以 x1=x*ratio,y1=y*ratio.
          uploads/200704/30_200825_2.gif

          這樣如果不好看懂的話,我們?cè)贀Q個(gè)角度來看,假設(shè)從上往下看和從右往左看,畫個(gè)頂視圖和右視圖,這時(shí)候頂視圖只能看到X軸和Z軸,Y軸只是一個(gè)點(diǎn),右視圖只能看到Y(jié)軸和Z軸,X而軸只是一個(gè)點(diǎn),如圖:
          uploads/200704/30_200855_3.gif

          uploads/200704/30_200904_4.gif

          接下來就很簡單了,二維數(shù)學(xué)坐標(biāo)和flash之間的坐標(biāo)轉(zhuǎn)換,只需把中心移動(dòng)到左上角就好了,那么A點(diǎn)最終的坐標(biāo):
          _x=width/2+x1,
          _y=height/2-y1,
          其中width和height分別是場景的寬和高.
          現(xiàn)在坐標(biāo)的問題解決了,只是第一步,要想讓物體符合空間透視,還需要對(duì)其它參數(shù)做調(diào)整,比如近大遠(yuǎn)小,景深之類的,但是flash畢竟不是專門的3d軟 件,所以我們只能盡可能的模仿了,通過調(diào)整物體的比例大小,透明度和物體所處的層次可以達(dá)到比較逼真的效果,其中比例問題的原理和坐標(biāo)相同,所以也可以根 據(jù)上面的公式得出,即:_xscale=_yscale=100*ratio(z越大,ratio就越小,離屏幕就越遠(yuǎn),物體就越小),透明度也是一樣 _alpha=100*ratio;至于層次的問題現(xiàn)在大都用的是經(jīng)驗(yàn)值swapDepths(10000-z)或者swapDepths(-z).
          導(dǎo)入三個(gè)小圖標(biāo),也可以是圖片,如果你畫的好的話,還可以畫三個(gè)小人,這樣效果更好,做成影片剪輯,拖入主場景中,分別命名為:mcA,mcB,mcC,然后在主場景的第一幀加入以下代碼:
          [color=Red]mcA.x = -300;
          mcA.y = 0;
          mcA.z = 0;
          mcA.dir = 1;//運(yùn)動(dòng)的方向
          mcB.x = -50;
          mcB.y = 0;
          mcB.z = 250;
          mcB.dir = 1;
          mcC.x = 200;
          mcC.y = 0;
          mcC.z = 500;
          mcC.dir = 1;//以上為三個(gè)圖標(biāo)的三維坐標(biāo)值
          d = 300;
          speed = 20;
          mcMove = function () {
           this.z += speed*this.dir;
           if (this.z>500) {
           this.z = 500;
           this.dir = -1;
           } else if (this.z<0) {
           this.z = 0;
           this.dir = 1;
           }
           var ratio = d/(d+this.z);
           this._x = 250+this.x*ratio;
           this._y = 150-this.y*ratio;//將三維坐標(biāo)轉(zhuǎn)化為二維坐標(biāo)
           this._xscale = this._yscale=100*ratio;
           this.swapDepths(-this.z);//調(diào)整比例大小,透明度和層次讓它符合透視原理
          };
          mcA.onEnterFrame = mcMove;
          mcB.onEnterFrame = mcMove;
          mcC.onEnterFrame = mcMove; [/color]

          這里是swf文件:3d1.swf
          附件: 3d1.swf
          Media 點(diǎn)擊播放/隱藏媒體

          接下來我們?cè)僮鲆粋€(gè)例子,在這個(gè)例子里我們引入一個(gè)鏡頭的概念,通過改變鏡頭的遠(yuǎn)近來實(shí)現(xiàn)一些更酷的效果,在主場景的第一幀加入以下代碼:
          [color=Red]this.createEmptyMovieClip("scene", 1);
          scene._x = scene._y=200;/
          scene.depth = 1;//建立一個(gè)空的影片剪輯,用來包含一切的3d元素
          cameraView = new Object();
          cameraView.x = 0;
          cameraView.y = 0;
          cameraView.z = 0;//鏡頭坐標(biāo)的初始值
          cameraView.target = new Object();
          cameraView.target.x = 0;
          cameraView.target.y = 0;
          cameraView.target.z = 0;//目標(biāo)鏡頭的坐標(biāo)值
          d = 200;//眼睛和屏幕的距離
          selectPic = function () {
           cameraView.target.x = this.x;
           cameraView.target.y = this.y;
           cameraView.target.z = this.z;
          };//這個(gè)函數(shù)就是每選擇一個(gè)圖時(shí),把這個(gè)圖的坐標(biāo)作為目標(biāo)鏡頭的坐標(biāo)
          displayPic = function (cameraView, d) {
           var x = this.x-cameraView.x;
           var y = this.y-cameraView.y;
           var z = this.z-cameraView.z;
           if (z<0) {
           this.z += 5000;
           this.x = 1000-Math.random()*1000;
           this.y = 1000-Math.random()*1000;
           x = this.x-cameraView.x;
           y = this.y-cameraView.y;
           z = this.z-cameraView.z;
           }
           var ratio = d/(d+z);
           this._x = x*ratio;
           this._y = y*ratio;
           this._xscale = this._yscale=100*ratio;
           this.swapDepths(1000-z);
          };
          Pic = new Array();
          for (var i = 1; i<=10; i++) {
           mc = scene.attachMovie("pic"+i, "pic"+i, scene.depth++);//導(dǎo)入10個(gè)圖標(biāo),做成影片剪輯
           mc.x = 1000-Math.random()*1000;
           mc.y = 1000-Math.random()*1000;
           mc.z = i*500;
           mc.onRelease = selectPic;
           mc.display = displayPic;
           Pic.push(mc);
          }
          scene.onEnterFrame = function() {
           cameraView.x += (cameraView.target.x-cameraView.x)/5;
           cameraView.y += (cameraView.target.y-cameraView.y)/5;
           cameraView.z += (cameraView.target.z-cameraView.z)/5;//緩沖公式
           for (var i = 0; i<=Pic.length; i++) {
           Pic.display(cameraView, d);
           }
          }; [/color]

          這里是swf文件:3d2.swf ,接下來的這倆個(gè)例子,都是利用了鏡頭的概念,你可以利用鍵盤的方向鍵來控制看看效果。

          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體


          以上的例子雖然有了點(diǎn)3d的效果了,但是都是直來直去,并沒有涉及到旋轉(zhuǎn)的效果,那么接下來我們?cè)僦v一下物體在三維空間里的旋轉(zhuǎn)效果是如何制作的,.我們把旋轉(zhuǎn)分成三種情況來講,繞X軸,繞Y軸,繞Z軸旋轉(zhuǎn),首先講一下繞X軸旋轉(zhuǎn),如圖:

          uploads/200704/30_201245_21.gif

          點(diǎn)A繞X軸旋轉(zhuǎn)b到達(dá)點(diǎn)B,X坐標(biāo)的值是不變的,即x1=x,OA=OB=r,再這里首先要說兩個(gè)數(shù)學(xué)里三角函數(shù)的公式:
          sina=對(duì)邊/斜邊,
          cosa=鄰邊/斜邊,.
          sin(a+b)=sina*cosb+cosa*sinb,
          cos(a+b)=cosa*cosb-sina*sinb,
          所以點(diǎn)A的坐標(biāo):
          y=r*sina,
          z=r*cosa,
          旋轉(zhuǎn)后B點(diǎn)的坐標(biāo):
          y1=r*sin(a+b),
          z1=r*cos(a+b),
          最后得到旋轉(zhuǎn)后B點(diǎn)的坐標(biāo)與旋轉(zhuǎn)前A點(diǎn)坐標(biāo)的關(guān)系:
          y1=y*cosb+z*sinb,
          z1=z*cosb-y*sinb,
          這個(gè)公式很重要,在3d效果里涉及到旋轉(zhuǎn)都要用到這個(gè)公式,
          同樣我們還可以計(jì)算出饒Y軸旋轉(zhuǎn)的公式:
          x1=x*cosb+z*sinb,
          z1=z*cosb-x*sinb,

          uploads/200704/30_201311_22.gif

          繞Z軸旋轉(zhuǎn)的公式:
          x1=x*cosb+y*sinb,
          y1=y*cosb-x*sinb,
          有了以上的知識(shí),我們就可以做一個(gè)空間旋轉(zhuǎn)的例子,在主場景加入以下代碼:

          uploads/200704/30_201332_23.gif

          [color=Red] this.createEmptyMovieClip("Scene", 1);
          Scene._x = 150;
          Scene._y = 150;
          d = 300;//眼睛和屏幕之間的距離,試著調(diào)整看有什么變化
          make3DPoint = function(x,y,z){
           var point = new Object();
           point.x = x;
           point.y = y;
           point.z = z;
           return point;
          };
          make2DPoint = function(x, y, depth, ratio){
           var point = new Object();
           point.x = x;
           point.y = y;
           point.depth = depth;
           point.ratio = ratio;
           return point;
          };
          Transform3DPointsTo2DPoints = function(points, rotations){
           var myArray = [];
           var sx = Math.sin(rotations.x);
           var cx = Math.cos(rotations.x);
           var sy = Math.sin(rotations.y);
           var cy = Math.cos(rotations.y);
           var sz = Math.sin(rotations.z);
           var cz = Math.cos(rotations.z);
           var x,y,z, xy,xz, yx,yz, zx,zy, ratio;
           var i = points.length;
           while (i--){
           x = points.x;
           y = points.y;
           z = points.z;
           xy = cx*y - sx*z;
           xz = sx*y + cx*z;
           yz = cy*xz - sy*x;
           yx = sy*xz + cy*x;
           zx = cz*yx - sz*xy;
           zy = sz*yx + cz*xy;//旋轉(zhuǎn)后的坐標(biāo)值
           ratio = d/(d + yz);
           x = zx*ratio;
           y = zy*ratio;//再轉(zhuǎn)化為二維坐標(biāo)
           z = yz;
           myArray = make2DPoint(x, y, -z, ratio);
           }
           return myArray;
          };//以上三個(gè)函數(shù)很重要,因?yàn)樵诖蠖鄶?shù)3d效果的例子里都能用到,可以說是公式了,尤其是最后一個(gè)
          pointsArray = [
           make3DPoint(-50,-50,-50),
           make3DPoint(50,-50,-50),
           make3DPoint(50,-50,50),
           make3DPoint(-50,-50,50),
           make3DPoint(-50,50,-50),
           make3DPoint(50,50,-50),
           make3DPoint(50,50,50),
           make3DPoint(-50,50,50)
          ];//正方體四個(gè)頂點(diǎn)的坐標(biāo)
          for (i=0; i<pointsArray.length; i++){
           attachedObj =Scene.attachMovie("ball", "ball"+i, i);
          }//畫一個(gè)小球,轉(zhuǎn)化為影片剪輯
          myRotations = make3DPoint(0,0,0);
          Scene.onEnterFrame = function(){
           myRotations.y -= this._xmouse/2000;
           myRotations.x += this._ymouse/2000;//鼠標(biāo)互動(dòng),你也可以調(diào)整2000這個(gè)值讓它轉(zhuǎn)的更快或者更慢,也可以換成固定值
           var screenPoints = Transform3DPointsTo2DPoints(pointsArray, myRotations);
           for (i=0; i<pointsArray.length; i++){
           myball = this["ball"+i];
           myball._x = screenPoints.x;
           myball._y = screenPoints.y;
           myball._xscale = myball._yscale = 100 * screenPoints.ratio;
           myball.swapDepths(screenPoints.depth);
           }
          };[/color]

          按Ctrl+Enter效果就出來了,是不是很酷啊?
          這是swf文件:3d3.swf

          Media 點(diǎn)擊播放/隱藏媒體

          當(dāng)然我們可以再加點(diǎn)東西,在剛才的onEnterFrame事件后再加以下代碼看看又會(huì)如何:
          [color=Red]this.clear();
           this.lineStyle(2, 0xff0000, 100);
           // 頂面的四條線
           this.moveTo(screenPoints[0].x, screenPoints[0].y);
           this.lineTo(screenPoints[1].x, screenPoints[1].y);
           this.lineTo(screenPoints[2].x, screenPoints[2].y);
           this.lineTo(screenPoints[3].x, screenPoints[3].y);
           this.lineTo(screenPoints[0].x, screenPoints[0].y);
           // 底面的四條線
           this.moveTo(screenPoints[4].x, screenPoints[4].y);
           this.lineTo(screenPoints[5].x, screenPoints[5].y);
           this.lineTo(screenPoints[6].x, screenPoints[6].y);
           this.lineTo(screenPoints[7].x, screenPoints[7].y);
           this.lineTo(screenPoints[4].x, screenPoints[4].y);
           // 把頂面和第面用四條線連起來
           this.moveTo(screenPoints[0].x, screenPoints[0].y);
           this.lineTo(screenPoints[4].x, screenPoints[4].y);
           this.moveTo(screenPoints[1].x, screenPoints[1].y);
           this.lineTo(screenPoints[5].x, screenPoints[5].y);
           this.moveTo(screenPoints[2].x, screenPoints[2].y);
           this.lineTo(screenPoints[6].x, screenPoints[6].y);
           this.moveTo(screenPoints[3].x, screenPoints[3].y);
           this.lineTo(screenPoints[7].x, screenPoints[7].y);
           //以上代碼是一個(gè)簡單的畫圖程序 [/color]

          再加點(diǎn)東西,在上面的畫圖程序里加上以下倆句看有什么:
          [color=Red]this.beginFill(0x00ff00,80);
          this.endFill(); [/color]

          這是swf文件:3d3B.swf "3d3C.swf

          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體


          從上面的例子里我們把a(bǔ)s畫圖和3d效果結(jié)合起來,那么我們接下來就專門講一下這方面的例子,用純粹的as 做一些3d效果,先畫一個(gè)旋轉(zhuǎn)的正方形,在第一幀加入以下的代碼:
          [code][/code] this.createEmptyMovieClip("theScene", 1);
          theScene._x = 150;
          theScene._y = 150;
          d = 300;
          make3DPoint = function(x,y,z){
          var point = new Object();
          point.x = x;
          point.y = y;
          point.z = z;
          return point;
          };
          make2DPoint = function(x, y){
          var point = new Object();
          point.x = x;
          point.y = y;
          return point;
          };
          Transform3DPointsTo2DPoints = function(points,rotations){
          var myArray = [];
          var sx = Math.sin( rotations.x);
          var cx = Math.cos( rotations.x);
          var sy = Math.sin( rotations.y);
          var cy = Math.cos( rotations.y);
          var sz = Math.sin( rotations.z);
          var cz = Math.cos( rotations.z);
          var x,y,z, xy,xz, yx,yz, zx,zy, ratio;
          var i = points.length;
          while (i--){
          x = points.x;
          y = points.y;
          z = points.z;
          xy = cx*y - sx*z;
          xz = sx*y + cx*z;
          yz = cy*xz - sy*x;
          yx = sy*xz + cy*x;
          zx = cz*yx - sz*xy;
          zy = sz*yx + cz*xy;
          ratio = d/(d + yz);
          x = zx*ratio;
          y = zy*ratio;
          myArray = make2DPoint(x, y);
          }
          return myArray;
          };
          pointsArray = [
          make3DPoint(-50,-50,-50),
          make3DPoint(50,-50,-50),
          make3DPoint(50,-50,50),
          make3DPoint(-50,-50,50),
          make3DPoint(-50,50,-50),
          make3DPoint(50,50,-50),
          make3DPoint(50,50,50),
          make3DPoint(-50,50,50)
          ];
          myRotations = make3DPoint(0,0,0);

          theScene.onEnterFrame = function(){
          myRotations.y -= this._xmouse/3000;
          myRotations.x += this._ymouse/3000;
          var screenPoints = Transform3DPointsTo2DPoints(pointsArray, myRotations);
          this.clear();
          this.lineStyle(2,0xff0000,100);
          // top
          this.moveTo(screenPoints[0].x, screenPoints[0].y);
          this.lineTo(screenPoints[1].x, screenPoints[1].y);
          this.lineTo(screenPoints[2].x, screenPoints[2].y);
          this.lineTo(screenPoints[3].x, screenPoints[3].y);
          this.lineTo(screenPoints[0].x, screenPoints[0].y);
          // bottom
          this.moveTo(screenPoints[4].x, screenPoints[4].y);
          this.lineTo(screenPoints[5].x, screenPoints[5].y);
          this.lineTo(screenPoints[6].x, screenPoints[6].y);
          this.lineTo(screenPoints[7].x, screenPoints[7].y);
          this.lineTo(screenPoints[4].x, screenPoints[4].y);
          // connecting bottom and top
          this.moveTo(screenPoints[0].x, screenPoints[0].y);
          this.lineTo(screenPoints[4].x, screenPoints[4].y);
          this.moveTo(screenPoints[1].x, screenPoints[1].y);
          this.lineTo(screenPoints[5].x, screenPoints[5].y);
          this.moveTo(screenPoints[2].x, screenPoints[2].y);
          this.lineTo(screenPoints[6].x, screenPoints[6].y);
          this.moveTo(screenPoints[3].x, screenPoints[3].y);
          this.lineTo(screenPoints[7].x, screenPoints[7].y);
          };


          這是swf文件:3d4.swf

          Media 點(diǎn)擊播放/隱藏媒體


          看看這段程序和上面的程序是不是很相似,其實(shí)只要你掌握了其中的原理,只需要把里面的東西作一些相應(yīng)的變換就可以做成你自己想的很酷的效果,現(xiàn)在我再把上 面的程序稍做調(diào)整,原碼我就不寫了,你可以自己考慮一下.上面做的都是正方形,如果把坐標(biāo)做相應(yīng)的調(diào)整,還可以做成其它立體圖形,比如三角形,五角形等, 關(guān)于單純的由線條組成的立體圖形現(xiàn)在看來很簡單,只要你知道各個(gè)點(diǎn)的坐標(biāo)就可以用以上的方法做出來,當(dāng)然你還可以把它填充起來,比如上面的那個(gè)正方體.現(xiàn) 在我就利用beginFill()和endFill()這倆個(gè)方法在上面的基礎(chǔ)把這個(gè)立方體填充起來.把上面的立方體去掉線條,只留下三個(gè)面,又是另一個(gè) 效果:這是swf文件:3d4B.swf " 3d4C.swf

          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體


          當(dāng)然你也可以利用以上的知識(shí)自己做一些很酷的效果,只需要將上面的坐標(biāo)坐標(biāo)變換一下就能做出很多圖形,下面是我做的一個(gè)平面五角星和一個(gè)只有線條的立體五角星,因?yàn)樽鴺?biāo)是我自己用苯辦法算出里的,所以有點(diǎn)不大像.

          Media 點(diǎn)擊播放/隱藏媒體


          Media 點(diǎn)擊播放/隱藏媒體


          Media 點(diǎn)擊播放/隱藏媒體

          下面這個(gè)立體圖形的坐標(biāo)我給出來看大家能不能自己做出來.
          v1(15.9689,-22.1275,-0.135825),
          v2(-15.3241,-22.1275,-0.135825),
          v3(15.9689,1.32056e-006,21.9917),
          v4(-15.3241,1.32255e-006,21.9917),
          v5(-15.3241,-1.31526e-006,-22.2633),
          v6(15.9686,-1.31725e-006,-22.2633),
          v7(15.9686,22.1275,-0.135827),
          v8(-15.3241,22.1275,-0.135827),
          v9(0.322368,-84.0845,83.9487),
          v10(0.322369,-84.0845,-84.2204),
          v11(119.236,0.0,-0.135826),
          v12(0.322368,84.0845,-84.2204),
          v13(0.322386,84.0845,83.9487),
          v14(-118.591,0,-0.135826)
          一共有十四個(gè)點(diǎn),組成二十四個(gè)面,下面是每個(gè)面對(duì)應(yīng)的那幾個(gè)點(diǎn):
          fa1=9,fb1=1,fc1=3,fa2=9,fb2=3,fc2=4,fa3=9,fb3=4,fc3=2,fa4=9,fb4=2,fc4=1,fa5=10,fb5=2,fc5=5,
          fa6=10,fb6=5,fc6=6,fa7=10,fb7=6,fc7=1,fa8=10,fb8=1,fc8=2,fa9=11,fb9=6,fc9=7,fa10=11,fb10=7,fc10=3,
          fa11=11,fb11=3,fc11=1,fa12=11,fb12=1,fc12=6,fa13=12,fb13=6,fc13=5,fa14=12,fb14=5,fc14=8,
          fa15=12,fb15=8,fc15=7,fa16=12,fb16=7,fc16=6,fa17=13,fb17=8,fc17=4,fa18=13,fb18=4,fc18=3,
          fa19=13,fb19=3,fc19=7,fa20=13,fb20=7,fc20=8,fa21=14,fb21=8,fc21=5,fa22=14,fb22=5,fc22=2,
          fa23=14,fb23=2,fc23=4,fa24=14,fb24=4,fc24=8

          這是我做的幾個(gè)例子:swf文件:3d10.swf "3d10B.swf "3d10C.swf

          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體


          做旋轉(zhuǎn)的六面體還有另一種做法,前面的那中方法,做出來的實(shí)際并不逼真,下面先看看我用另一個(gè)方法做出來的例子看與這個(gè)有什么區(qū)別呢,代碼如下:
          [color=Red] this.createEmptyMovieClip("theScene", 1);
          theScene._x = 150;
          theScene._y = 150;
          d = 300;
          make3DPoint = function(x,y,z){
           var point = new Object();
           point.x = x;
           point.y = y;
           point.z = z;
           return point;
          };
          make2DPoint = function(x,y){
           var point = new Object();
           point.x = x;
           point.y = y;
           return point;
          };
          isVisibleBetween = function(a,b,c){
           if (((b.y-a.y)/(b.x-a.x)-(c.y-a.y)/(c.x-a.x)<0)^(a.x<=b.x == a.x>c.x)){
           return true;
           }else{
           return false;
           }
          };[/color]

          // 這個(gè)函數(shù)很重要,你不必知道它的原理,只要知道怎么用就可以了,其實(shí)我也不知道怎么解釋它,但是這個(gè)函數(shù)可以根據(jù)一個(gè)平面上任意三個(gè)點(diǎn)的坐標(biāo)而判斷該平面 是否看的見,因?yàn)橐粋€(gè)立體圖形在平面上最多可以顯示三個(gè)面,所以就必須判斷你可以看的那三個(gè)面,這個(gè)函數(shù)不僅可以用在四面體上,不管有多少面的立體圖形都 可以用這個(gè)公式:
          [color=Red] drawFilledSquare = function(a,b,c,d){
           this.clear();
           this.lineStyle(2,0,100);
           if (isVisibleBetween(a,b,c)){
           this.moveTo(a.x, a.y);
           this.beginFill(this.col, 100);
           this.lineTo(b.x, b.y);
           this.lineTo(c.x, c.y);
           this.lineTo(d.x, d.y);
           this.lineTo(a.x, a.y);
           this.endFill();
           }
          };[/color]

          //這里就是上面函數(shù)的應(yīng)用,如果這個(gè)面看的見就畫出它,
          //下面的程序基本上就成為了一種固定的形式了:
          [color=Red]Transform3DPointsTo2DPoints = function(points, axisRotations){
           var myArray = [];
           var sx = Math.sin(axisRotations.x);
           var cx = Math.cos(axisRotations.x);
           var sy = Math.sin(axisRotations.y);
           var cy = Math.cos(axisRotations.y);
           var sz = Math.sin(axisRotations.z);
           var cz = Math.cos(axisRotations.z);
           var x,y,z, xy,xz, yx,yz, zx,zy, scaleRatio;
           var i = points.length;
           while (i--){
           x = points.x;
           y = points.y;
           z = points.z;
           xy = cx*y - sx*z;
           xz = sx*y + cx*z;
           yz = cy*xz - sy*x;
           yx = sy*xz + cy*x;
           zx = cz*yx - sz*xy;
           zy = sz*yx + cz*xy;
           scaleRatio = d/(d + yz);
           x = zx*scaleRatio;
           y = zy*scaleRatio;
           myArray = make2DPoint(x, y);
           }
           return myArray;
          };
          pointsArray = [
           make3DPoint(-50,-50,-50),
           make3DPoint(50,-50,-50),
           make3DPoint(50,-50,50),
           make3DPoint(-50,-50,50),
           make3DPoint(-50,50,-50),
           make3DPoint(50,50,-50),
           make3DPoint(50,50,50),
           make3DPoint(-50,50,50)
          ];
          rollOverFace = function(){
           this.col = 0xff0000;
          };
          rollOutFace = function(){
           this.col = 0xdddddd;
          };
          for (i=0; i<6; i++){
           emptyFace = theScene.createEmptyMovieClip("face"+i,i);
           emptyFace.col = 0xdddddd;
           emptyFace.onRollOver = emptyFace.onDragOver = rollOverFace;
           emptyFace.onRollOut = emptyFace.onDragOut = rollOutFace;
           emptyFace.onPress = pressFace;
           emptyFace.draw = drawFilledSquare;
          }
          cubeAxisRotations = make3DPoint(0,0,0);

          theScene.onEnterFrame = function(){
           cubeAxisRotations.y -= this._xmouse/3000;
           cubeAxisRotations.x += this._ymouse/3000;
           var pts2D = Transform3DPointsTo2DPoints(pointsArray, cubeAxisRotations);
           this.face0.draw(pts2D[0], pts2D[3], pts2D[2], pts2D[1]);
           this.face1.draw(pts2D[4], pts2D[5], pts2D[6], pts2D[7]);
           this.face2.draw(pts2D[0], pts2D[4], pts2D[7], pts2D[3]);
           this.face3.draw(pts2D[3], pts2D[7], pts2D[6], pts2D[2]);
           this.face4.draw(pts2D[2], pts2D[6], pts2D[5], pts2D[1]);
           this.face5.draw(pts2D[1], pts2D[5], pts2D[4], pts2D[0]);
          }; [/color]

          這是swf文件:3d5.swf
          Media 點(diǎn)擊播放/隱藏媒體


          現(xiàn)在我們?cè)侔焉厦娴淖鴺?biāo)換成三角形的坐標(biāo),再把最后畫圖的部分也做一下調(diào)整,那么就很容易做成一個(gè)旋轉(zhuǎn)的的四面體了,具體調(diào)整如下:
          [color=Red] pointsArray = [
           make3DPoint(-50,87,29),
           make3DPoint(0,87,-58),
           make3DPoint(50,87,29),
           make3DPoint(0,0,0)
           ];//這是坐標(biāo)部分
          this.face0.draw(pts2D[0], pts2D[1], pts2D[2]);
           this.face1.draw(pts2D[0], pts2D[3], pts2D[1]);
           this.face2.draw(pts2D[1], pts2D[3], pts2D[2]);
           this.face3.draw(pts2D[2], pts2D[3], pts2D[0]);
          //這是畫圖部分[/color]

          這是swf文件:3d6.swf .下面的幾個(gè)例子也是在此基礎(chǔ)上擴(kuò)展的:3d6C.swf ;最后來個(gè)超酷的飛機(jī),這可是純AS做的哦:3d7B.swf .

          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體


          上面的例子比較常見,當(dāng)然還有一些其它的效果,我現(xiàn)在再給大家連出一些這方面的例子:
          有投影的三維效果:3DB2.swf " 3DF.swf
          有彈性的立體小球:3DD.swf
          可以拖動(dòng)的小球:3DA.swf
          最后是我做的兩個(gè),一個(gè)是可以用鍵盤方向鍵控制旋轉(zhuǎn)的立體DNA,另一個(gè)是我用BitmapData類做的空間旋轉(zhuǎn)的立方體. DNA_exam2.swf "3d9.swf

          Media 點(diǎn)擊播放/隱藏媒體


          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體

          Media 點(diǎn)擊播放/隱藏媒體
          posted on 2008-11-21 10:48 seal 閱讀(505) 評(píng)論(1)  編輯  收藏 所屬分類: Flex+ActionScript

          評(píng)論

          # re: 3dflash原理(轉(zhuǎn)) 2008-12-15 01:24 dancingracie
          yun....ju ran da bu chu zhong wen,han a ...
          da gai shi ji qi you wen ti..

          zheng zai xue xi xiangguan dongdong ,zhenghao kandao bozhu de wenzhang ,xie de hen zixi ,hen hao de shuo,xue xi le ,fei chang ganxie   回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 永德县| 台北县| 阳朔县| 利川市| 永宁县| 浦江县| 宣恩县| 丰原市| 手游| 吉林市| 佛冈县| 八宿县| 伊通| 大荔县| 抚宁县| 吴堡县| 巴马| 巴中市| 石首市| 平顶山市| 宜黄县| 巴林右旗| 崇文区| 道孚县| 隆化县| 堆龙德庆县| 桐庐县| 马公市| 安仁县| 梨树县| 万安县| 波密县| 黔东| 临武县| 贞丰县| 沙田区| 喀喇沁旗| 方城县| 锦屏县| 临夏县| 平罗县|