Papervision3D specTest

2010.03.17 | flash, papervision3d

今までPapervision3Dでつくってきた経験を元に、自分がよく使い動作に影響を及ぼす要素を検証してみます。

まず、基本となるソース。
Cubeを4x4x4で配置し、それぞれの面に異なるmaterialを割り当てています。Cubeの面の分割数は2。
ポリゴン数が多く、materialが複数設定されている場合を想定しています。
http://wonderfl.net/code/93fcf……d6198241fb

これをforkして設定を変え動作を比較してみます。
createViewportLayerでviewportLayerを作った場合。
materialのinteractiveをtrueにした場合。
materialのanimeをtrueにした場合。
materialのsegment数の変更、precise, smoothの適用。

viewportLayerオブジェクトに対してalphaやfilterなどを使う場合に使用します。
3Dオブジェクトに対してalphaやfilterを適用する場合。被射界深度の表現などに使用します。

materialのinteractiveは、3Dオブジェクトに対してのインタラクションを使用する場合。
サンプルでは、3DオブジェクトをクリックするとviewportLayerに対してblurを適用しています。

materialのanimeは3Dオブジェクトのmaterialをアニメーションさせるかどうか設定します。
trueと設定すると、materialで使用されているbitmapdataが毎フレームごとに更新されます。
サンプルでは、それぞれの面にmouseOverするとmaterialの色を変更しています。

いくつか代表的なものを。下にいけばいくほど重いです。
●_createViewPortLayer = true; _interactive = true;
http://wonderfl.net/code/d3f0c……a17ca7e61c

●_interactive = true; _anime = true;
http://wonderfl.net/code/f59d9……a9f0a6d2bc

●_createViewPortLayer = true;_interactive = true; _anime = true;
http://wonderfl.net/code/4f043……47332f49d5

●materialのクオリティを高くするために
segments: 1; mat.precise = true; smooth = true; に変更
http://wonderfl.net/code/df561……15b04a397f

●全てを適用。(かなり重いので注意)
http://wonderfl.net/code/4f043……47332f49d5

一番動作に関係するのは、materialのanimeです。
createViewPortLayerは経験的にもっと重くなるかと思いましたが、
今回のサンプルでは、重くはなりますがそこまでは変わりませんでした。

動作を早くするためによくやるのは、levelOfDetailを使って描画するポリゴン数やmaterialの解像度を減らす。
animeに関しては、必要な時にだけanimeを有効にする。
これは、smoothやpreciseも同じです。cameraとの距離が近いとテクスチャの歪みや解像度の粗は目立ちます。そこでcameraとの位置関係でこれらのオンオフをコントロールして、見えと速度のバランスをとっていきます。

また、空間全体がダイナミックに動くものはアニメーションしている間だけmaterialやstageの画質を下げrenderingし、アニメーションが終了したら画質を下げてrenderingを停止するなど。

とはいえ、それはわりと調整に時間がかかったり、コードが複雑になりがちです。

検証用の基本のスクリプトは以下

