Astro de 3D(11) PerspectiveProjection は放棄<2>
2008/06/15 21:51 - Astro
前回の解説編。
以前、自作の三次元変換行列を使った 3D 表現を試みたことがありました。
そのとき、頂点をクラスとして整備しましたが、今回はそれを流用します。名前はそのまま Vertex クラスとします。
というか、自作クラスによる 3D 表現シリーズで作った三次元変換行列クラスと三次元座標クラスを、それぞれ Flash ビルトインのクラスの Matrix3D と Vector3D に置き換えたものが、今回の Astro de 3D シリーズなワケです。
頂点が対象の 3D 表現における肝は Main.as の zsort メソッドの際に呼び出される頂点クラスのメソッド perspective です。 この perspective メソッドがパースをつけるんですね。
Vertex クラスの詳細は、以前の頂点クラスについてのエントリーをご参照いただくとして、必要な部分だけを再度述べると、頂点クラスは以下のふたつの Vector3D クラスを持っています。
- 頂点オブジェクトが生成されたときに指定された三次元座標
- 刻々と変化する Matrix3D によって変換される三次元座標
前者は初期位置を保持し、後者は現在位置を示すものです。
perspective メソッドは前者を後者に変換する処理をおこないます。
public function perspective( mat:Matrix3D ):void { (1) _projection = mat.transformVector( _local ); (2) _projection.w = 1; (3) _projection.project(); }
引数に指定された Matrix3D は、頂点オブジェクトの外側、つまり、Main.as で三次元空間全体を制御しているマトリクスです。 今回の事例でいうと globalMat です。
_local は頂点クラスが持つふたつの Vector3D の前者、_projection は後者です。
(1)が初期座標を現在座標に変換している部分です。 Matrix3D のメソッドに座標をそのまま突っ込んでるだけです。
Matrix3D.transformVector の返り値である Vector3D の w プロパティの値は 1 です。
それゆえ、平行投影のコーディングをしている今回、(2)は不要なんですが、明示のため Vector3D のプロパティ w に 1 を代入しています。
(3)も平行投影では不要な部分ですが、透視投影による遠近感をつけるときは必要になります。
Vector3D.project は何をするメソッドかというと、プロパティ x、y、z をそれぞれプロパティ w で割るものです。 つまり以下の処理をおこなっているんですね。
Vector3D.x /= Vector3D.w; Vector3D.y /= Vector3D.w; Vector3D.z /= Vector3D.w;
平行投影では w が常に 1 なので、意味のない処理なわけです。
では、なぜ各座標値を w で÷るのか。
私としては÷るんではなくて×る方が馴染みがあるんですが、これこそがパースをつける行為になるのです(z を w で÷る処理はパースには不要)。
そのために w の値が問題になるわけで、PerspectiveProjection クラスに w を計算して決定するメソッドがあってしかるべきだと思うんですが、存在しません(PerspectiveProjection クラスが釈然としない理由その1)。
ネット上にある先達の情報を見ると、皆さん w は自前で計算なさっているようです。
なお Astro ASDoc の Vector3D の項を見ると、プロパティ w は以下のように説明されています。
ってことは、この w ってプロパティには何を保持しても良いんですかね。 要は extra に相当するわけですか?
それともクォータニアンなるものを学ばないと w の意味は理解できないんでしょうか。
次回は、今回の平行投影過程を書き換えて、Vertex.perspective メソッドで透視投影処理をおこなうようにします。