forked from: simple 3D 02 (not using PV3D)

by hiragana forked from simple 3D 02 (not using PV3D) (diff: 2)
PV3Dとかを使わない3D表現その2
PixelじゃなくてBitmapを使う。Arrayを使ってZソートしとこう。
少し数値がおかしいんであとで修正。
♥0 | Line 124 | Modified 2011-10-30 17:22:28 | MIT License | (replaced)
play

Related images

ActionScript3 source code

/**
 * Copyright hiragana ( http://wonderfl.net/user/hiragana )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wx40
 */

// forked from sakef's simple 3D 02 (not using PV3D)
/*
PV3Dとかを使わない3D表現その2
PixelじゃなくてBitmapを使う。Arrayを使ってZソートしとこう。
少し数値がおかしいんであとで修正。
*/
package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.filters.BlurFilter;
    import flash.geom.Point;
    import net.wonderfl.utils.SequentialLoader;
    
    [SWF(width="465", height="465", backgroundColor="0xffffff", frameRate="30")]
    public class simple3d_02 extends Sprite
    {
        private const FOCUS:Number=370;
        private const RADIUS:Number=180;
        private const N_POINT1:int=8;
        private const N_POINT2:int=10;
        private const N_POINT3:int=N_POINT1 * N_POINT2;
        private const CENTER_X:int=465 / 2;
        private const CENTER_Y:int=465 / 2;
        private const W:int=465;
        private const H:int=465;
        private const RADIAN:Number=Math.PI / 180;
        private const N_BLUR_IMG:int=30;
        private const STEP:Number=RADIUS / N_BLUR_IMG;
        private const imgURL:String="http://assets.wonderfl.net/images/related_images/0/00/00b3/00b30adf53ec9d9d805c0311de854b6b79e4fe73";
        
        private var ballAry:Array;
        private var imgAry:Array;
        private var imgs:Array;
        
        public function simple3d_02()
        {
            imgs=[];
            SequentialLoader.loadImages([imgURL], imgs, onLoaded);
        }
        
        private function onLoaded():void
        {
            var i:int;
            var j:int;
            ballAry=[];
            imgAry=[];
            
            // 画像の読み込み
            var ldr:Loader=imgs.pop();
            var ballImg:BitmapData=(ldr.content as Bitmap).bitmapData;
            
            // ブラー付きのBitmapDataを先に作っておくべ。
            var p:Point=new Point;
            for(i=0; i < N_BLUR_IMG; i++)
            {
                var tmp:BitmapData=ballImg.clone();
                tmp.applyFilter(tmp, tmp.rect, p, new BlurFilter(0.4 * i, 0.4 * i));
                imgAry[i]=tmp;
            }
            
            // 各点の初期位置を計算
            for(i=0; i < N_POINT1; i++)
            {
                var theta1:Number=(360 / N_POINT1) * i * RADIAN;
                for(j=0; j < N_POINT2; j++)
                {
                    var theta2:Number=((180 / N_POINT2) * j - 90) * RADIAN;
                    var xx:Number=RADIUS * Math.cos(theta2) * Math.sin(theta1);
                    var yy:Number=RADIUS * Math.sin(theta2);
                    var zz:Number=RADIUS * Math.cos(theta2) * Math.cos(theta1);
                    var ball:Ball3D=new Ball3D(ballImg, xx, yy, zz);
                    ballAry[i * N_POINT2 + j]=ball;
                    addChild(ball);
                }
            }
            addEventListener(Event.ENTER_FRAME, onFrame);
        }
        
        private function onFrame(e:Event):void
        {
            // 座標計算
            for(var i:int=0; i < N_POINT3; i++)
            {
                var ball:Ball3D=ballAry[i]as Ball3D;
                
                // 回転行列で回転 (x軸回転とy軸回転の積を展開したもの)
                var tmpX:Number=ball.xx * Math.cos(RADIAN) + ball.yy * Math.sin(RADIAN) * Math.sin(RADIAN) - ball.zz * Math.sin(RADIAN) * Math.cos(RADIAN);
                var tmpY:Number=ball.yy * Math.cos(RADIAN) + ball.zz * Math.sin(RADIAN);
                var tmpZ:Number=ball.xx * Math.sin(RADIAN) - ball.yy * Math.sin(RADIAN) * Math.cos(RADIAN) + ball.zz * Math.cos(RADIAN) * Math.cos(RADIAN);
                
                // 3D→2D変換 
                var scale:Number=FOCUS / (FOCUS + tmpZ);
                var xx:int=int(tmpX * scale) + CENTER_X;
                var yy:int=int(tmpY * scale) * (-1) + CENTER_Y;
                
                ball.scaleX=ball.scaleY=scale;
                ball.x=xx;
                ball.y=yy;
                
                // BitmapDataの更新
                var tmp:int=int(tmpZ / STEP);
                tmp=(tmp > 0) ? (tmp) : (-1 * tmp);
                tmp=(tmp >= N_BLUR_IMG) ? (N_BLUR_IMG - 1) : (tmp);
                ball.bitmapData=imgAry[tmp]as BitmapData;
                
                // 座標の保存
                ball.yy=tmpY;
                ball.zz=tmpZ;
                ball.xx=tmpX;
            }
            
            // zソート
            ballAry.sortOn("zz", Array.NUMERIC | Array.DESCENDING);
            for(i=0; i < N_POINT3; i++)
            {
                ball=ballAry[i]as Ball3D;
                setChildIndex(ball, i)
            }
            
        }
    }
}

import flash.display.Bitmap;
import flash.display.BitmapData;

class Ball3D extends Bitmap
{
    public var xx:Number;
    public var yy:Number;
    public var zz:Number;
    public var sort:Number;
    private var w:Number;
    private var h:Number;
    
    public function Ball3D(bmpd:BitmapData=null, xx:Number=0, yy:Number=0, zz:Number=0)
    {
        this.xx=xx;
        this.yy=yy;
        this.zz=zz;
        bitmapData=bmpd;
        w=bmpd.width / 2;
        h=bmpd.height / 2;
    }
    
    override public function set x(value:Number):void
    {
        super.x=value - w;
    }
    
    override public function set y(value:Number):void
    {
        super.y=value - h;
    }
}