Platform SDK: DirectX

ビュー行列の設定

[C++]

この SDK 付属の D3dutil.cpp ソース ファイルの D3DUtil_SetViewMatrix ヘルパー関数は、この関数に渡されるカメラ位置座標と注視点に基づいてビュー行列を作成する。この関数は、MagnitudeCrossProduct、および DotProduct D3D_OVERLOADS ヘルパー関数を使用する。

HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom, 
       D3DVECTOR& vAt, D3DVECTOR& vWorldUp )
{
// 奥行きを示す Z 軸の基底ベクトルを取得する。これは、
// 注視点に対する視点とは異なる。
    D3DVECTOR vView = vAt - vFrom;
 
    FLOAT fLength = Magnitude( vView );
    if( fLength < 1e-6f )
return E_INVALIDARG;
 
// z 軸の基底ベクトルを正規化する。
    vView /= fLength;
 
// 内積を取得して、上方向ベクトルに対する、Z 軸の基底ベクトルの
// 射影を計算する。この射影は y 軸の基底ベクトルである。
    FLOAT fDotProduct = DotProduct( vWorldUp, vView );
 
    D3DVECTOR vUp = vWorldUp - fDotProduct * vView;
 
// 不正な上方向ベクトルを入力したために
// ベクトルがゼロに近くなった場合は、ベクトルをデフォルト値にする。
    if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
    {
vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView;
 
// ベクトルがなおゼロに近ければ、別の軸を利用する。
if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
{
    vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView;
 
    if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
return E_INVALIDARG;
}
    }
 
// y 軸の基底ベクトルを正規化する。
vUp /= fLength;
 
// x 軸の基底ベクトルは、y 軸および z 軸の基底ベクトルの
// 外積として簡単に求められる。
D3DVECTOR vRight = CrossProduct( vUp, vView );
    
// 行列の作成を開始する。先頭の 3 行には、
// ビューを注視点で回転するための基底ベクトルを格納する。
    D3DUtil_SetIdentityMatrix( mat );
    mat._11 = vRight.x;    mat._12 = vUp.x;    mat._13 = vView.x;
    mat._21 = vRight.y;    mat._22 = vUp.y;    mat._23 = vView.y;
    mat._31 = vRight.z;    mat._32 = vUp.z;    mat._33 = vView.z;
 
// 移動値を実行する (回転はまだ視点にある)。
    mat._41 = - DotProduct( vFrom, vRight );
    mat._42 = - DotProduct( vFrom, vUp );
    mat._43 = - DotProduct( vFrom, vView );
 
    return S_OK;
}

ワールド トランスフォームの場合と同様、IDirect3DDevice7::SetTransform メソッドを呼び出してビュー トランスフォームを設定し、第 1 パラメータに D3DTRANSFORMSTATE_VIEW フラグを指定する。詳細については、「トランスフォームの設定」を参照すること。

[Visual Basic]

Visual Basic アプリケーションでは、DirectX7.ViewMatrix メソッドを使用して、カメラ位置座標、注視点、"上方向" ベクトル (通常は 0,1,0)、およびラジアン単位で指定する回転値に基づいてビュー行列を作成する。

次の Visual Basic コードは、ViewMatrix メソッドの使用方法を示す。

' この例では、g_dx 変数にグローバル DirectX7 オブジェクトへの
' 有効な参照が格納されているとする。
Dim matView  As D3DMATRIX
Dim vFrom As D3DVECTOR, _ 
vTo As D3DVECTOR, _ 
vUp As D3DVECTOR

vFrom.x = 0:vFrom.y = 0:vFrom.z = -15
vTo.x = 0:vTo.y = 0:vTo.z = 0
vUp.x = 0:vUp.y = 1:vUp.z = 0

' 行列を初期化して単位行列にする。
g_dx.IdentityMatrix matView

' 0,0,-15 にあるカメラでビュー行列を作成する。
' これは、ワールド原点を指し、vFrom->vTo ベクトルを中心とした回転を行わない。
Call g_dx.ViewMatrix(matView, vFrom, vTo, vUp, 0)

ワールド トランスフォームの場合と同様、Direct3DDevice7::SetTransform メソッドを呼び出してビュー トランスフォームを設定し、第 1 パラメータに D3DTRANSFORMSTATE_VIEW フラグを指定する。詳細については、「トランスフォームの設定」を参照すること。

パフォーマンスの最適化  Direct3D では、設定されたワールド行列およびビュー行列を使用して、いくつかの内部データ構造を構築する。新しいワールド行列またはビュー行列を設定するたびに、関係する内部構造が再計算される。これらの行列をフレームごとに 2 万回も設定するなど頻繁に設定すると、多大な計算負荷が発生する。必要な計算を最小限に抑えるには、ワールド行列として設定する "ワールドビュー" 行列にワールド行列およびビュー行列を連結し、次にビュー行列を単位行列に設定する。ワールド行列およびビュー行列の各キャッシュ コピーは保持しておくこと。必要に応じてワールド行列を修正、連結、およびリセットできる (Direct3D のサンプルでは、簡潔であることを優先して、この最適化はほとんど用いていない)。