Matrix3D.recompose()

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)
[sourcecode language=”as3″]
/*
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;
}
}
[/sourcecode]