Beautifl - Flash Gallery

Preview

[Stardust][PV3D] Depth of field
paq 2010年1月14日 MIT License
?
@see		http://clockmaker.jp/blog/2008/08/papervision3d_focus_blur/  
@see		http://wonderfl.net/code/d22f0f92eb9390b6f6ef84b808ab923f2e467137  
@author	paq89
      package {
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.BlurFilter;
    import idv.cjcat.stardust.common.clocks.SteadyClock;
    import idv.cjcat.stardust.threeD.papervision3d.renderers.PV3DDisplayObject3DRenderer;
    import org.papervision3d.core.effects.view.ReflectionView;
    import org.papervision3d.objects.DisplayObject3D;

    /**
     * @see        http://clockmaker.jp/blog/2008/08/papervision3d_focus_blur/
     * @see        http://wonderfl.net/code/d22f0f92eb9390b6f6ef84b808ab923f2e467137
     * @author    paq89
     */
    
    [SWF(width=465, height=465, backgroundColor=0x001122, frameRate=60)]
    public class Main extends ReflectionView
    {
        private var _container:DisplayObject3D;
        private var _emitter:PlaneEmitter;
        private var _particlesList:Array = [];
        private var _blurFilter:Array = [];
        
        /**
         * コンストラクタ
         */
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        /**
         * ...
         */
        private function init():void
        {
            // PV3D
            _container = new DisplayObject3D();
            scene.addChild(_container);
            opaqueBackground = 0x001122;
            
            // カメラ
            camera.zoom = 2;
            camera.focus = 200;
            
            // 反射のアルファ
            viewportReflection.alpha = 0.5;
            
            // 軽量化のため、フィルターをあらかじめ作っておく
            for (var i:int = 0; i < 20; i++) 
            {
                _blurFilter[i] = new BlurFilter(i, i, 1);
            }
            
            // パーティクルシステムの構築
            _emitter = new PlaneEmitter(new SteadyClock(0.1), _particlesList);
            var renderer:PV3DDisplayObject3DRenderer = new PV3DDisplayObject3DRenderer(_container);
            renderer.addEmitter(_emitter);
            
            // イベントリスナー
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        }
        
        /**
         * エンターフレームイベント
         */
        private function onEnterFrame(e:Event):void 
        {
            // エミッター更新
            _emitter.step();
            
            // Papervision3Dのレンダリング
            singleRender();
            
            // 被写界深度
            setBlur();
        }
        
        /**
         * マウスの位置に合わせてカメラを移動
         */
        private function onMouseMove(e:MouseEvent):void 
        {
            camera.x += (2000 * Math.sin(mouseX / stage.stageWidth * 360 * Math.PI / 180) - camera.x) * .1;
            camera.z += (2000 * Math.cos(mouseX / stage.stageWidth * 360 * Math.PI / 180) - camera.z) * .1;
            camera.y += (2000 * mouseY / stage.stageHeight - camera.y) * .1;
        }
        
        /**
         * 被写界深度
         */
        private function setBlur():void 
        {
            var len:int = _particlesList.length;
            for (var i:int = 0; i < len; i++) 
            {
                var o:DisplayObject3D = _particlesList[i];
                if (!o.visible) o.visible = true;
                
                // 距離の算出
                var deg:Number = Math.abs(calcPointDistanceFromCamera(o) - 2000);
                
                // ぼかしの適用値
                var blurVal:int = Math.min(20, deg * 0.008 << 1 ) >> 0;;
                if (blurVal > 19) blurVal = 19;
                var blurFilter:BlurFilter = _blurFilter[blurVal];
                
                // フィルター適用
                o.filters = [blurFilter];
            }
        }
        
        /**
         * カメラからの距離を算出します
         * @param    obj 計測したいオブジェクト
         * @return    カメラからの距離(3D空間内のpx値)
         */
        private function calcPointDistanceFromCamera(obj:DisplayObject3D):Number
        {
            var vecX:Number = obj.sceneX - camera.x;
            var vecY:Number = obj.sceneY - camera.y;
            var vecZ:Number = obj.sceneZ - camera.z;
            return Math.sqrt((vecX * vecX) + (vecY * vecY) + (vecZ * vecZ));
        }
    }
}

