Adobe Flash非公式テクニカルノート 変換行列を数学的に捉える
1. 行列とは 図001■2行×2列の正方行列 行列は、一定の決まりにしたがって並んだ複数の数値を、まとめて計算できることが便利な点です。行列の中のひとつひとつの数は、「成分」または「要素」と呼ばれます。
2. 行列の乗算 たとえば、平面のxy座標を2行×1列の行列(列ベクトル)[*3]で表すと、2行×2行の行列と掛け算ができます。その場合、掛けられる左の行列の行と、掛合わせる右の行列の列とを、つぎのように計算します(図002)[*4]。 結果は、2行×1列の行列になります。 図002■2行×2列の正方行列と2行×1列の行列との乗算 上図002で見たとおり、行列の乗算では、掛合わせるふたつの行列の行数と列数がともに等しい必要はありません。しかし、掛けられる左の行列の列数と、掛合わせる右の行列の行数は等しくなければなりません(図003上図)。したがって、行列では乗算の交換法則は成立たず、掛合わせる順番を入換えると計算ができなかったり(図003下図)、できたとしても結果の行列の数値は変わります。 図003■乗算では左の行列の列数と右の行列の行数は等しくなければならない 行数×列数の同じ正方行列同士を乗算すると、その結果も同じ行数×列数の正方行列になります(図004)[*5]。したがって、同じ行数×列数の正方行列は、いくつでも掛合わせることができます。 図004■正方行列同士の乗算結果は同じ行数×列数の正方行列になる 以上述べた中で、行列の乗算における重要な特徴は、つぎのふたつになります。
いくつでも掛けられて、その順序を変えると結果が変わる、というと何かを想い起こさないでしょうか。ビットマップ画像に適用するフィルタと同じ性質です(図005)。実際、フィルタの多くは、内部的に行列を使って処理していると考えられます。 図005■フィルタはいくつでも掛けられて順序により効果が変わる(Flash CS4の[フィルタ])
3. 変換行列とMatrixクラス
ただし、注意しなければならないのは、2行×2列の正方行列にxy座標の列ベクトルを乗じた場合、その座標変換は配置された座標空間の原点つまり親タイムラインの基準点が起点になるということです。いわば[自由変形ツール]で、変形点を親タイムラインの基準点に置いて変形するのと同じです(図006)。親タイムラインでなく、たとえば自分の基準点を中心に変換することはできません。さらにいえば、単純な座標の移動(平行移動)も、2行×2列の正方行列では実現できないのです。 図006■配置されたタイムラインの基準点を起点に変形 この平行移動ができるようにするため、変換行列はひとつ列を増やすことになります。正方行列でなければ複数の乗算ができませんので、行数も列数に等しくします。また、掛合わせる列ベクトルも同じ行数にしなければなりません。2次元座標空間を扱うMatrixクラスは、変換行列をつぎのように定義します(図007上図)[*6]。 図007■Matrixクラスの変換行列と列ベクトル 列ベクトルの3行目の要素を1にしましたので、乗算した結果の列ベクトルのxy座標にはそれぞれ追加したtxとtyの値が加算されます(図007下図)[*7]。つまり、平行移動したいピクセル数を、このtxとtyに指定すればよいということです。また、正方行列にするために加えた変換行列の3行目は、「0 0 1」という値に固定されていますので、乗算結果の列ベクトルの3行目の要素はつねに1になります。ですから、さらに別の変換行列と乗算することができます。 これで、拡大・縮小や回転、傾斜に加えて、座標の平行移動ができるようになりました。すると、親タイムラインの原点でなく、たとえばインスタンスの基準点を中心に変換することも可能です。そのときは、インスタンスの基準点を原点と一致するように移動し、拡大・縮小や回転などの変換を行ったうえで、初めとは反対方向に移動してもとの位置座標に戻せばよいのです。 Matrixクラスの変換行列は、固定の3行目を除く6つの要素をプロパティとして設定できます[*8]。また、平行移動や拡大・縮小、回転の変換を加えるためのメソッドも用意されています[*9]。Matrixクラスのプロパティやメソッドについて詳しくは、オンラインヘルプの[ActionScript 3.0コンポーネントリファレンスガイド]で「Matrix」の項をご覧ください[*10]。
4. Matrix3Dクラスにおける変換行列の扱い これらの変換を組合わせて適用するには、内部的にはそれらの変換行列を乗算したうえで、その結果の変換行列に座標ベクトルを掛け合わせます。気をつけなければならないのは、前述(2.「行列の乗算」【行列の乗算の特徴】)のとおり、行列の掛合わせる「順序を変えると結果が変わる」ということです。 そこで、Matrix3Dクラスの平行移動や拡大・縮小、回転の各メソッドは、そのための変換行列を前に(prepend)乗じるか後に(append)乗じるかの2種類がそれぞれ提供されています(表002)。たとえば、単純な2次元のxy平面で考えても、親タイムラインの基準点で(z軸の)回転をしてから移動する(図009左図)のと、移動してから親タイムラインの基準点を中心に回転する(図009右図)のでは、明らかに結果は異なります。 表002■Matrix3Dクラスの移動/拡大・縮小/回転のメソッドと変換行列を乗算する順序
図009■平行移動と回転の変換の順序により結果は異なる インスタンスに変換が何も加えられていないデフォルトの状態は、その座標が親タイムラインの基準点(0, 0, 0)にあり、xyz軸方向の拡大・縮小の比率はいずれも実寸の1、各軸についての回転はすべて0度が設定された状態です。したがって、インスタンスがその状態でなければ、逆にいうとデフォルトでない変換行列が適用されていることを意味します。 前掲表009の中で変換行列を後に乗じるメソッドというのは、現在のインスタンスに適用されている変換行列の後からメソッドの変換行列を掛合わせます。たとえば、インスタンスの位置が親タイムラインの基準点でなかったなら、Matrix3D.appendRotation()メソッドによりインスタンスは親タイムラインの基準点を中心として回転されます(前掲図009右図)。 変換行列を前に乗じるメソッドは、現在のインスタンスに設定されている変換行列の前にメソッドの変換行列を掛合わせます。つまり、デフォルトの状態に、まずメソッドの変換行列を先に適用します。たとえば、Matrix3D.prependRotation()メソッドはデフォルト状態に戻したインスタンスを初めに回転し、その後にインスタンスのもとの変換行列を乗じます。結果として、インスタンスは配置されていた場所で、自身の基準点を中心に回されたのと同じ状態になります(図009左図)。 以上からは、インスタンスの基準点を原点とする変換は、変換行列を前に乗じるメソッドの方が簡単に思えるかもしまれせん。単純な変換であれば、そういえる場合が多いでしょう。しかし、すでに複数の変換が組合わせて加えられている場合には、デフォルトに戻してしまうことが意図に沿わないこともありえます。 たとえば、親タイムラインの基準点から離れた場所のインスタンスが、インスタンスの基準点を原点にy軸で90度回転して、真横を向いていたとします。インスタンスをその真横の向きのまま、さらにx軸で回転させるにはどうしたらよいでしょうか。 この場合、Matrix3D.prependRotation()メソッドでは、意図した変換になりません。なぜなら、このメソッドを適用する前に、インスタンスはデフォルトの正面向きに戻ります。したがって、正面向きのインスタンスをx軸で回転した後に、y軸による90度の回転と平行移動を掛合わせることになるからです(図010)。 図010■デフォルトに戻して回転した後もとの変換を乗じるインスタンスがy軸で横向きのままx軸による回転を行うには、完全にデフォルトに戻す訳にはいきません。戻すのは位置座標のみに止める必要があります。この場合には、変換行列を後から乗じます。つまり、Matrix3D.appendTranslation()メソッドでまず位置座標を親タイムラインの基準点に平行移動し、インスタンスは横向きのままx軸による回転をMatrix3D.appendRotation()で加えます。その後、さらにMatrix3D.appendTranslation()メソッドで、位置座標をもとに戻せばよいのです(図011)。 図011■基準点に移動して回転の変換を乗じてからもとの位置に戻す以上より、変換をデフォルト状態から考える場合には、変換行列は前に乗じるメソッドで扱った方が簡単だといえます。しかし、変換された現在の状態をベースにするときは、その内容を個別に考えて、補正や追加を後に乗じるメソッドで処理した方がよいでしょう。いずれにしても、変換行列にかぎらず、行列は一般に乗算の順序に注意する必要があります。 作成者: 野中文雄 Copyright © 2001-2008 Fumio Nonaka. All rights reserved. |
||||||||||||||||||||||||||||||||||||