PV3Dでパーティクルタイポグラフィ表現

Papervision3Dを使って、パーティクル生成を試してみました。下のFlashをクリックすると再生が始まります。

以前、AfterEffectsのパーティクルプレイグラウンドを使ってこの表現を試してみたのですが、いつかFlashで再現してみたいと思って作ってみました。Flashで一番やってみたかったのは被写界深度で文字をぼかすことです。ただ、やり方がわからずパーティクルのサイズで判別してブラーをかけました。http://blog.r3c7.net/?p=178の記事によるとAway3DだとZ-depth filterという機能があるらしく、名前から想像するにまさに求めているものなので、次回試してみたいと思います。

今回のソースコースはこちらから。↓

ソースコード

package
{
    // Papervision3D
    import org.papervision3d.cameras.*;
    import org.papervision3d.core.proto.*;
    import org.papervision3d.events.*;
    import org.papervision3d.materials.*;
    import org.papervision3d.objects.*;
    import org.papervision3d.scenes.*;
    
    // Tweener
    import caurina.transitions.Tweener;
    
    // Flash
    import flash.display.*;
    import flash.events.*;
    import flash.filters.*;
    import flash.text.*;
    import flash.utils.*;

    [SWF(width="450",height="300",frameRate="60",backgroundColor="#000000")]
    
    public class PV3DSample extends Sprite
    {
        // 定数
        private const PARTICLE_ROUND   :int = 250;
        private const PARTICLE_AMOUNT  :int = 2;
        private const PARTICLE_INTERVAL:int = 50;
        private const MOUSE_INTERVAL   :int = 50;
        private const FONT_SIZE        :int = 72;
        
        // 3D定義
        private var scene      :Scene3D;
        private var camera     :Camera3D;
        private var container  :DisplayObject3D;
        
        // マウス追随用の変数
        private var oldX:Number;
        private var oldY:Number;
        
        // 背景画像
        /*
        [Embed(source="asset/bg.png")]
        private var BackGround:Class;
        */

        /**
         * コンストラクタ 
         */            
        public function PV3DSample()
        {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align     = StageAlign.TOP_LEFT;
            stage.quality   = StageQuality.LOW;
            
            stage.addEventListener(MouseEvent.CLICK, init);
            
            //addChild(new BackGround());
        }
        
        /**
         * 初期化 
         * @param event
         */        
        private function init(event:MouseEvent):void
        {
            // マウスクリックを解除
            stage.removeEventListener(MouseEvent.CLICK, init);
            
            // コンテナ作成
            var world:Sprite = new Sprite();
            addChild(world);
            
            // 3D初期化
            // ピクセル等倍になる距離 = camera.focus * camera.zoom - camera.focus
            scene = new Scene3D(world);
            container = new DisplayObject3D();
            camera  = new Camera3D(container,2,200,{x:0, y:0, z:-200});
            
            // レンダリング
            stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            
            // パーティクル生成タイマー
            var particleTimer:Timer = new Timer(PARTICLE_INTERVAL);
            particleTimer.start();
            particleTimer.addEventListener(TimerEvent.TIMER, createParticle );
            
            // マウス追随タイマー
            var mouseTimer:Timer = new Timer(MOUSE_INTERVAL);
            mouseTimer.start();
            mouseTimer.addEventListener(TimerEvent.TIMER, drawMouseLine );
        }
        
        /**
         * 3Dレンダリング 
         * @param event
         */    
        private function onEnterFrame(event:Event):void
        {
            scene.renderCamera(camera);
        }
        
        /**
         * パーティクル生成 
         * @param event
         */        
        private function createParticle(event:TimerEvent):void
        {
            // 親を生成(マウス座標に配置)
            var wrap:DisplayObject3D = new DisplayObject3D();
            wrap.x =  stage.mouseX + 12;
            wrap.y = -stage.mouseY - 12;
            
            for(var i:int=0; i FONT_SIZE * .8)       mc.filters = [ new BlurFilter(8, 8, 3) ]
                else if(fontsize > FONT_SIZE * .6) mc.filters = [ new BlurFilter(4, 4, 2) ]
                
                var material:MovieMaterial = new MovieMaterial(mc, true,{doubleSided:false, smooth:false} );
                
                var obj:Plane = new Plane(material, 50, 50, 0, 0);
                Tweener.addTween(obj,
                {
                    x : Math.random()*PARTICLE_ROUND - PARTICLE_ROUND/2,
                    y : 500, 
                    z : Math.random()*PARTICLE_ROUND - PARTICLE_ROUND/2,
                    time       : 3,
                    transition : "easeInExpo",
                    onCompleteParams:[wrap, obj],
                    onComplete : function(w:DisplayObject3D, o:Plane):void{ w.removeChild(o) }
                });
                
                wrap.addChild(obj);
                
            }
            scene.addChild(wrap);
        }
        
        /**
         * マウス追随を描画 
         * @param event
         */        
        private function drawMouseLine(event:TimerEvent):void
        {
            var sp:Sprite = new Sprite();
            sp.graphics.lineStyle(1, 0x99CC00);
            sp.graphics.moveTo(oldX, oldY);
            sp.graphics.lineTo(mouseX, mouseY);
            addChild(sp);
            
            oldX = mouseX;
            oldY = mouseY;
            
            Tweener.addTween(sp,
            {
                alpha      : 0,
                time       : 3,
                onComplete : function():void{ removeChild(sp); }
            });
        }
    }
}

はてなの仕様で</pp>という意味もないタグが上記ソースに入っていますので、上記ソースをお試しになる際は取り除いてください。