//------------------------------------------------------------------------------------------------

import frocessing.color.ColorHSV;
import idv.cjcat.stardust.common.actions.Age;
import idv.cjcat.stardust.common.actions.CompositeAction;
import idv.cjcat.stardust.common.actions.DeathLife;
import idv.cjcat.stardust.common.actions.ScaleCurve;
import idv.cjcat.stardust.common.clocks.Clock;
import idv.cjcat.stardust.common.initializers.Life;
import idv.cjcat.stardust.common.initializers.Scale;
import idv.cjcat.stardust.common.math.UniformRandom;
import idv.cjcat.stardust.threeD.actions.Deflect3D;
import idv.cjcat.stardust.threeD.actions.Gravity3D;
import idv.cjcat.stardust.threeD.actions.Move3D;
import idv.cjcat.stardust.threeD.actions.Spin3D;
import idv.cjcat.stardust.threeD.deflectors.PlaneDeflector;
import idv.cjcat.stardust.threeD.emitters.Emitter3D;
import idv.cjcat.stardust.threeD.fields.UniformField3D;
import idv.cjcat.stardust.threeD.initializers.DisplayObjectClass3D;
import idv.cjcat.stardust.threeD.initializers.Omega3D;
import idv.cjcat.stardust.threeD.initializers.Position3D;
import idv.cjcat.stardust.threeD.initializers.Rotation3D;
import idv.cjcat.stardust.threeD.initializers.Velocity3D;
import idv.cjcat.stardust.threeD.zones.SinglePoint3D;
import idv.cjcat.stardust.threeD.zones.SphereCap;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.objects.primitives.Plane;

//------------------------------------------------------------------------------------------------

/**
 * プレーンをひたすら出し続けるEmitter
 * 
 * @author    paq89
 */
class PlaneEmitter extends Emitter3D
{
    public function PlaneEmitter(clock:Clock, particlesList:Array)
    {
        super(clock);
        
        var doc3D:DisplayObjectClass3D = new DisplayObjectClass3D();
        doc3D.displayObjectClass = PlaneParticle;
        doc3D.constructorParams = [null, 100, 100, 1, 1, particlesList];
        
        var cap:SphereCap = new SphereCap(0, 0, 0, 50, 50, 15);
        cap.rotationX = 180;
        
        var rotationRand:UniformRandom = new UniformRandom(0, 180);
        var omegaRand:UniformRandom = new UniformRandom(0, 4);
        
        // パーティクルの属性を定義
        addInitializer(doc3D);
        addInitializer(new Life(new UniformRandom(200, 0)));
        addInitializer(new Scale(new UniformRandom(1, 1.2)));
        addInitializer(new Position3D(new SinglePoint3D(0, 0, 0)));
        addInitializer(new Velocity3D(cap));
        addInitializer(new Rotation3D(rotationRand, rotationRand, rotationRand));
        addInitializer(new Omega3D(omegaRand, omegaRand, omegaRand));
        
        // 重力を定義
        var field:UniformField3D = new UniformField3D(0, -1, 0);
        var gravity:Gravity3D = new Gravity3D();
        gravity.addField(field);
        
        // デフレクトを定義
        var deflect:Deflect3D = new Deflect3D();
        deflect.addDeflector(new PlaneDeflector(0, 90, 0, 0, 1, 0));
        
        // パーティクルのアクションを定義
        addAction(gravity);
        addAction(deflect);
        addAction(new Age());
        addAction(new DeathLife());
        addAction(new Move3D());
        addAction(new Spin3D());
        addAction(new ScaleCurve(5, 20));
    }
}

class PlaneParticle extends Plane
{
    static private var col:int = 180;
    public function PlaneParticle(material:MaterialObject3D = null, width:Number = 0, height:Number = 0, segmentsW:Number = 0, segmentsH:Number = 0, particlesList:Array = null):void 
    {
        var color:ColorHSV = new ColorHSV(col += 2, 0.8);
        
        // マテリアルを作成
        var mat:WireframeMaterial = new WireframeMaterial(color.value);
        mat.doubleSided = true;
        
        super(mat, width, height, segmentsW, segmentsH);
        
        useOwnContainer = true;
        if (particlesList){ particlesList.push(this); visible = false;}
    }
}