PaperVision3D 2.0で被写界深度が実現できたよ

Papervision3D 2.0(GreateWhite)を試していたら、いつの間にか求めていたプロパティが実装されているではありませんか。filtersとsceneZという、なんとも被写界深度が実装できそうなプロパティ。というわけで被写界深度を早速試してみました。今まで苦労したのが嘘のように簡単にできました♪

Demo(require Flash Player 9)


仕様については以下にまとめております。

ポイントはuseOwnContainer

DisplayObject3Dに実装されている「useOwnContainer」というプロパティがありますが、これをtrueにすることでfilterやalphaの使用が可能となります。

var o:Plane = new Plane(new ColorMaterial(), 100, 100, 1, 1);
o.useOwnContainer = true;
o.filters = [new BlurFilter()];
o.alpha = 0.5;

filterにBlurFilterを適用することで「ぼかし」が再現できます。

3D空間内の絶対座標に変換されたプロパティscreenX,screenY,screenZ

ネストされた構造の3Dオブジェクトでも、絶対座標が上記プロパティにより取得ができます。通常のZ座標(例:obj.z)だとローカル座標ですが、screenZ(例:obj.screenZ)ではlocalToGlobal的な絶対座標(3D)となります。これをぼかしの材料に使います。

被写界深度表現の実現

ここまで値が取得できれば、もう力技でも適用してみるだけです。私は基準位置から3DオブジェクトのZ座標がどのくらい離れているかの値をブラーフィルターに適用しました。

var o:DisplayObject3D = list[i] as DisplayObject3D;
var blur:Number = Math.ceil((基準ポジション値 – o.sceneZ) / 調整する数値);
o.filters = [new BlurFilter(blur, blur, 1)];

デモのソース

package
{
	import flash.display.*;
	import flash.events.*;
	import flash.filters.*;

	import org.papervision3d.view.*;
	import org.papervision3d.materials.*;
	import org.papervision3d.objects.*;
	import org.papervision3d.objects.primitives.*

    [SWF(width = "450", height = "250", frameRate = "60", backgroundColor = "#000000")]

	public class Main extends BasicView
	{
		// const vars
		static private const OBJ_LENGTH   :int = 20;
		static private const CIRCLE_RANGE :int = 500;

		// 3d vars
		private var list :Array = []
		private var wrap :DisplayObject3D;

		/**
		 * Constructor
		 */
		public function Main()
		{
			super(450, 250);

			// init swf
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align     = StageAlign.TOP_LEFT;
			stage.quality   = StageQuality.HIGH;

			init();
		}

		public function init():void
		{
			//camera
			camera.focus     = 400;
			camera.zoom      = 1;
			camera.x         = 0;
			camera.y         = 200;
			camera.z         = 1000;
			camera.rotationX = 5;

			// wrap
			wrap = new DisplayObject3D();
			scene.addChild(wrap);

			for (var i:int = 0; i < OBJ_LENGTH; i++)
			{
				var rot:Number = 360 * i / OBJ_LENGTH ;

				var m:ColorMaterial = new ColorMaterial(0x0066CC);
				m.doubleSided = true;

				var o:Plane = new Plane(m, 100, 100, 2, 2);
				o.x = CIRCLE_RANGE * Math.sin(rot * Math.PI / 180);
				o.y = 0;
				o.z = CIRCLE_RANGE * Math.cos(rot * Math.PI / 180);
				o.rotationY = rot;
				o.useOwnContainer = true; //ココ重要

				wrap.addChild(o);
				list.push(o);
			}

			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
			startRendering();
		}

		private function enterFrameHandler(event:Event):void
		{
			wrap.yaw(-1);
			for (var i:int = 0; i < list.length; i++)
			{
				var o:DisplayObject3D = list[i] as DisplayObject3D;
				var blur:Number = Math.ceil((CIRCLE_RANGE - o.sceneZ) / 50);
				o.filters = [new BlurFilter(blur, blur, 2)];
			}
		}
	}
}

※別途Papervision3D 2.0(GreateWhite)とFlex SDK3(Flash CS3でも可)が必要です。
このあたりで紙面いっぱいなので、次回に続きます。

大変参考になったリンク

PV3Dの関連記事

投稿者 : 池田 泰延

BookMark

いかがでしたでしょうか、ブックマークはこちらからどうぞ。

このエントリーをはてなブックマークに追加

Comment/Trackback 2件

  • フラスコ » Twilight より:

    […] throw Life – Papervision3d入門 Motion().lab » PV3D::HelloWord Papervision3D の Materials(2) ~ graphics コマンド系 ~【閃光的網站・弛緩複合体 -Review Division-】 PV3Dまとめ(超基礎) 【カメラとは】 | [FlaTech+]WebDesign Rainyday PaperVision3D 2.0で被写界深度が実現できたよ | ClockMaker Blog […]

  • 乐多夫设计 | 博客 | REX » Blog Archive » 继续百威项目 より:

    […] 通的代码去写,但是没法和酒瓶配合出立体的效果。无奈只好放弃 随后用papervision去写。为了给plane加模糊的滤镜。必须加上下面这句。参照这篇文章以及wonderfl上面的例子 p1.useOwnContainer=true; […]