前回の第35回「Matrix3Dクラスによる座標変換」では、先に加える変換となるprependがついたMatrix3Dクラスのメソッドを試した。しかし、インスタンスに加わる変換は、スクリプトに書かれたものだけではないというヒントを示して終わった。今回は、その変換の中身を明らかにし、後から加えるappendのついた変換のメソッドを試す。
DisplayObjectインスタンスに加わる変換
例によって、まずは簡単なサンプルで確かめよう。ステージ中央にMovieClipインスタンスmy_mcを置き、2次元平面で90度回してみる[1]。これを初めの状態とする(図1)。
MovieClipインスタンスを置いたタイムラインには、以下のフレームアクションを記述する。第1に注目してほしいのは、インスタンスのDisplayObject.transformプロパティから参照したTransform.matrix3Dに、Matrix3D()コンストラクタで生成した新規のオブジェクトを代入していることだ。これにより、インスタンスのもつ変換行列つまりMatrix3Dオブジェクトは、デフォルトに設定される。しかし第2に、インスタンスがもともともっていたMatrix3Dオブジェクトは、予め変数(myMatrix3D)にとっておいた。そして、インスタンスをクリックするとリスナー関数(setMatrix3D())によって、もとのMatrix3Dオブジェクトが改めて設定し直されるという流れだ。
[ムービープレビュー]を確かめると、まずインスタンスはタイムラインの基準点つまりメインタイムラインなら左上隅に、回転していない(角度0)実寸(100%)で表示される(図2左図)。つぎにインスタンスをクリックすると、前掲スクリプトのリスナー関数により、オーサリング時に設定したとおり、ステージ中央で90度横に回る(図2右図)。
実は、Flash Player内部でも、インスタンスはこのような手順で配置されている。つまり、まずタイムラインに置くべきデフォルト状態のインスタンスを取出し、その変換情報が納められたMatrix3Dオブジェクトを調べる。そして、そのMatrix3Dオブジェクトをインスタンスに適用して表示する。変換を前に加えるprependと後に加えるappendは、もとのMatrix3Dオブジェクトよりメソッドを適用するのが前か後かという意味なのだ。
動的に配置したビットマップをマウスポインタに応じて上下左右に回す
それでは改めて前回の課題だった、動的に配置したビットマップを、マウスポインタの動きに応じて上下左右に回してみよう。前回マウスポインタの動きとインスタンスの回る方向がちぐはぐだったのは、Matrix3D.prependRotation()メソッドを使ったからだ。
たとえば、インスタンスがy軸で横に回転していたとき(図3上図)、マウスポインタを上に動かせば、インスタンスは横向きのまま垂直に回ることを期待する。ところが、Matrix3D.prependRotation()メソッドを用いると、インスタンスはデフォルトの正面向きで上に回転して、その後直前の状態の変換を加えることになってしまう(図3下図)。
図3 Matrix3D.prependRotation()メソッドは正面向きのインスタンスを回すことになる
直前の状態
|
デフォルト状態
|
→ |
Matrix3D.prependRotation()メソッドを適用
|
→ |
直前の変換を適用
|
直前の状態に対して変換を加えたいなら、後から適用するappendのメソッドを用いる必要がある。平行移動や回転あるいは伸縮の変換を後から加えるには、prependのメソッドに対応するMatrix3D.appendTranslation()、Matrix3D.appendRotation()、Matrix3D.appendScale()といったメソッドをそれぞれ用いる。これらのメソッドは変換を後から加えるという違いがあるだけで、引数は変わらない。
もっとも、Matrix3D.prependRotation()メソッドをMatrix3D.appendRotation()に変えただけでは、インスタンスを上下左右に回すことは思惑どおりにいかない。MovieClipインスタンスmy_mcをステージ中央に置いて、Matrix3D.appendRotation()メソッドによりy軸で単純に水平に回してみよう。フレームアクションはつぎのとおりだ。
[ムービープレビュー]を確かめると、確かにインスタンスは水平に回る。ただし、回転の軸がインスタンスの基準点ではない。実は、行列による座標変換は、原点がつねにインスタンスの置かれた親タイムラインの基準点になる。メインタイムラインなら、水平回転のy軸はステージ左端だ(図4)。そして、この原点は動かせない。
Matrix3D.prependRotation()メソッドではインスタンスの基準点を軸に回ったのは、デフォルト状態つまり座標(0, 0)ではインスタンスと親タイムラインの基準点が一致するためだ。後から変換を加えるMatrix3D.appendRotation()メソッドでは、インスタンスと親タイムラインの基準点の位置は通常異なる。
とはいえ、対処法はさほど難しくない。インスタンスの角度は変えずに、回転の軸だけずらせばよい。つまり、インスタンスの座標のみ親タイムラインの基準点に移動すれば、直前の角度からインスタンスの基準点で回転できる。その後忘れずに、座標はもとの位置に戻す。つまり、平行移動・回転・平行移動を組合わせるということだ。
前回つくった「動的に配置したビットマップをマウスポインタに応じて水平回転させる」のスクリプト1に、垂直の処理を加えたのが以下のスクリプト1だ。垂直方向の回転角を計算したうえで、インスタンスは親タイムラインの基準点に移動してから回転し、改めてもとの位置に戻した。
[ムービープレビュー]を確かめると、今度は直前の状態からインスタンスの中心を軸にマウスポインタの向きに回る(図5)。2回にわたって見てきたように、単純な変換であれば前に加えるメソッドの方が簡単に書ける。しかし、いくつかの変換を組合わせてアニメーションするような場合には、後から加えるメソッドの方がステートメント数は増えるものの、細かく処理できる。
次回は、回す面の数を増やし、その重ね順について解説したい。
今回解説した次のサンプルファイルがダウンロードできます。