Japanese | English | Korean

Samples

座標系とカメラ

ここではMascotCapsuleに用いられている座標系とその変換、およびカメラの設定について解説します。

目次

1. 座標系

MascotCapsuleではモデル座標系・ワールド座標系・カメラ座標系・スクリーン座標系の4つの座標系が用いられています。これらの座標系はすべて直交座標系として扱います。

モデル座標系

各3Dモデルごとに用意された座標系です。

ワールド座標系

ワールドの基準となる座標系です。各3Dモデルはワールド座標系上に配置されます。

カメラ座標系

カメラから見たときの座標系です。カメラ座標系で描画される領域は ニアクリップ面・ファークリップ面・画角などを定めることによってできる視体積内になります。

スクリーン座標系

ディスプレイに実際に描画されるときの座標系です。カメラ座標系における 視体積を1辺の長さが1の立方体に拡大・縮小し、それをスクリーンに投影します。

MascotCapsuleでは、ディスプレイに3Dグラフィックスを表示するために、
モデル座標系 -> ワールド座標系 -> カメラ座標系 -> スクリーン座標系
という3回の座標変換を行います。



2. AffineTrans クラス

AffineTransクラスは3次元アフィン変換用の4×4行列を保持するクラスです。カメラや3Dオブジェクトの配置や移動はこのクラスを用いて行います。ここではAffineTransクラスを用いたカメラの配置および3Dモデルの操作について解説します。

2.1. カメラの配置

レンダリングされた3Dモデルはワールド座標系上に配置されます。
それらをディスプレイに表示するためにはワールド座標系からカメラ座標系に変換し、そこから、さらにスクリーン座標系に変換する必要があります。そのためにまず、ワールド座標系からカメラ座標系に変換するために、ワールド座標系上にカメラを配置します。
カメラがどのように配置されるかはカメラの位置(position)・参照方向(lookAt)・カメラの頭頂部の向き(up)をそれぞれ3次元ベクトルで指定することで定まります。

MascotCapsuleでは、その3次元ベクトルをVector3Dクラスという3次元ベクトルクラスのインスタンスとして扱います。Vector3Dクラスは、直交座標系におけるx成分、y成分、z成分の3つを要素としてもつクラスです。
カメラを配置するには、position・lookAt・upベクトルをそれぞれVector3Dクラスのオブジェクトとして定義し、それらを引数としてAffineTransクラスのsetViewTrans( Vector3D position, Vector3D lookAt, Vector3D up )メソッドを用いることで行います。

lookAtメソッドが引数として取るこれら3つのVector3Dオブジェクトの詳細は次の通りです。

position

カメラを配置する位置です。

lookAt

positionが示す位置に配置されたカメラは、そこから点lookAtがある方に向かってカメラを向けます。つまり、カメラが向く方向ベクトルはlookAtベクトルからpositionベクトルを引いたものになります。

up

カメラの頭頂部の向きです。このベクトルの向きがディスプレイの上方向になります。ただし、カメラが向く方向ベクトルがupベクトルと反対方向になるようにpositionベクトルとlookAtベクトルを定めることはできません。また、upベクトルは方向ベクトルですので、通常は正規化されたベクトル(長さが1のベクトル)を設定してください。

これら3つのオブジェクトを上に挙げた順にlookAtメソッドの引数に設定することで、カメラの配置を定めます。


以下はサンプルコード内でカメラを設定している部分です。

/**
  * CanvasEx
  * コンストラクタ(データロード等初期化)
  */
public CanvasEx(){

. . .

/* カメラ座標への視点変換行列の作成 */
vtrans.setViewTrans( new Vector3D( 0, 512, 2048 ),
new Vector3D( 0, -512, -4096 ),
new Vector3D( 0, 4096, 0 ));

2.2. 3D モデルの操作

3DモデルにAffineTransクラスによる行列演算を施すことで、モデルの回転・移動・拡大縮小などを行うことができます。サンプルプログラムでは、毎描画ごとに視点座標への変換行列に対し、Y軸を軸として1度回転させる行列をかけることで、カメラが回転しているように見せています。

/* カメラ回転 */
AffineTrans trans = new AffineTrans();
trans.setRotationY( 4096 / 360 );
vtrans.multiply( trans );

/* 座標変換関係設定 */
layout.setAffineTrans( vtrans );


SampleCamera 描画結果