[DXライブラリ]コリジョン関数について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
ptolemy
記事: 258
登録日時: 11年前

[DXライブラリ]コリジョン関数について

#1

投稿記事 by ptolemy » 10年前

今回は、DXライブラリのコリジョン関数である、MV1_COLL_RESULT_POLY_DIM MV1CollCheck_Capsule関数について質問があります。

私は3D内でポリゴンとカプセルの衝突判定をするために、
(カプセルと壁のようなモデルとの衝突判定です。)
①衝突地点とカプセルの中心との距離を取得
②カプセルの半径と①によって取得した距離の差が押し出し量
③当たったポリゴンの法線ベクトルの方向にカプセル押し出す

というような形で行っています。
しかし、カプセルの場合は衝突した地点が求められないため、
「カプセルの半径と同じ大きさで移動ベクトル方向に向くカプセルの中心とを結ぶ線分」を利用して
MV1_COLL_RESULT_POLY MV1CollCheck_Line関数で衝突地点を取得しております。

そこで問題が発生しました。
角などに当たると、線分のためちょうど壁同士が交わった点に当たり、モデルの形によってはすり抜けが発生してしまいます。また、角に限らずモデルの形状によって時々発生します。
それ以外は特に問題がありませんでした。

よって、線分を使わずに衝突地点を求める方法としてほかに方法がないでしょうか?
そして、なぜカプセルの場合は地点が取得できないのでしょうか?複数出るためでしょうか?

分かりずらいと思いますがご回答してくだされば幸いです。
よろしくお願いします。

イメージとしてはこのような感じです。
上から見た図です。
添付ファイル
000001.jpg
000001.jpg (13.24 KiB) 閲覧数: 4223 回

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: [DXライブラリ]コリジョン関数について

#2

投稿記事 by softya(ソフト屋) » 10年前

衝突した面は分かるはずなので、その面の中央を通る線分から押出量は計算できませんか?
やった事ないので保証は出来かねますけど。

あとは、DXライブラリ御本家のサンプルを参考にされると良いかもしれません。
新しく出た本の3Dゲームのサンプルもありますし。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
ptolemy
記事: 258
登録日時: 11年前

Re: [DXライブラリ]コリジョン関数について

#3

投稿記事 by ptolemy » 10年前

ご回答ありがとうございます。
softya(ソフト屋) さんが書きました:衝突した面は分かるはずなので、その面の中央を通る線分から押出量は計算できませんか?
やった事ないので保証は出来かねますけど。
なるほど。ポリゴンの中心座標ということですね。
ポリゴンの三点座標は取得出来るので、試したいと思います。
softya(ソフト屋) さんが書きました:衝突した面は分かるはずなので、その面の中央を通る線分から押出量は計算できませんか?
やった事ないので保証は出来かねますけど。

あとは、DXライブラリ御本家のサンプルを参考にされると良いかもしれません。
新しく出た本の3Dゲームのサンプルもありますし。
上記の方法で出来なかったらサンプルを参考にしたいと思います。

アバター
ptolemy
記事: 258
登録日時: 11年前

Re: [DXライブラリ]コリジョン関数について

#4

投稿記事 by ptolemy » 10年前

できました。
ポリゴンの中心座標ではありませんが、ポリゴンの数分押し出すという処理が必要だったようです。

コード:

/*変数一部抜粋*/

	MV1_COLL_RESULT_POLY_DIM	wall ; //壁のコリジョン構造体
	VECTOR	slide_vector ; //スライドベクトル
	VECTOR	capsule ; //カプセルの座標
	VECTOR	capsule_move_vector ; //カプセルの進行ベクトル
	int	capsule_move_flag ; //カプセルの移動フラグ

/*DXライブラリにもありますが...*/

	//二つのベクトルの外積を求める関数
	VECTOR	CrossVector( VECTOR	Avector, VECTOR	Bvector ) {

		VECTOR	Cross ;

		Cross.x = Avector.y * Bvector.z - Avector.z * Bvector.y ;
		Cross.y = Avector.z * Bvector.x - Avector.x * Bvector.z ;
		Cross.z = Avector.x * Bvector.y - Avector.y * Bvector.x ;

		return	Cross ;

	}

/*ここから別に抜粋*/

	//壁のポリゴンと衝突したら
	if( wall.HitNum != 0 ) {

		//衝突したポリゴン分法線ベクトルの方向へ押し出す
		for( int i = 0 ; i < wall.HitNum ; i ++ ) {

			capsule.x += wall.Dim->Normal.x ;
			capsule.z += wall.Dim->Normal.z ;

		}

		//カプセルが移動したら
		if( capsule_move_flag != 0 ) {

			//横にスライドするベクトルを取得
			//当たったポリゴンの法線ベクトルと進行ベクトルの外積とポリゴンの法線ベクトルの外積
			slide_vector = CrossVector( wall.Dim->Normal, CrossVector( capsule_move_vector, wall.Dim->Normal ) ) ;

			//横にスライド
			capsule.x += slide_vector.x ;
			capsule.z += slide_vector.z ;

		}

	}else{

		//衝突していない時は後始末を行う
		MV1CollResultPolyDimTerminate( wall ) ;

	}
あくまで一部抜粋して少し改変したものです。

今考えてみるとそこまで難しいことではなかった気がしますが、当たった地点というものにとらわれていました。

今回は本当にありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る