トップページ > 3D > Matrix3D(prepend編)



概要

Matrix3D(基本編)
の続きです。

今回は平行移動、拡大縮小、回転を行うコードを書いていきます。


prepend append
平行移動 prependTranslation appendTranslation
拡大縮小 prependScale appendScale
回転 prependRotation appendRotation
それぞれの処理にprependとappendで分かれていますが、今回はprepend~のメソッドを使用します。


初期設定

var rect:Sprite = new Sprite();
rect.graphics.lineStyle(2.0);
rect.graphics.beginFill(0x009AD6);
rect.graphics.drawRect(0, 0, 100, 100);
rect.graphics.endFill();
addChild(rect);
 
rect.z = 0;
 
まずMatrix3Dを適用させるオブジェクトを作っておきましょう。
z = 0と入れて、Matrix3Dオブジェクトを生成するのを忘れないようにしてください。


平行移動 - prependTranslation

rect.transform.matrix3D.prependTranslation(100, 0, 0); // x, y, zの順番
 
オブジェクトを移動させるにはprependTranslation()を使用します。
x, y, zの順番で指定しますが、どれも省略することが出来ません。今の位置から移動させたくない場合は0を入れておきましょう。


さて、ここでprependの機能を説明しておきます。
上のコード、prependTranslation(100, 0, 0)はrect.x += 100と同じように見えますが、厳密にいうと違います。
計算結果は同じになるのですが、メソッド内の計算方法が違うのです。

別のコードで説明しましょう。
rect.x = 150;
rect.transform.matrix3D.prependTranslation(100, 0, 0);
trace(rect.x);
 
1行目はrect.x = 150なので、rectのx位置を150pxに合わせます。

2行目はprependTranslation()ですが、prepend~系のメソッドは特殊な機能を持っています。
まず、prepend~の行までに設定した平行移動、拡大縮小、回転の設定を全てクリアさせます。
つまり、rect.x, y, z, scaleX, scaleY, scaleZ, rotation(Z), rotationX, rotationY全てに0を入れるわけです。
そのクリアな状態で100px平行移動させます。
そしてその後に、prepend~の行までに設定した内容をまた設定しなおします。

もう一度コードを見てみましょう。

rect.x = 150;
rect.transform.matrix3D.prependTranslation(100, 0, 0);
trace(rect.x);
 
1行目の設定でrect.xの位置xが150になります。(rect.x = 150)
2行目がprependの平行移動なので、まずrect.xを0にして設定をクリアさせます。(rect.x = 0)
そしてその状態でprependTranslation()の引数値を反映させます。上の場合だとx方向に100px移動させますね。(rect.x = 100)
そして先ほどクリアにした元の設定を反映し直します。元の設定と言うのは上のコードでいうとrect.x = 150がそれにあたります。
prependTranslation()でrect.xを100にしていますので、反映しなおした場合は100 + 150で250になります。

prependは日本語で「先に追加する」という意味です。
なので、prependTranslation()では、元々設定してある値を無視して先に位置を設定します。その後、元々設定してある位置を反映させるわけです。


// 2行目の処理
 
// 間違い
rect += 100
 
// 正解
rect = 100
rect += 150
 
prependを呼び出すまでに設定した内容が後に来るわけですね。


拡大縮小 - prependScale

rect.transform.matrix3D.prependScale(2, 3, 4); // x, y, z
 
上のコードだと、x方向に2倍、y方向に3倍、z方向に4倍に拡大するコードです。
平行移動と同じく引数全てに値を設定しないといけません。拡大縮小させたくない場合は1を入れておきましょう。
ちなみに0を入れるとエラーが出ます。


rect.x = 100;
rect.transform.matrix3D.prependScale(2, 1, 1);
 
まず1行目でx位置を100にします。
2行目はprependのメソッドなので、今まで設定した内容(rect.x = 100)をクリアします。
そして、オブジェクトをx方向に2倍に伸ばし、rect.xを100に設定します。


回転 - prependRotation

rect.transform.matrix3D.prependRotation(30, Vector3D.Y_AXIS); // 角度, 軸
 
