Home > 梅原 > Matrix3D.recompose()

Matrix3D.recompose()

20091213
Category:梅原 /Tags:

recomposeMatrix3D.recompose()メソッドについて
http://help.adobe.com/ja_JP/AS3LCR/Flash_10.0/flash/geom/Matrix3D.html#recompose()

実体行列.recompose([平行移動、回転、および拡大 / 縮小],回転方法の指定)
 
処理としては
eulerAngles to Matrix3D
axisAngle to Matrix3D
quaternion to Matrix3D
を行う。
 
 
拡大 / 縮小エレメントのをかけかたに
プレイヤーのバージョンによって違いがあるっぽい。
MAC 10,0,2,54ではappendScale
MAC 10,0,12,36ではprependScale
のように処理しているので、それに合わせて分岐処理をしている。

実制作の場合には気をつけないといけなさそう。

helpには「拡大 / 縮小エレメントのいずれかが 0 の場合は、false を返します。」
とあるがtrueしか返さないっぽい、、
 
 
◆関連項目
Matrix3D.decompose()
 

▼Wonderfl

▼ActionScript AS3(FP9)

/*
Matrix3D.recompose();
と同じ機能の関数を作ってみる。
MAC 10,0,2,54,MAC 10,0,12,36で動作確認。

処理としては
eulerAngles to Matrix3D
axisAngle to Matrix3D
quaternion to Matrix3D
を行う。

拡大 / 縮小エレメントのをかけかたに
プレイヤーのバージョンによって違いがあるっぽい。
MAC 10,0,2,54ではappendScale
MAC 10,0,12,36ではprependScale
のように処理しているので、それに合わせて分岐処理をしている。

実制作の場合には気をつけないといけなさそう。

helpには「拡大 / 縮小エレメントのいずれかが 0 の場合は、false を返します。」
とあるがtrueしか返さないっぽい、、

各要素をrandomで値を入れて、recomposeし、
行列の各要素を比較して確認とした。

Matrix3D.recompose()

http://help.adobe.com/ja_JP/AS3LCR/Flash_10.0/flash/geom/Matrix3D.html#recompose()

*/
package {
	import flash.display.Sprite;
	import flash.geom.Matrix3D;
	import flash.geom.Orientation3D;
	import flash.text.TextField;
	import flash.geom.Vector3D;
	import flash.system.Capabilities;
	public class FlashTest extends Sprite {
		public function FlashTest() {
			var txt:String="◆同機能関数Mtrx3D.recompose "+Capabilities.version+"での実行結果\n\n";

			//確認用の値を用意
			var entityMatrix3D:Matrix3D=new Matrix3D(Util.random9());
			var entity1:Matrix3D=new Matrix3D();
			var entity2:Matrix3D=new Matrix3D();
			var orientationStyle:String;
			if (Math.random()<1/3) {
				orientationStyle="eulerAngles";
			} else if (Math.random()<1/2) {
				orientationStyle="axisAngle";
			} else {
				orientationStyle="quaternion";
			}
			var entity:Vector.<Vector3D>=entityMatrix3D.decompose(orientationStyle);

			// == "10,0,2,54"
//			entity[2].x = 0;
//			entity[2].y = 0;
//			entity[2].z = 0;

			//実行
			entity1.recompose(entity,orientationStyle);
			Mtrx3D.recompose(entity2,entity,orientationStyle);

			//確認
			txt+="orientationStyle = "+orientationStyle+"で確認\n\n";
			var entity1RawData:Vector.<Number>=entity1.rawData;
			txt+="↓Matrix3D.recomposeの結果\n"+entity1RawData+"\n";
			var entity2RawData:Vector.<Number>=entity2.rawData;
			txt+="\n↓同機能関数Mtrx3D.recomposeの結果\n"+entity2RawData+"\n\n";
			txt+=Util.hikaku(entity1RawData,entity2RawData);

			//テキストフィールドを作りtxtを流し込み。
			var tf:TextField = new TextField();
			tf.width=stage.stageWidth;
			tf.height=stage.stageHeight;
			tf.wordWrap=true;
			stage.addChild(tf);
			tf.text=txt;
		}
	}
}
import flash.display.Sprite;
class Mtrx3D extends Sprite {
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	import flash.system.Capabilities;
	public static function recompose(entity:Matrix3D,components:Vector.<Vector3D>, orientationStyle:String = "eulerAngles"):Boolean {

		//プレヤーのバージョンによって乗算の仕方が違うっぽい。
		var ver_array:Array = Capabilities.version.substr(4).split(",");
		var scale:Vector.<Number>=new Vector.<Number>(16,true);
		if(int(ver_array[2])*1000+int(ver_array[3]) > 2054){
			//prependScale的な乗算
			scale[0] = scale[1] = scale[2] = components[2].x;
			scale[4] = scale[5] = scale[6] = components[2].y;
			scale[8] = scale[9] = scale[10] = components[2].z;
		}else{
			//10,0,2,54以下の場合はこちら
			//appendScale的な乗算
			scale[0] = scale[4] = scale[8] = components[2].x;
			scale[1] = scale[5] = scale[9] = components[2].y;
			scale[2] = scale[6] = scale[10] = components[2].z;
		}
		trace(scale)

		var v:Vector.<Number>=new Vector.<Number>(16,true);
		if (orientationStyle=="eulerAngles") {
			//eulerAngles to Matrix3D
			var cx:Number=Math.cos(components[1].x);
			var cy:Number=Math.cos(components[1].y);
			var cz:Number=Math.cos(components[1].z);
			var sx:Number=Math.sin(components[1].x);
			var sy:Number=Math.sin(components[1].y);
			var sz:Number=Math.sin(components[1].z);
			v[0]=cy*cz*scale[0];
			v[1]=cy*sz*scale[1];
			v[2]=- sy*scale[2];
			v[3]=0;
			v[4] = (sx*sy*cz-cx*sz)*scale[4];
			v[5] = (sx*sy*sz+cx*cz)*scale[5];
			v[6]=sx*cy*scale[6];
			v[7]=0;
			v[8] = (cx*sy*cz+sx*sz)*scale[8];
			v[9] = (cx*sy*sz-sx*cz)*scale[9];
			v[10]=cx*cy*scale[10];
			v[11]=0;
			v[12]=components[0].x;
			v[13]=components[0].y;
			v[14]=components[0].z;
			v[15]=1;
		} else {
			//"quaternion" to Matrix3D
			var x:Number=components[1].x;
			var y:Number=components[1].y;
			var z:Number=components[1].z;
			var w:Number=components[1].w;
			if (orientationStyle=="axisAngle") {
				//"axisAngle" to Matrix3D
				x*=Math.sin(w/2);
				y*=Math.sin(w/2);
				z*=Math.sin(w/2);
				w=Math.cos(w/2);
			}
			v[0] = (1-2*y*y-2*z*z)*scale[0];
			v[1] = (2*x*y+2*w*z)*scale[1];
			v[2] = (2*x*z-2*w*y)*scale[2];
			v[3]=0;
			v[4] = (2*x*y-2*w*z)*scale[4];
			v[5] = (1-2*x*x-2*z*z)*scale[5];
			v[6] = (2*y*z+2*w*x)*scale[6];
			v[7]=0;
			v[8] = (2*x*z+2*w*y)*scale[8];
			v[9] = (2*y*z-2*w*x)*scale[9];
			v[10] = (1-2*x*x-2*y*y)*scale[10];
			v[11]=0;
			v[12]=components[0].x;
			v[13]=components[0].y;
			v[14]=components[0].z;
			v[15]=1;
		}
		//v[0],v[4],v[8]が三つとも0だと
		//ArgumentError: Error #2188: 行マトリックスが無効です。マトリックスは反転可能である必要があります。
		//というエラーでMatrix3Dを作れないので、設定可能な最小値を入れている。
		//0.000000000000000000000000000000000000000000001;
		//これは1e-45と書ける。
		//ただしx,y,z三つとも1e-45には設定できないので、1e-15にしてる。
		if(components[2].x == 0){v[0] = 1e-15};
		if(components[2].y == 0){v[5] = 1e-15};
		if(components[2].z == 0){v[10] = 1e-15};
		entity.rawData = v;
		//helpには拡大 / 縮小エレメントのいずれかが 0 の場合は、false を返します。
		//とあるがtrueしか返さないっぽい、、
		//return !(components[2].x == 0 || components[2].y == 0 || components[2].y == 0)
		return true;
	}
}
class Util {
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	public static function hikaku(v0:Vector.<Number>,v1:Vector.<Number>):String {
		var _str:String="↓二つのMatrix3Dの要素毎の差\n";
		var _n:int=v0.length;
		for (var i:int=0; i<_n; i++) {
			_str += "["+i+"]:"+(v0[i]-v1[i])+"\n";
		}
		return _str;
	}

	public static function random16():Vector.<Number> {
		var _v:Vector.<Number>=new Vector.<Number>(16,true);
		for (var i:int=0; i<16; i++) {
			_v[i]=Math.random()*200-100;
		}
		return _v;
	}
	public static function random9():Vector.<Number> {
		var _mt:Matrix3D = new Matrix3D();
		var v:Vector.<Vector3D>=new Vector.<Vector3D>  ;
		v[0]=new Vector3D(200*Math.random()-100,200*Math.random()-100,200*Math.random()-100);//平行移動、
		v[1]=new Vector3D(10*Math.random()-5,10*Math.random()-5,10*Math.random()-5);//回転
		v[2]=new Vector3D(100*Math.random(),100*Math.random(),100*Math.random());//拡大 / 縮小
		_mt.recompose(v);
		return _mt.rawData;
	}
}

関連記事:

Comments are closed.