Now on Sale!! |
|||||||||||||||
■Mailing List: ActionScript 3.0 F-siteセミナー Flash Player 10で新たに加わった3Dの行列とベクトルを使ってみる
1. 配列を最適化したVectorクラス
しかし、配列と異なる点もある。とくに、エレメントについて、データ型の指定を始めとする制約がある。
Vectorクラスのインスタンスを作成するコンストラクタメソッドは、つぎのようなシンタックス(文法)だ[*2]。他のクラスと異なるのは、コンストラクタの後にドット(.)とタグのような不等号の組(<>)を記述し、その中にエレメントのデータ型を指定することである。 Vector.<データ型>() Vectorクラスを使うと、エレメントにデータ型が指定されるため、エレメントに値を設定するときだけでなく、取出した値についても型がチェックされる。また、エレメントへのアクセスも、配列と比べて高速だ。
Vectorインスタンスの生成とエレメントの値の追加、変更、取出しは、つぎのように行う(スクリプト001)。エレメントのデータ型は、整数intで指定している。 スクリプト001■Vectorクラスでエレメントの追加・変更・取出しを行う
Vectorインスタンスはエレメントのデータ型まで指定できるので、メソッドの引数にも適している(配列では、エレメントにどんなデータが入っているかわからない)。 たとえば、Flash Player 10から実装されたGraphics.drawTriangles()メソッドは3つの引数に、エレメントが数値型のVectorインスタンスを取り、第2引数はエレメントが整数(int)型で指定されている[*3]。 drawTriangles(頂点座標:Vector.<Number>, 頂点番号:Vector.<int> = null, uvtデータ:Vector.<Number> = null):void
2. 変換行列を数学的に捉える[*4] 【行列とは】 図002■2行×2列の行列 行列は、加減算のほか、乗算ができる。乗算は、掛けられる左の行列の行と、掛合わせる右の行列の列とを、それぞれつぎのように計算する(図003)。 図003■2行×2列の行列と2行×1列の列ベクトルとの乗算[*5] 乗算では、掛けられる左の行列の列数と、掛合わせる右の行列の行数は等しくなければならない(図004上図)。したがって、行列では乗算の交換法則は成立たない(図004下図)。 図004■乗算では左の行列の列数と右の行列の行数は等しくなければならない 行と列の数が等しい行列を「正方行列」と呼ぶ。行数×列数の同じ正方行列同士を乗算すると、その結果も同じ行数×列数の正方行列になる(図005)[*6]。したがって、同じ行数×列数の正方行列は、いくつでも掛合わせられる。 図005■正方行列同士の乗算結果は同じ行数×列数の正方行列になる まとめると、行列の乗算における重要な特徴は以下のとおり。その性質は、フィルタに似ている(図006)。
図006■フィルタはいくつでも掛けられて順序により効果が変わる
3. 変換行列とMatrixクラス Flashの座標空間では、インスタンスの配置された親タイムラインの基準点が原点になる。そのため、親の基準点(0, 0)をつねに原点として、インスタンスの拡大・縮小や回転が行われる。[自由変形ツール]で、中心点を親タイムラインの基準点に設定したのと同じ状態だ(図007) 図007■配置されたタイムラインの基準点を原点に変形 この原点が固定される問題を解決する方法として、Matrixクラスの変換行列はひとつ列を増やした[*7]。そして、正方行列にするため、行数も列数に等しくする。また、掛合わせる列ベクトルも同じ行数にしなければならない。 各行列の3行目は、下図008上図のように値を固定する。変換行列を3行×3列にしたことにより、座標を平行移動することが可能になった。変換行列の3列目のtxとtyに、それぞれxy座標の移動ピクセル数を指定する(図008下図)。 図008■Matrixクラスの変換行列と列ベクトル すると、親タイムラインの原点でなく、たとえばインスタンスの基準点を中心に変換することができる。そのときは、インスタンスの基準点を原点と一致するように移動し、拡大・縮小や回転などの変換を行ったうえで、初めとは反対方向に移動してもとの位置座標に戻せばよい。
4. Matrix3Dクラスにおける変換行列の扱い たとえば、3次元座標空間でDisplayObjectインスタンスを回転するには、Matrix3D.prependRotation()メソッドが使える。メソッドのシンタックスは、つぎのとおりだ。 prependRotation(度数:Number, 軸:Vector3D):void 第1引数には、加える回転角を度数で指定する。第2引数は、回転の軸を、定数Vector3D.X_AXIS、Vector3D.Y_AXIS、Vector3D.Z_AXISからひとつ選ぶ。 Matrix3Dクラスにより座標の変換を行うには、対象となるDisplayObjectインスタンスのDisplayObject.transformプロパティに保持される、Transform.matrix3DプロパティのMatrix3Dインスタンスを操作する。ただし、注意しなければならないのは、DisplayObjectインスタンスに対して3次元座標の操作をしないと、DisplayObject.transform.matrix3DプロパティにはMatrix3Dインスタンスが設定されず、nullが返されることだ。 それでは、タイムラインに配置したMovieClipインスタンスmy_mcを、マウスポインタの水平座標に応じて、y軸で水平に回転させてみよう[*8]。回転のアニメーションは、DisplayObject.enterFrameイベント(定数Event.ENTER_FRAME)にリスナー関数xRotate()として登録する[*9]。すると、フレームアクションは、つぎのスクリプト001のようになる。 スクリプト001■3次元座標空間におけるインスタンスをy軸で回転させる
前述のとおり、MovieClipインスタンスmy_mcに3次元座標の操作をしないと、Matrix3Dインスタンスが設定されない。そこで、スクリプト001では、インスタンスmy_mcのDisplayObject.zプロパティにデフォルト値0を設定した。 Matrix3D.prependRotation()メソッドに設定する回転角は、インスタンスの基準点から見たマウスポインタの水平座標値に比例させている。したがって、インスタンスから水平方向にマウスポインタを離すほど、インスタンスが水平に回転するスピードは増すことになる(図009)。 図009■インスタンスがマウスポインタの位置に応じて水平に回転 つぎに、前掲スクリプト001に、y軸の水平回転だけでなく、x軸による垂直の回転も加えよう。
試してみると、垂直方向の回転の軸に違和感がある。いわばインスタンスが正面を向いた状態で垂直に回り、配置されたタイムラインのx軸でなく、インスタンス自身のx軸で回転しているように見える(図010)。 図010■インスタンスがマウスポインタの位置に応じて水平に回転 Matrix3D.prependRotation()メソッドは、回転の変換行列を、インスタンスがもつMatrixインスタンス(DisplayObject.transform.matrix3Dプロパティ)よりも前(prepend)に適用つまり乗算する。 すると、変換をまったく加えていないデフォルト状態のインスタンス(図001)[*10]に、Matrix3D.prependRotation()メソッドの回転が加えられ、その後にインスタンスのもつ変換行列が適用される。そのため、つねに正面向きの状態で回転することになる。 図011■変換を行う前のデフォルト状態 これを避けてインスタンスの現在の状態で回すには、後(append)から回転するMatrix3D.appendRotation()メソッドを使えばよい。ただし、そのままでは回転の原点が親タイムラインの基準点になってしまう。 したがって、前項(「3. 変換行列とMatrixクラス」)で確認したように、一旦インスタンスを親タイムラインの基準点に平行移動し、変換を加えた後、位置をもとに戻す必要がある。 後から平行移動するメソッドは、Matrix3D.appendTranslation()だ。引数は3つで、xyzの各座標値を指定する。この考え方に沿ってスクリプト001を修正したのが、つぎのフレームアクションである(スクリプト002)。 スクリプト002■3次元座標空間におけるインスタンスをx軸とy軸で回転させる
これで、ステージ上のインスタンスの状態をもとに、マウスポインタの位置に応じてインスタンスがx軸およびy軸で回転する(図012)。 図012■ステージ上のインスタンスの状態から水平・垂直に回転
作成者: 野中文雄 Copyright © 2001-2008 Fumio Nonaka. All rights reserved. |
|||||||||||||||