« Spark project 勉強会 #01 いってきました | MAIN | [as]ちらっとBox2D »

[as]Matrix の scale と rotate のこと

frocessingでは、Matrixを拡張してFMatrix2Dというクラスをつくっているのですが、その過程でどうもオリジナルの matrix.scale() と Matrix.rotate() が遅いんじゃないかと思いまして、以下試してみたものです。

とりあえずテスト用につくったもので、オリジナル(ori)と scale,translate,rotateをoverrideして実装しなおしたもの(ext)を、それぞれfor文でまわしたものです。影響が出そうな、createBox, createGradientBox についても比較しています。それぞれ10万回実行しています。

自分の環境では、translateは大体同じだけど、scale と rotate 及び影響が出ていると思われる box系で随分処理時間に差が出ています。どうでしょうか?

実際には10万回なんて実行しないので、現実的には差がないように思えますが、とりあえずメモということで。

以下実装し直した TestMatrix と 上のテストで使用したスクリプトです。

TestMatrix.as

package{
	
	import flash.geom.Matrix;
	
	public class TestMatrix extends Matrix
	{
		
		public function TestMatrix( a_:Number=1, b_:Number=0, c_:Number=0, d_:Number=1, tx_:Number=0, ty_:Number=0)
		{
			super( a_, b_, c_, d_, tx_, ty_ );
		}
		
		override public function translate( dx:Number, dy:Number ):void
		{
			//(1,0,0,1,dx,dy)
			tx += dx;
			ty += dy;
		}
		
		override public function scale( sx:Number, sy:Number ):void
		{
			//(sx,0,0,sx,0,0)
			a  *= sx;
			b  *= sy;
			c  *= sx;
			d  *= sy;
			tx *= sx;
			ty *= sy;
		}
		
		override public function rotate( angle:Number ):void
		{
			//(c, s, -s, c, 0, 0)
			var sin:Number = Math.sin(angle);
			var cos:Number = Math.cos(angle);
			var n11:Number = a * cos - b * sin;
			var n12:Number = a * sin + b * cos;
			var n21:Number = c * cos - d * sin; 
			var n22:Number = c * sin + d * cos;
			var n31:Number = tx * cos - ty * sin; 
			var n32:Number = tx * sin + ty * cos;
			a  = n11; b  = n12;
			c  = n21; d  = n22;
			tx = n31; ty = n32;
		}
	}
}

テストコード

//ベタなテストですいません
//out_txtはTextFieldです

var n:int = 50000;
var t:int;
var i:int;

var fmt:TestMatrix = new TestMatrix( 1, 2, 3, 4, 5, 6 );
var mt:Matrix = new Matrix( 1, 2, 3, 4, 5, 6 );

//---------------------------------------------
out_txt.appendText( "[SCALE]");

t = getTimer();
for( i=0; i<n; i++ )
{
	mt.scale( 10, 10 ); mt.scale( 0.1,0.1 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i<n; i++ )
{
	fmt.scale(10,10); fmt.scale(0.1,0.1);
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[TRANSLATE]");
t = getTimer();
for( i=0; i<n; i++ )
{
	mt.translate( 10, 10 ); mt.translate( -10,-10 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i<n; i++ )
{
	fmt.translate(10,10); fmt.translate(-10,-10);
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[ROTATE]");
t = getTimer();
for( i=0; i<n; i++ )
{
	mt.rotate( 1.5 ); mt.rotate( -1.5 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i<n; i++ )
{
	fmt.rotate(1.5); fmt.rotate(-1.5);
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[CREATE_BOX]");
t = getTimer();
for( i=0; i<n; i++ )
{
	mt.createBox( 10, 10, 1, 1, 1 );
	mt.createBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i<n; i++ )
{
	fmt.createBox( 10, 10, 1, 1, 1 );
	fmt.createBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

//---------------------------------------------
out_txt.appendText( "\n[CREATE_GRADIENT_BOX]");
t = getTimer();
for( i=0; i<n; i++ )
{
	mt.createGradientBox( 10, 10, 1, 1, 1 );
	mt.createGradientBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( "\n ori: " + (getTimer()-t).toString() );

t = getTimer();
for( i=0; i<n; i++ )
{
	fmt.createGradientBox( 10, 10, 1, 1, 1 );
	fmt.createGradientBox( 0.1, 0.1, -1, -1, -1 );
}
out_txt.appendText( " ext: " + (getTimer()-t).toString() );

テストの方法が微妙な気がしますが、いいベンチマークの方法があったら知りたい…

COMMENT+

いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。

TRACKBACK

URL : http://nutsu.com/cgi/mt/mt-tb.cgi/88