オブジェクトを回転させるメソッドです。
第一引数は回転させる角度です。

第二引数は、どこを軸として回転するかを設定します。
これはVector3Dクラスに定数が用意されているのでそれを使用しましょう。

定数名 意味
Vector3D.X_AXIS xを軸にする
Vector3D.Y_AXIS yを軸にする
Vector3D.Z_AXIS zを軸にする
AXISは「アクシス」と読み、軸という意味になります。


rect.transform.matrix3D.prependRotation(40, Vector3D.Z_AXIS);
rect.transform.matrix3D.prependRotation(50, Vector3D.Z_AXIS);
 
1行目はprependで、z軸を中心に40度回転させます。これより前の設定が無いのでクリアする必要はありません。
2行目もprependで、z軸を中心に50度回転させます。前の設定は一行目のz軸40度回転になります。
なので、50度回転させた後、元の設定40度回転を反映させて、90度回転している状態にさせます。


基点

とりあえず、ここまでで紹介した平行移動、拡大縮小、回転ですが、その処理を行う「基点」についても解説しないといけません。
要は、移動するにも回転するにも必ずどこかを軸にして処理を行います。
その軸の位置、つまり基点は一体どこなのでしょうか。

何を言っているんだ? prepend~を呼び出したオブジェクトの位置(x, y, z)に決まってるだろ、と思われるかもしれませんがそれは大体合っています。
これは正確にいうと、メソッドを呼び出したオブジェクトの「親の位置」が基点になっています。

ただ、上でも解説したとおりprependはそれまでに設定した内容をクリアします。
クリアした時点でメソッドを呼び出したオブジェクトの位置は親の位置と同じになりますね。

親の位置に子がいる状態で親の位置を基準にして処理されるというのは、子の位置を基準にして処理するのとまったく同じになるわけですから、prepend~系メソッドは子(メソッドを呼び出したオブジェクト)の位置を基準にして回転や移動が行われると考えたほうが分かりやすいですね。

ただ、「正確」ではなく「大体合ってます」と書いたとおり、一部例外があります。
prepend~系メソッドの組み合わせによっては、メソッドを呼び出したオブジェクトの位置x,yを基点として考えるとおかしな計算になる場合があります。

メソッドを呼び出したオブジェクトの親の位置が基点になるというのが分かる例を挙げてみましょう。

rect.scaleX = 2;
rect.transform.matrix3D.prependTranslation(100, 0, 0);
trace(rect.x);
 
3行目で出力されるrect.xの値は幾らになるでしょうか。


メソッドを呼び出したオブジェクトが基点になるなら、100と出力されるはずです。
しかし、実際は200が出力されます。

コードを追ってみましょう。
1行目は普通にrectの横サイズを2倍にしているだけです。(x = 0, y = 0)

2行はprepend系メソッドなので、1行目で設定した内容が初期化されます。
xyが0になりますが、元々0だったので値は変わっていませんね(x = 0, y = 0)

prependTranslation(100, 0, 0);なので、「親の位置(0, 0)を基点」として移動させます。rectの位置は(100, 0)になります。
その後、元々設定していた内容であるscaleX = 2を反映させますが、これも親の位置を基点として拡大させます。
そうすると、rectのxは200になるので、3行目のtrace出力で200と表示されるわけです。


検証用コード

package
{
	import flash.display.Sprite;
	import flash.geom.Vector3D;
 
	public class Main extends Sprite
	{
		public function Main()
		{
			var rect:Sprite = new Sprite();
			rect.graphics.beginFill(0x009AD6);
			rect.graphics.lineStyle(3.0, 0x0);
			rect.graphics.drawRect(0, 0, 100, 100);
			rect.graphics.endFill();
			addChild(rect);
 
			rect.z = 0;
 
			rect.scaleX = 2;
			rect.transform.matrix3D.prependTranslation(100, 0, 0);
			trace(rect.x); // 200
		}
	}
}
 

|新しいページ|検索|ページ一覧|RSS|@ウィキご利用ガイド | 管理者にお問合せ
|ログイン|