ホームゲームつくろー!衝突判定編<Direct3DXのヘルパー関数群

実装編
その2 Direct3DXのヘルパー関数群


 Direct3DXには便利なヘルパー関数が多数用意されています。これらを使えば、わざわざ行列を定義したり、内積・外積の関数群などを自作する必要が無くなります。信用のあるヘルパー関数を有効に使い、衝突を計算しましょう。


○ ベクトル系
 ・ 内積
 ・ 外積
 ・ ベクトルの大きさ
 ・ 内分点

○ 行列系
 ・ 単位行列作成
 ・ 行列の積
 ・ X軸回転行列作成
 ・ Y軸回転行列作成
 ・ Z軸回転行列作成
 ・ ヨーピッチロール指定による回転行列作成
 ・ 平行移動行列作成
 ・ 頂点変換

○ 平面系
 ・ 平面と点の位置関係を検査
 ・ 平面とベクトルの内積
 ・ 点と法線から平面を作成
 ・ 平面を突き抜ける直線の貫通点を取得



○ ベクトル系

内積
D3DXVec3Dot 関数
FLOAT D3DXVec3Dot(      
    CONST D3DXVECTOR3 *pV1,
   CONST D3DXVECTOR3 *pV2
);

 内積を計算します。Direct3DXではベクトルをD3DXVECTOR3構造体で定義します。戻り値が内積の値になります。

外積
D3DXVec3Cross 関数
D3DXVECTOR3 *D3DXVec3Cross(      
    D3DXVECTOR3 *pOut,
    CONST D3DXVECTOR3 *pV1,
    CONST D3DXVECTOR3 *pV2
);

 外積を計算します。pOutに出力先の構造体を指定します。また戻り値にも計算結果が返ります。外積ですからpV1とpV2を逆にすると正反対の結果が出ますから気をつけてください。

ベクトルの大きさ
D3DXVec3Length 関数
FLOAT D3DXVec3Length(
    CONST D3DXVECTOR3 *pV
);

3Dベクトルの大きさを返します。

内分点
D3DXVec3Lerp 関数
D3DXVECTOR3 *D3DXVec3Lerp(      
    D3DXVECTOR3 *pOut,
    CONST D3DXVECTOR3 *pV1,
    CONST D3DXVECTOR3 *pV2,
    FLOAT s
);

 2つのベクトルの内分点(内分ベクトル)を算出します。sに内分比を指定すると、その位置ベクトルを算出してくれます。内分は何かと使うのでありがたいです。

○ 行列系

単位行列作成
D3DXMatrixIdentity 関数
D3DXMATRIX *D3DXMatrixIdentity(      
    D3DXMATRIX *pOut
);

 単位行列を作成します。引数に渡した行列が単位行列として初期化されます。自分で構造体を初期化すると意外と大変なんです(D3DXMATRIXは4×4の行列です)。

行列の積
D3DXMatrixMultiply 関数
D3DXMATRIX *D3DXMatrixMultiply(      
    D3DXMATRIX *pOut,
    CONST D3DXMATRIX *pM1,
    CONST D3DXMATRIX *pM2
);

 行列の掛け算を行います。大変便利な関数です。pM1にpM2を掛けた結果をpOutに返します。関数の戻り値にも同じ結果が返ります。

X軸回転行列作成
D3DXMatrixRotationX 関数
D3DXMATRIX *D3DXMatrixRotationX(      
    D3DXMATRIX *pOut,
    FLOAT Angle
);

 X軸を回転軸としAngleだけ回転させる回転行列を作成します。回転方向は軸上から原点方向を向いた時に右回りが正とされます。(1, 0, 0)から原点を見たときに右回転に見えると言うことです。

Y軸回転行列作成
D3DXMatrixRotationY 関数
D3DXMATRIX *D3DXMatrixRotationY(      
    D3DXMATRIX *pOut,
    FLOAT Angle
);

 Y軸を回転軸としAngleだけ回転させる回転行列を作成します。回転方向は軸上から原点方向を向いた時に右回りが正とされます。(0, 1, 0)から原点を見たときに右回転に見えると言うことです。

Z軸回転行列作成
D3DXMatrixRotationZ 関数
D3DXMATRIX *D3DXMatrixRotationZ(      
    D3DXMATRIX *pOut,
    FLOAT Angle
);

 Z軸を回転軸としAngleだけ回転させる回転行列を作成します。回転方向は軸上から原点方向を向いた時に右回りが正とされます。(0, 0, 1)から原点を見たときに右回転に見えると言うことです。

