ホーム < ゲームつくろー! < DirectX技術編 < オブジェクトを注視しながら一緒に動くカメラ

その36 オブジェクトを注視しながら一緒に動くカメラ


 ワールドに置いたオブジェクトは、カメラを通して画面に出力されます。現実のTVや映画と同様に、3Dゲームにおいてもカメラの操作はゲームの演出を決める重要な要素になります。DirectXのカメラの概念は「ビュー変換行列」にすべて集約されます。そして、そのビュー変換行列は殆どの場合「D3DXMatrixLookAtLH関数」で作成します。D3DXMatrixLookAtLH関数は「位置」「注視点」そして「空の方向(上方向)」でカメラの位置姿勢を決定します。つまり、DirectXにおいてカメラとは、この3要素で操作されるオブジェクトに他なりません。

 あるオブジェクトを追従する、もしくはキャラクタ視点として振舞うためには、オブジェクトの位置や姿勢の変化にカメラが対応しなければなりません。しかし、オブジェクトの位置決めは通常「ワールド変換行列」を用います。「位置」「注視点」「空の方向(上方向)」ではないわけです。では、カメラ位置をオブジェクトに合わせるにはどうしたら良いのでしょうか?

 この章ではそういったオブジェクトを注目しながら一緒に付きまとうカメラの設定について考えて見ます。



@ 原理は簡単

 冒頭の繰り返しになりますが、カメラは「位置」「注視点」そして「空の方向(上方向)」の3つの要素で姿勢が決定されます。これは、簡単に言えば「L字定規」だと思って頂ければいいかなと思います(本当は少し違います)。図にしますと次のような感じでしょうか:

 位置はC、注視点はL、そして上方向はベクトルCUに相当します。これが定まっていれば、カメラの姿勢は完全に決まるわけです。

 オブジェクトにカメラが追従するということは、オブジェクトとカメラの間に一定の距離と姿勢の関係があるわけです。これは「カメラがオブジェクトのローカル座標内にある」ことを意味します。親が対象オブジェクトであるとも言えます。ですから、カメラの姿勢も親のローカル座標で定義されます。そして、親がワールド変換行列でワールドに置かれる時、「カメラも同じワールド変換行列で移動される」事になります。

 カメラの姿勢を保ったままワールド変換するには、「点U、C、Lを座標変換」すれば良いわけです。これは非常に単純な行列計算になります。すなわち、

という計算で求められます。ここでCBeforeがローカル座標にあるカメラの位置(点)、Worldがワールド変換行列、そしてCAfterが変換された点の位置です。3点についてこの計算を行うと、ワールド空間での位置と上方向ベクトルが算出されるので、その値を用いてD3DXMatrixLookAtLH関数からビュー変換行列を求めればOKです。尚、点×行列を3回やるのは面倒ですから、

と行列としてまとめた方が楽ですし、きっと計算も速くなります。2行目の4列目、ここが「0」である事に注目して下さい。2行目は「上方向」を表すベクトルです。このベクトルは回転だけを適用させなければなりません。2行4列目が「1」だとワールド変換行列のオフセットが加算されてしまいます。ベクトルがオフセットされると、別の場所を指してしまいますよね。



A カメラクラス

 カメラも1つのオブジェクトと考えますと、カメラクラスを定義する事が出来ます。上のような計算はカメラの内部事情ですからカメラクラスにさせるべき事です。コンセプトとしては、カメラのローカル位置を定義しておいて、外部からワールド変換行列を与えると対応するビュー変換行列を返すような仕組みを作っておけば便利でしょう。メソッドの仮組みはこんな感じです。

CCamera::GetViewMatrixメソッド
void CCamera::GetViewMatrix( D3DXMATRIX *pViewOut, D3DXMATRIX *world )
{
   // カメラ姿勢をワールド変換
   D3DXMATIRX CameraW = m_LocalMat * world;

   // ビュー変換行列を生成
   D3DXMatrixLookAtLH(
        pViewOut,
        &D3DXVECOTR3( CameraW._11, CameraW._12, CameraW._13 ),
        &D3DXVECOTR3( CameraW._31, CameraW._32, CameraW._33 ),
        &D3DXVECTOR3( CameraW._21, CameraW._22, CameraW._23 )
   );
}

 m_LocalMatは@で示したカメラのローカル座標と姿勢が格納されています。それにワールド変換行列を掛けてカメラの位置・姿勢を更新し、ビュー行列を作成しています。


 この仕組みを作ってしまうと、注視するオブジェクトの振る舞い(ワールド変換)に付随するカメラができてしまいます。後はカメラのローカル座標を変えれば、オブジェクトの周囲を回したり、上下に移動したりと自由に出来ます。これが威力を発揮するのは、例えば3D空間を飛び回る戦闘機から見た視点や、RPGで自分視点になる時、部屋の中の固定カメラ(部屋自体がワールド変換されても映像は同じ)などです。カメラクラス自体は一般的に広く使えると思いますので、色々と工夫してみて下さい。