/**
_createViewPortLayer = false;
_interactive = false;
_anime = false;
*/
package  
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import net.hires.debug.Stats;
	import org.papervision3d.events.InteractiveScene3DEvent;
	import org.papervision3d.materials.MovieMaterial;
	import org.papervision3d.materials.utils.MaterialsList;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Cube;
	import org.papervision3d.view.BasicView;
	
	[SWF(backgroundColor="#ffffff", frameRate=60)]
	public class Pv3dTest extends BasicView
	{
		private var field:DisplayObject3D;
		private var _createViewPortLayer:Boolean = false;
		private var _interactive:Boolean = false;
		private var _anime:Boolean = false;
		
		public function Pv3dTest() 
		{
			field = new DisplayObject3D();
			field.name = "field";
			scene.addChild(field);
			
			viewport.interactive = _interactive;
			
			camera.z = -480;
			camera.useClipping = true;
			camera.useCulling = true;
			
			_createRandomCubes();
			
			this.startRendering();
			this.addEventListener(Event.ENTER_FRAME, update);
			this.addChild(new Stats());
		}
		
		private function update(e:Event):void 
		{
			field.rotationY += 0.3;
		}
		
		private function _createRandomCubes():void
		{
			var objs:Array = [];
			var size:Number = 60;
			var alpha:Number = 1.0;
			
			var p:Number = 2.75;
			var num:int = 4;
			
			var offset:Number = -(size * p * (num - 1)) / 2;
			/*
			var colors:Array = [];
			for (var n:int = 0; n < 6; n++) {
				colors.push(0xffffff * Math.random());
			}
			*/
			for (var i:int = 0; i < num; i++) {
				for (var j:int = 0; j < num; j++) {
					for (var k:int = 0; k < num; k++) {
						
						var f0_:Sprite = new TestTexture();
						var f1_:Sprite = new TestTexture();
						var f2_:Sprite = new TestTexture();
						var f3_:Sprite = new TestTexture();
						var f4_:Sprite = new TestTexture();
						var f5_:Sprite = new TestTexture();
						
						var isAnime:Boolean = _anime;
						var interactive:Boolean = _interactive;
						var f0Mat:MovieMaterial = new MovieMaterial(f0_, false, isAnime);
						var f1Mat:MovieMaterial = new MovieMaterial(f1_, false, isAnime);
						var f2Mat:MovieMaterial = new MovieMaterial(f2_, false, isAnime);
						var f3Mat:MovieMaterial = new MovieMaterial(f3_, false, isAnime);
						var f4Mat:MovieMaterial = new MovieMaterial(f4_, false, isAnime);
						var f5Mat:MovieMaterial = new MovieMaterial(f5_, false, isAnime);
						f0Mat.interactive = interactive;
						f1Mat.interactive = interactive;
						f2Mat.interactive = interactive;
						f3Mat.interactive = interactive;
						f4Mat.interactive = interactive;
						f5Mat.interactive = interactive;
						
						var matList:MaterialsList = new MaterialsList();
						matList.addMaterial(f0Mat ,"front");
						matList.addMaterial(f1Mat ,"back");
						matList.addMaterial(f2Mat ,"left");
						matList.addMaterial(f3Mat ,"right");
						matList.addMaterial(f4Mat ,"top");
						matList.addMaterial(f5Mat ,"bottom");
						
						var cube:Cube = new Cube(matList, f0_.width, f0_.width, f0_.width, 2, 2, 2);
						if(_createViewPortLayer){
							cube.container = cube.createViewportLayer(viewport);
						}
						if(_interactive){
							cube.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, _rollOverHandler);
						}
						cube.x = i * size * p + offset;
						cube.y = j * size * p + offset;
						cube.z = k * size * p + offset;
						
						_startCubeAnime(cube);
						
						field.addChild(cube);
						
						objs.push(cube);
					}
				}
			}
		}
		
		private function _rollOverHandler(e:InteractiveScene3DEvent):void 
		{
			Cube(e.target).container.filters = [new BlurFilter(12, 12)];
		}
			
		
		private function _startCubeAnime(cube_:Cube):void
		{
			this.addEventListener(Event.ENTER_FRAME, function():void { cube_.rotationX += 1.5; cube_.rotationY += 1.0;} );
		}
	}

}

//
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	
	import caurina.transitions.properties.ColorShortcuts;
	import caurina.transitions.Tweener;
	/**
	 * ...
	 * @author inoook
	 */
	internal class TestTexture extends Sprite
	{
		public function TestTexture(str:String = "") 
		{			
			ColorShortcuts.init();
			
			var g:Graphics = this.graphics;
			var size:Number = 50;
			g.beginFill(Math.random()*0xffffff);
			g.drawRect(-size/2, -size/2, size, size);
			g.endFill();
			
			g.beginFill(Math.random()*0xffffff);
			g.drawCircle(0,0, size*0.4);
			g.endFill();
			/*
			this.addEventListener(MouseEvent.ROLL_OVER, _mouseOverHandler);
			this.addEventListener(MouseEvent.ROLL_OUT, _mouseOutHandler);
			
			this.addEventListener(MouseEvent.CLICK, _mouseClickHandler);
			*/
		}
		
		private function _mouseClickHandler(e:MouseEvent):void 
		{
			Tweener.addTween(this, { 
				_color:0xff0000,
				time:1, 
				transition:"linear",
				onComplete:function():void {
					
				}
			} );
		}
		
		private function _mouseOverHandler(e:MouseEvent):void 
		{
			//this.alpha = 0.3;
			Tweener.addTween(this, { 
				_color:0x00ff00,
				time:0.5, 
				transition:"linear",
				onComplete:function():void {
					
				}
			} );
		}
		
		private function _mouseOutHandler(e:MouseEvent):void 
		{
			//this.alpha = 1.0;
			Tweener.addTween(this, { 
				_color:null,
				time:0.5, 
				transition:"linear",
				onComplete:function():void {
					
				}
			} );
		}
		
	}

There are no comments.

Please Leave a Reply

TrackBack URL :

pagetop