Home > 梅原 > Matrix3Dの1/20,20のバグ

Matrix3Dの1/20,20のバグ

20090727
Category:梅原 /Tags:

Matrix3Dの1/20,20のバグMatrix3DはAS3.0(FP10)から追加されたクラスで、3Dの座標処理を行う際に使う。とても便利なんだけど、バグがある。
プラグインのバージョンアップと共に改善はされているんだけど、一気に直ったわけでもないのでそれはそれで困り者。
このエントリーでは、現状をとりあえずまとめてみる。

 

どんなバグか

Matrix3Dで処理した結果、値が1/20または、20倍になる。
例えば画面中央で写真が回転するモーションを作ったつもりが、他のPCで見たら20倍の大きさ、画面いっぱいに拡大されてしまっている、なんてことが起こる。
↓英語版のhelpで指摘されてるけど、関係ないレスが返って来ている。
http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/geom/Matrix3D.html#transpose()
このtransposeに関する問題は10.0.22.87では修正されたから、バグであるのは間違いない。
ただ、それ以前のプラグインに最適化して作っていたら、最新のプラグインでは1/20の写真になってしまった、という状況が起こっているはず。
こちらにも指摘がある。
http://www.dango-itimi.com/blog/archives/2008/000966.html

 

もうちょっと詳しく

例えば、Matrix3D内の値を入れ替えるだけのメソッド、transposeのはずなのに一部の値が、1/20,20倍して帰ってくる。上記の英語のhelpで指摘されているのはコレ。
へんな挙動を再現するとこんな感じ↓

function _transpose(mt:Matrix3D):void {
	var m:Vector.<Number>=mt.rawData;
	var v:Vector.<Number>=new Vector.<Number>(16,true);
	v[0]=m[0];
	v[1]=m[4];
	v[2]=m[8];
	v[3]=m[12]*20;
	v[4]=m[1];
	v[5]=m[5];
	v[6]=m[9];
	v[7]=m[13]*20;
	v[8]=m[2];
	v[9]=m[6];
	v[10]=m[10];
	v[11]=m[14]*20;
	v[12]=m[3]/20;
	v[13]=m[7]/20;
	v[14]=m[11]/20;
	v[15]=m[15];
	mt.rawData=v;
}

 

1/20,20のバグありなし一覧(暫定)

1/20,20のバグあり(あった)
Matrix3D.append()*10,0,22,87で対応済み
Matrix3D.appendRotation()*10,0,22,87で対応済み
Matrix3D.prepend()*10,0,22,87で対応済み
Matrix3D.prependRotation()
Matrix3D.prependTranslation()*10,0,22,87で対応済み
Matrix3D.transformVector()*10,0,12,36で対応済み
Matrix3D.transpose()*10,0,22,87で対応済み
Matrix3D.determinant

1/20,20のバグ無し
Matrix3D.appendScale()
Matrix3D.appendTranslation()
Matrix3D.clone()
Matrix3D.decompose()*別なバグがある
Matrix3D.deltaTransformVector()
Matrix3D.identity()
Matrix3D.interpolate()
Matrix3D.invert()
Matrix3D.recompose()*別なバグがある
Matrix3D.transformVectors()
Matrix3D.position
Matrix3D.prependScale()

 

解決したの?

重要なメソッドでは修正されたが、まだ一部のメソッドでこのバグは残っている。
今後修正されるとは思うが、バージョンごとにバグが直っていたり、直っていなかったり、ということになっている。
本サイト閲覧者のプラグイン状況では、2009年7月末現在17%以上のPCで重要なメソッドの部分でバグの残っているFlashPlayer10を使用している模様。

 

回避法

1.バグの無いメソッドのみを使う。
2.バグのあるメソッドではスケール処理を行わない。
3.プラグインのバージョンを取得して、値を分岐させる
4.プラグインのバージョンを取得して、最新版を入れないと見れないようにする。

とかなのかな。
4以外はかなり理解したうえじゃないと、怖くて使えないよね。

 

実行例

(バグアリプラグイン向けに作ったものなのでわかりにくいけど)
 
▼Wonderfl

▼ActionScript AS3(FP10)

/*
下記のblogにてもう少し詳しく説明しています。

http://umehara.net/blog/?p=32

Matrix3Dの一部の値が、1/20になったり、20倍になる。
バグだと思うんだけど、良くわかんない。

Matrix3D.transformVectorは解決されているようだけど

http://www.dango-itimi.com/blog/archives/2008/000967.html

Matrix3D.transpose()のほうは10,0,12,36でも解決されていない。

英語版のhelpで指摘されてるけど、関係ないレスが帰って来ている。 

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

*追記
10,0,22,87では解決された模様。

*/
package {
	import flash.display.Sprite;
	import flash.geom.Matrix3D;
	import flash.text.TextField;
	import flash.geom.Vector3D;
	import flash.system.Capabilities;
	public class FlashTest extends Sprite {
		public function FlashTest() {
			var m:Matrix3D = new Matrix3D();
			var v:Vector3D=new Vector3D(500,1000,0);
			var c:Vector3D=m.transformVector(v);

			var txt:String="◆同機能関数Mtrx3D.transformVector "+Capabilities.version+"での実行結果\n\n";

			txt+="10,0,12,36未満(10,0,2,54?)では\n↓がVector3D(25,50,0)になる\n"+String(c);
			//
			var m0:Matrix3D=new Matrix3D(Vector.<Number>([1,2,3,4,11,12,13,14,21,22,23,24,31,32,33,34]));
			var m1:Matrix3D=m0.clone();
			var m2:Matrix3D=m0.clone();
			txt+="\n\n\nまた、\n";
			txt+=m0.rawData;
			txt+="\nはtranspose()を使うとhelp通りだと";
			txt+="\n1,11,21,31,2,12,22,32,3,13,23,33,4,14,24,34";
			txt+="\n\nになるはずだけど実際は10.0.12.36でも以下のようになる。";

			m1.transpose();
			_transpose(m2);

			txt+="\n"+m1.rawData;
			txt+="\n\n同じ値を返す関数を作るとすると以下になる。\n"+m2.rawData;

			var tf1:TextField = new TextField();
			tf1.width=stage.stageWidth;
			tf1.height=stage.stageHeight;
			tf1.wordWrap=true;
			stage.addChild(tf1);
			tf1.text=txt;

			function _transpose(mt:Matrix3D):void {
				var m:Vector.<Number>=mt.rawData;
				var v:Vector.<Number>=new Vector.<Number>(16,true);
				v[0]=m[0];
				v[1]=m[4];
				v[2]=m[8];
				v[3]=m[12]*20;
				v[4]=m[1];
				v[5]=m[5];
				v[6]=m[9];
				v[7]=m[13]*20;
				v[8]=m[2];
				v[9]=m[6];
				v[10]=m[10];
				v[11]=m[14]*20;
				v[12]=m[3]/20;
				v[13]=m[7]/20;
				v[14]=m[11]/20;
				v[15]=m[15];
				mt.rawData=v;
			}
		}
	}
}

関連記事:

Comments are closed.