Beautifl - Flash Gallery

Thumbnail : [Stardust][PV3D] Depth of field
[Stardust][PV3D] Depth of field
paq 2010-01-14 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

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;}
	}
}