ゲームプログラミング技術集 
ひっと

ビューとプロジェクション行列でカメラ制御

DirectXを使ったゲームプログラミング例を紹介しています。

カメラ制御の仕組み、ビューとプロジェクション変換行列

ゲームプログラミングにとってカメラ制御ってなんだろかと考えてみると、ビュー変換行列プロジェクション変換行列による画面の見え方ということで多分あってると思います。

ビュー変換行列

ビュー変換行列はカメラの視点をきめるための行列です。
カメラの位置方向を制御します。

プロジェクション変換行列(射影変換行列)

「望遠」「広角」といったカメラのレンズに相当する役割がプロジェクション変換行列にあります。
画角だけでなく描画範囲などの情報も持ちますが、プロジェクション変換行列を図化すると下のようになります。


ビュー変換行列の作りかた

ビュー変換行列を作るのに必要なので、先にカメラの位置と回転を行列で表してみましょう。

カメラの位置と回転を行列にしてみる

DirectXの座標系

DirectXではY軸が画面の上を向いていてZ軸が奥行きを表します。左手座標系といいます。
ビューがセットされていない状態ではカメラは原点にいてZ軸のプラス側を向いています。

カメラの座標変換行列を作る

カメラには3次元上の点と、XYZ各軸の回転角を持たせました。
DirectXに位置や回転の行列を作る関数があるので、これを使えばあっさりプログラミングできます。

まずはカメラの位置を任意の場所へ移動させる行列を作ります。

    D3DXMATRIX mat_move;
    D3DXMatrixTranslation(&mat_move, x, y, z);


つぎにカメラを回転させる行列を作ります。

    //yawはY軸、pitchはX軸、rollはZ軸の回転です。
    D3DXMATRIX mat_rot;
    D3DXMatrixRotationYawPitchRoll( &mat_rot, yaw, pitch, roll );


さて、移動と回転の2つの行列ができました。つぎにこれを合成します。
移動と回転を一つの行列にまとめることができます。

    D3DXMATRIX mat_rotmove;
    mat_rotmove = mat_rot * mat_move;


D3DXMATRIXのかけ算の演算子が使えます。
(D3DXMatrixMultiply関数でも同様のことができます)

行列のかけ算は「回転*移動」と「移動*回転」は違いますので注意して下さい。

行列のかけ算では、左の行列で座標変換した結果をさらに右側の行列で座標変換しています。
今回の例ではカメラを「回転」させた後で「移動」したいので、回転行列が左側です。

これでカメラの座標変換をする行列が完成しました。

カメラの座標変換行列からビュー変換行列を作るには

カメラ自身を一つの行列で表すことができましたが、惜しいことにこれをそのままビュー変換行列に使うことはできません。

ところで。人が右を向いたとき世界は左にうごきますね。そして前に進めば目の前の物体はこちらに迫ってきます。 ビュー変換行列もこれと同様でカメラを中心に世界がどう動くかを表した行列にします。

ビュー変換行列の作り方は簡単です。
カメラ座標変換の逆行列がビュー変換行列になります。

逆行列を作成するための関数にD3DXMatrixInverseが用意されています。

    D3DXMATRIX mat_view;
    D3DXMatrixInverse( &mat_view, &mat_camera );//カメラの逆行列を求める

こうして作ったビュー変換行列をSetTransformでDirect3Dデバイスに渡すとビューの指定が全て完了します。

    LPDIRECT3DDEVICE9* device;  //Direct3Dデバイス
    device->SetTransform( D3DTS_VIEW, &mat_view);

プロジェクション変換行列の作りかた

プロジェクション変換行列を作るにはD3DXMatrixPerspectiveFovLHを使います。
引数は特に難しい物でもないですね。
上の方で紹介した図と同じですけど、引数と見比べてみて下さい。


    LPDIRECT3DDEVICE9* device;  //Direct3Dデバイス

    //プロジェクション変換行列を作成
    D3DXMATRIX matProj;
    D3DXMatrixPerspectiveFovLH( &matProj,
                                (float)(D3DX_PI/4.0), //視野角(ここでは45度をセットしてます)
                                (float)(640/480),     //画面アスペクト比
                                1.0f,                 //クリッピング距離(これより近いのは描画しません)
                                1000000.0f);          //クリッピング距離(これより遠いのは描画しません)

    //プロジェクション変換行列をセット
    device->SetTransform( D3DTS_PROJECTION, &matProj);

      次へ

Direct3Dグラフィック - カメラ制御

ビューとプロジェクション
プログラムとソースコード