ヨーピッチロール指定による回転行列作成
D3DXMatrixRotationYawPitchRoll 関数
D3DXMATRIX *D3DXMatrixRotationYawPitchRoll(      
    D3DXMATRIX *pOut,
    FLOAT Yaw,
    FLOAT Pitch,
    FLOAT Roll
);

 ヨー・ピッチ・ロールを指定して回転行列を作成します。ロールはZ軸回転に相当します。ピッチがX軸回転、ヨーがY軸回転です。この順番に回転する行列が作成されます。これらの用語は飛行機で良く使われます。飛行機が曲芸飛行などでぐるぐる回転するのは「ロール回転」です。上昇や下降時に頭を上げたり下げたりするのがピッチ、姿勢(視線)を保ったまま左や右に回転するのがヨーです。イメージし難い方は「エースコンバット(ナムコ)」をしてみると「な〜るほど」と良く分かりますよ(笑)

平行移動行列作成(オフセット)
D3DXMatrixTranslation 関数
D3DXMATRIX *D3DXMatrixTranslation(      
    D3DXMATRIX *pOut,
    FLOAT x,
    FLOAT y,
    FLOAT z
);

 指定の位置に頂点をオフセットする行列を作成します。ワールド座標上を自由に移動するためにはこの関数が必須になります。

頂点変換
D3DXVec3TransformCoord 関数
D3DXVECTOR3 *WINAPI D3DXVec3TransformCoord(
    D3DXVECTOR3 *pOut,
    CONST D3DXVECTOR3 *pV,  
   CONST D3DXMATRIX *pM
);

 指定の変換行列pMを用いて頂点pVを変換します。結果は変換後の頂点となります。衝突判定では本当に多様する関数でしょう。

○ 平面系

平面と点の位置関係を検査
D3DXPlaneDotCoord 関数
FLOAT D3DXPlaneDotCoord(      
    CONST D3DXPLANE *pP,
    CONST D3DXVECTOR3 *pV
);

 平面を表すpP(4次元ベクトル)と点の位置を表すpV(3次元ベクトル)から、平面と点の位置関係を検査します。戻り値がプラスの場合、点は平面の表側(法線が突き出ている方)になります。マイナスだと裏側です。ゼロだと点は平面上に載っていることになります。また、戻り値を平面の法線の大きさで割ると、点から平面までの距離を求めることができます。よって、pPに与える平面の係数a,b,cを標準化して法線の大きさを1にしてしまうと、この戻り値がそのまま平面までの距離となります!係数の標準化はD3DXPlaneNormalize関数で行えます。このコンビは使えるのですよ(^-^)

平面とベクトルの内積
D3DXPlaneDotNormal 関数
FLOAT D3DXPlaneDotNormal(      
    CONST D3DXPLANE *pP,
    CONST D3DXVECTOR3 *pV
);

 平面の法線ベクトルと任意のベクトルとの内積を計算してくれる関数です。平面の法線ベクトルを標準化しておけば、任意のベクトルpVの大きさで戻り値を割ると、cos(θ)が出てきます。平面に対してベクトルがどれだけ傾いているかをすぐに出せます。

点と法線から平面を作成
D3DXPlaneFromPointNormal 関数
D3DXPLANE *D3DXPlaneFromPointNormal(      
    D3DXPLANE *pOut,
    CONST D3DXVECTOR3 *pPoint,
    CONST D3DXVECTOR3 *pNormal
);

 法線ベクトルと平面上の1点から、平面(D3DPLANE)を作成してくれます。点を固定して法線だけを変えれば、ある点を中心として平面が自由に動き回ります。ポリゴンの頂点の1つと法線ベクトルを与えれば、ポリゴンにぴったりくっつく平面も作成できます。

平面を突き抜ける直線の貫通点を取得
D3DXPlaneIntersectLine 関数
D3DXVECTOR3 *D3DXPlaneIntersectLine(      
    D3DXVECTOR3 *pOut,
    CONST D3DXPLANE *pP,
    CONST D3DXVECTOR3 *pV1,
    CONST D3DXVECTOR3 *pV2
);

 平面を突き抜ける直線の貫通点の座標を取得します。これは強烈に使える関数です!直線は2点を与える方式です(pV1, pV2)。もし直線と平面が平行ならば、戻り値にはNULLが返ります。この関数をうまく使えば、平面と線分、ポリゴンと線分など、貫通に関する判定が随分と楽になります。