AS3 2D转3D【算法】

发布时间:2019-09-23 17:05:45编辑:auto阅读(1675)

    FLASH只是有二维的坐标.怎么把三维坐标转换成二维坐标:
    (一).公式
        给定点:(x,y,z)
        绕x轴旋转后的点(x1,y1,z1)
        绕y轴旋转后的点(x2,y2,z2)
        绕z轴旋转后的点(x3,y3,z3)
     1.x旋转(x不变):
     x1=x
     y1=y*cosb+z*sinb
     z1=z*cosb-y*sinb
        2.y旋转(y不变):
     x2=x*cosb-z*sinb
     y2=y
     z2=z*cosb+x*sinb
        3.z旋转(z不变)
        x3=x*cosb-y*sinb
     y3=y*cosb+x*sinb
     z3=z
     
    (二).原理分析
    1.三角形定理:
    如上图,已知一个点(x,y,z),利用三角形相似的原理,可以得出下列结论:
      d/(d+z)=y1/y,推出:y1=d*y/(d+z),可在二维平面上来表现空间上的点的位置。进一步把它简化。提出因子d/(d+z),用ratio(比率)表示,这个公式就变为
      ratio=d/(d+z);
      y1=ratio*y;同理可推出
      x1=ratio*x;
     
    2.flash模拟3D坐标:
    如上图,z轴表示一个物体离屏幕的远近,当物体的z轴位置增加时,物体朝远离屏幕的方向运动,当物体的z值减小时,物体朝接近屏幕的方向运动。在三维坐标中,当z值增大,也就是远离屏幕时,物体应越小,反之越大。我们可以用上面的ratio,当z增加时,ratio减少,因为在ratio中,z是作为分母的。反之,当z减少时,ratio增加。所以可用ratio来控制mc的大小。z值最大,物体应在最底层,最小,在最上层。
     
    3.公式推导:
    旋转有三种,x旋转:坐标x不变,y旋转:y不变,z旋转:z不变,我们先来推导z旋转。如上图:从点(x,y,0)转到(x1.y1.0),求点(x1.y1.0)
    利用数学中的正弦、余弦公式得出
      x1=r*cos(a+b),而cos(a+b)=sina*cosb+cosa*sinb
      推出:x1=r(cosa*cosb-sina*sinb)
      又因为x=r*cosa,y=r*sina
      所以x1=x*cosb-y*sinb
      同样推出:y1=y*cosb+x*sinb
      这就是z旋转的公式。用同样的方法可推出x旋转,y旋转的公式。总结如下:
    给定点:(x,y,z)
    绕x轴旋转后的点(x1,y1,z1)
    绕y轴旋转后的点(x2,y2,z2)
    绕z轴旋转后的点(x3,y3,z3)
     x旋转(x不变)
     x1=x
     y1=y*cosb-z*sinb
     z1=z*cosb+y*sinb
    注:是先加后减,因为FLASH里的Y轴是反的,箭头向下的。 即:
     y1=y*cosb+z*sinb
     z1=z*cosb-y*sinb
     
    同理推出:
     y旋转(y不变)
     x2=x*cosb-z*sinb
     y2=y
     z2=z*cosb+x*sinb

     z旋转(z不变)
     x3=x*cosb-y*sinb
     y3=y*cosb+x*sinb
     z3=z
      从以上公式可看出,在flash要实现旋转,先要求x轴的旋转点,再求y轴的旋转点,最后再求出z轴的旋转点。
     
    (三).实例应用
    最后我们来一个y旋转的AS3应用(复制代码到时间轴即可)
    // 全局变量
    var mcNums:Number=3;
    var mcArr:Array = new Array();
    var rocArr_x:Array=new Array(100,-100,0);
    var rocArr_y:Array=new Array(0,10,0);
    var rocArr_z:Array=new Array(-100,0,0);
    var hutu:Number=0.001;// 控制旋转的速度
    var jiaodu:Number=hutu*180/Math.PI;
    var distance:int=1000;

    initConfig();

    //初始化
    function initConfig():void {
      for (var i=1; i<=mcNums; i++) {
        var t:MovieClip=doDrawRoundRect(); 
        //t.angle = i * ((Math.PI*2)/mcNums);
        this.addChild(t);
        mcArr.push( t );
      }
      addEventListener(Event.ENTER_FRAME, EnterFrame);
    }

    //刷频
    function EnterFrame(e:Event) {
      for (var i = 0; i<mcNums; i++) {
        // 按公式计算
        var x1=rocArr_x[i]*Math.cos(jiaodu)-rocArr_z[i]*Math.sin(jiaodu);
        var y1=rocArr_y[i];
        var z1=rocArr_z[i]*Math.cos(jiaodu)+rocArr_x[i]*Math.sin(jiaodu);
        //赋值
        rocArr_x[i]=x1;
        rocArr_y[i]=y1;
        rocArr_z[i]=z1;
        // 更新数组元素
        var ratio:Number = distance/(distance+z1);
        var perspective_x=x1*ratio;
        var perspective_y=y1*ratio;
        var perspective_z=z1*ratio;
        // 赋值X Y坐标 
        mcArr[i].x=stage.stageWidth/2+perspective_x;
        mcArr[i].y=stage.stageHeight/2-perspective_y;
        // mc的大小
        mcArr[i].scaleX=mcArr[i].scaleY=80*ratio/100;
        mcArr[i].alpha=50*ratio
        // mc的层次
        this.setChildIndex(mcArr[i],ratio);
      }
    }

    //产生随机颜色的矩形影片
    function doDrawRoundRect():MovieClip {
      var size:uint=80;
      var bgColor:uint=Math.random()*0xffffff;
      var borderColor:uint=0x666666;
      var borderSize:uint=0;
      var cornerRadius:uint=9;
      var gutter:uint=5;
      var child:MovieClip = new MovieClip();
      child.graphics.beginFill(bgColor);
      child.graphics.lineStyle(borderSize, borderColor);
      child.graphics.drawRoundRect(0, 0, size, size, cornerRadius);
      child.graphics.endFill();
      return child;
    }

     
     

关键字