DirectX9で3Dのフライトシューティングゲームを作ろうと思っています。
で、地形(山)との衝突判定で詰まっています。
衝突判定をどうやるかネットでいろいろ探したところ「ゲームつくろー」というサイトに出会い、そこの記述を参考に自分ですこし考えてみました。
1.地形のXファイルからメッシュを得る。
2.得たメッシュから座標データを取り出す。
3.抜き取った座標データから表面の三角ポリゴンを作る。
4.三角ポリゴンと自機の位置関係を調べる。
で、これをやろうと思ったのですがメッシュから座標データを取り出し三角ポリゴンを作ることに苦戦しています。
ID3DXBaseMesh::GetVertexBufferをつかったのですが、どの頂点の組み合わせで三角ポリゴンを作ればいいのかわかりません。
頂点インデックスが関係して来るのかと思いいろいろ探し回っているのですが、なかなか見つかりません。
GetVertexBufferで頂点データを得たあとの処理をおしえてください。
また、地形との衝突判定の方法についてもっといい方法があったら教えてください。
地形との衝突判定
Re: 地形との衝突判定
メッシュとの当たり判定なら、D3DXIntersectを使うと楽かもしれません。
頂点データは頂点フォーマットによってサイズが異なります。
ID3DXBaseMesh::GetFVFで得られる頂点フォーマットコードを使ってD3DXGetFVFVertexSizeを呼び出すと頂点データ一個分のサイズを求めることができます。
頂点インデックスはID3DXBaseMesh::LockIndexBufferを使ってポインタを取得できます。yucky001 さんが書きました:で、これをやろうと思ったのですがメッシュから座標データを取り出し三角ポリゴンを作ることに苦戦しています。
ID3DXBaseMesh::GetVertexBufferをつかったのですが、どの頂点の組み合わせで三角ポリゴンを作ればいいのかわかりません。
頂点インデックスが関係して来るのかと思いいろいろ探し回っているのですが、なかなか見つかりません。
頂点データは頂点フォーマットによってサイズが異なります。
ID3DXBaseMesh::GetFVFで得られる頂点フォーマットコードを使ってD3DXGetFVFVertexSizeを呼び出すと頂点データ一個分のサイズを求めることができます。
Re: 地形との衝突判定
ISLeさん、返信ありがとうございます。
教えていただいたD3DXIntersectなのですが、msdnを見ていて10個目の引数に
教えていただいたD3DXIntersectなのですが、msdnを見ていて10個目の引数に
とあったのですが、これは何ですか?pCountOfHits
[out] ppAllHits 配列内のエントリ数を格納する DWORD へのポインタ。
Re: 地形との衝突判定
9番目の引数(ppAllHits)でレイに交差するすべてのポリゴンの情報を持つID3DXBufferオブジェクトへのポインタを取得できますが、それがポリゴン何個分の情報なのかを変数に取得するため、変数のポインタを指定することができます。yucky001 さんが書きました:とあったのですが、これは何ですか?pCountOfHits
[out] ppAllHits 配列内のエントリ数を格納する DWORD へのポインタ。
レイの始点から最も近いポリゴンは除きます。
地形との当たり判定なら最も近いポリゴンだけが分かれば良いと思います。
取得する必要がない出力パラメータにはNULLを指定することができます。
Re: 地形との衝突判定
ISLeさん、返信ありがとうございます。
D3DXIntersectを使って衝突判定用の関数を作ってみましたがうまく動作しません。
この関数で衝突判定を行うと地面にぶつかっているのに返り値として1が返ってきません。
少しD3DXIntersectについて調べていたらメッシュを移動・拡大している場合うまく動作しないと書いてあったのですが、自分は移動も拡大も行っています。
原因は移動・拡大でしょうか?
D3DXIntersectを使って衝突判定用の関数を作ってみましたがうまく動作しません。
int GetCollisionJudge(LPD3DXMESH mesh,D3DXVECTOR3 point,D3DXVECTOR3 direction){
float dis;
BOOL judge;
D3DXIntersect(mesh,&point,&direction,&judge,NULL,NULL,NULL,&dis,NULL,NULL);
if(judge){
if(dis<0){
return 1;
}else{
return 0;
}
}else{
return 0;
}
}
少しD3DXIntersectについて調べていたらメッシュを移動・拡大している場合うまく動作しないと書いてあったのですが、自分は移動も拡大も行っています。
原因は移動・拡大でしょうか?
Re: 地形との衝突判定
D3DXIntersect 関数は、モデルをローカル座標で計算します(当然といえば当然ですが)
モデルに移動、拡大を行っている場合、
レイに対して(レイの始点、向き両方に対して)、
モデルを描画する時に使用しているワールド行列の逆行列を、あらかじめ掛け算しておく必要があります。
注意点としては、向きは平行移動されると困るので、D3DXVec3TransformCoordを使用するところでしょうか
(始点と終点で計算する場合は普通に掛け算するだけでよいですが)
【蛇足】
別なアプローチでは、描画用メッシュとは別に、ポリゴン数を減らしたコリジョン用ポリゴンデータを用意し、
それを読み込んで衝突判定を行う方法もあります。
モデラーでwavefront objなどの読みやすい形式で保存し、
そこからポリゴンデータだけ抽出し、独自形式にでも変換すればよいでしょう。
こちらは少し手間が増えますが、柔軟なアプローチではないかと思います。
【追記】
関数名を修正しました
モデルに移動、拡大を行っている場合、
レイに対して(レイの始点、向き両方に対して)、
モデルを描画する時に使用しているワールド行列の逆行列を、あらかじめ掛け算しておく必要があります。
注意点としては、向きは平行移動されると困るので、D3DXVec3TransformCoordを使用するところでしょうか
(始点と終点で計算する場合は普通に掛け算するだけでよいですが)
【蛇足】
別なアプローチでは、描画用メッシュとは別に、ポリゴン数を減らしたコリジョン用ポリゴンデータを用意し、
それを読み込んで衝突判定を行う方法もあります。
モデラーでwavefront objなどの読みやすい形式で保存し、
そこからポリゴンデータだけ抽出し、独自形式にでも変換すればよいでしょう。
こちらは少し手間が増えますが、柔軟なアプローチではないかと思います。
【追記】
関数名を修正しました
最後に編集したユーザー うしお on 2011年9月07日(水) 10:27 [ 編集 1 回目 ]
Re: 地形との衝突判定
うしおさん、返信ありがとうございます。
教えていただいた通り逆行列をかけて判定をしたところ、なんとも言えない結果になりました。
途中までは正しく動作するのですが、機体がある一線を越えると常に当たっていると判定されてしまいます。
何故でしょうか?
書き換えた関数です。↓
教えていただいた通り逆行列をかけて判定をしたところ、なんとも言えない結果になりました。
途中までは正しく動作するのですが、機体がある一線を越えると常に当たっていると判定されてしまいます。
何故でしょうか?
書き換えた関数です。↓
int GetCollisionJudge(LPD3DXMESH mesh,D3DXVECTOR3 point,D3DXVECTOR3 direction,D3DXMATRIX mat,float distance){
float dis;
BOOL judge;
D3DXMATRIX matI;
D3DXMatrixInverse(&matI,NULL,&mat);
D3DXVECTOR3 pointI,directionI;
D3DXVec3TransformCoord(&pointI,&point,&matI);
D3DXVec3TransformCoord(&directionI,&direction,&matI);
D3DXIntersect(mesh,&pointI,&directionI,&judge,NULL,NULL,NULL,&dis,NULL,NULL);
if(judge){
if(dis<distance){
return 1;
}else{
return 0;
}
}else{
return 0;
}
}
Re: 地形との衝突判定
向きは平行移動されると困るので、D3DXVec3TransformCoordを使用する必要があります。
ご注意ください。
ご注意ください。