座標系とカメラ
ここでは M3G に用いられている座標系とその変換、およびカメラの設定について解説します。
目次
1. 座標系
M3G ではモデル座標系・ワールド座標系・カメラ座標系・スクリーン座標系の4つの座標系が用いられています。これらの座標系はすべて直交座標系として扱います。
各3Dモデルごとに用意された座標系です。
ワールド座標系ワールドの基準となる座標系です。各3Dモデルはワールド座標系上に配置されます。
カメラ座標系カメラから見たときの座標系です。カメラ座標系で描画される領域はニアクリップ面・ファークリップ面・画角などを定めることによってできる視体積内になります。
スクリーン座標系ディスプレイに実際に描画されるときの座標系です。カメラ座標系における視体積を1辺の長さが1の立方体に拡大・縮小し、それをスクリーンに投影します。
M3G では、ディスプレイに3Dグラフィックスを表示するために、
モデル座標系→ワールド座標系→カメラ座標系→スクリーン座標系
という3回の座標変換を行います。
2. 変換行列
ここでは M3G で使用されている変換行列を表すクラスについて解説します。
2.1. Transform クラス
Transformクラスは3次元アフィン変換用の4×4行列を保持するクラスです。カメラや3Dオブジェクトの配置や移動はこのクラスを用いて行います。 Transfrom クラスは 3D モデルに対してrotate (回転)、 translate (平行移動)、 scale (拡大・縮小)の各操作を行うことが可能です。これらの操作は以下のメソッドによって行われ実際には、Transformオブジェクトにそれぞれの操作を行う4×4のアフィン変換行列を掛けることで実現しています。それぞれのメソッドが掛ける変換行列の内容についてはjavadocのTransformクラスの項をご参照ください。
対象となるモデルに対し、ベクトル ( ax, ay, az ) を軸として angle の分だけ回転を行います。 angle の単位は度 ( degree ) です。なお、 postRotateQuat ( float qx, float qy, float qz, float qw ) を利用すると、四元数を用いた回転も可能です。
postTranslate ( float tx, float ty, float tz )対象となるモデルを方向ベクトル ( tx, ty, tz ) の分だけ平行移動します。
postScale ( float sx, float sy, float sz )対象となるモデルを各方向に各成分の値の分だけ拡大します。
2.2. Transformable クラス
M3G では、Transformable クラスと呼ばれる Node クラス及び Texture2D の抽象基底クラスが存在します。このクラスの存在により、 Node クラスや Texture2D クラスといったオブジェクトを直接操作することが可能となっています。また、Transformable クラスは演算のために3次元アフィン変換用の4×4行列を保持しています。
Transformable クラスが認める操作には rotate (回転)、 translate (平行移動)、 scale (拡大・縮小)があり、以下のメソッドにより行われます。これらのメソッドも Transform クラス同様、 Transformable オブジェクトにそれぞれの操作を行う4×4のアフィン変換行列を掛けることで実現しています。それぞれのメソッドが掛ける変換行列の内容については javadoc の Transformable クラスの項をご参照ください。
対象となるモデルに対し、ベクトル ( ax, ay, az ) を軸として angle の分だけ回転を行います。 angle の単位は度 ( degree ) です。このとき回転行列は対象となる行列に対し右から掛けられます。すなわち、このメソッドが呼び出される前に設定された、他のメソッドによる演算が終了した後に回転が行われます。
preRotate( float angle, float ax, float ay, float az )対象となるモデルに対し、ベクトル ( ax, ay, az ) を軸として angle の分だけ回転を行います。 angle の単位は度 ( degree ) です。このとき回転行列は対象となる行列に対し左から掛けられます。すなわち、このメソッドが呼び出される前に設定された、他のメソッドによる演算が開始される前に回転が行われます。
setTranslation ( float tx, float ty, float tz )対象となるモデルの座標を座標 ( tx, ty, tz ) の位置に設定します。
translate ( float tx, float ty, float tz )対象となるモデルを方向ベクトル ( tx, ty, tz ) の分だけ平行移動します。
setScale ( float sx, float sy, float sz )対象となるモデルの拡大率を与えられた各成分値に設定します。
scale ( float sx, float sy, float sz )対象となるモデルを各方向に各成分の値だけ拡大します。
なお、イミディエイトモードの場合 Transformable クラスに直接設定された変換行列は無視されます。
このサンプルでは、イミディエイトモードを使用しているため、 Transform クラスを使用した描画を行っています。
3. モデル、及びカメラの操作
ここでは M3G におけるモデルやカメラの操作について解説します。
3.1 カメラの配置
レンダリングされた3Dモデルはワールド座標系上に配置されます。それらをディスプレイに表示するためにはワールド座標系からカメラ座標系に変換し、そこからさらにスクリーン座標系に変換する必要があります。まずワールド座標系からカメラ座標系に変換するために、ワールド座標系上にカメラを配置します。このとき、カメラを配置するためには方向と位置を表す変換行列を設定する必要があります。
カメラの方向は Transform.postRotate() メソッドによって設定できます。カメラは最初 Z 軸負方向を向いていますが、このメソッドによりカメラ方向を任意軸周りに任意の角度回転させることができ、カメラ自体を任意の方向へ向けることができます。また、カメラの位置は Transform.postTranslate() メソッドで設定できます。各引数がワールド座標上での位置座標を表しています。
* private Camera camera = new Camera ();
* private Transform camPos = new Transform ();
*/
/* カメラの設定 */
camPos.setIdentity ();
camPos.postTranslate ( 0.f, 2.5f, 5.f );
camPos.postRotate ( -20.f, 1.f, 0.f, 0.f );
このサンプルでカメラはワールド座標系上の ( 0.0, 2.5, 5.0 ) の位置で、ベクトル ( 0, 0, -1 ) が X 軸中心に –20 度回転した方向を向いています。
3.2. 3D モデル及びカメラの操作
以下はサンプルコード内でモデル及びカメラに対し回転を行っている部分です。
* private Transform camTrans = new Transform ();
* private Transform boxTrans = new Transform ();
* private float camRot;
* private float boxRot;
* private float rotation = 1.5f;
*/
/* 初期化 */
camTrans.setIdentity ();
/* キー状態取得 */
keyState = getKeyStates ();
/* 回転 */
if ( ( keyState & RIGHT_PRESSED ) != 0 ) {
camRot += rotation;
}
if ( ( keyState & LEFT_PRESSED ) != 0 ) {
camRot -= rotation;
}
keyState = 0;
/* モデルの回転 */
boxRot += rotation;
if ( boxRot > 360.f )
boxRot -= 360.f;
/* カメラが一周したら初期化 */
if ( camRot > 360.f )
camRot -= 360.f;
if ( camRot < -360.f )
camRot += 360.f;
/* 変換行列の設定 */
boxTrans.setIdentity ();
boxTrans.postRotate ( boxRot, 0.f, 1.f, 0.f );
camTrans.postRotate ( camRot, 0.f, 1.f, 0.f );
camTrans.postMultiply ( camPos );
画面の再描画が行われるたびに ( 0, 1, 0 ) 方向を軸として1.5度3Dモデルが回転し、左右キーが押されるたびに原点を中心としてカメラが回転しています。

描画結果

