自キャラ足元よりY軸マイナス方向にレイを飛ばし、床(ステージ)メッシュとの接触点距離を返す関数を作りました。
現在の主な流れを大まかに記述しますと、
void rayControl()
{
・レイの始点座標、方向ベクトルの代入
始点座標は、自キャラ足元。 ベクトルはY軸マイナス方向、真下ですね
posが、自キャラ座標となっています。
・bool hitCheck_Stage関数の呼び出し
引数は、上記レイ情報2種と、最終的な接触点距離を格納する distance変数
if( map->hitCheck_Stage(&firstPos, &firstDir, &ray.distance) )
{
pos.y -= (ray.distance);
pos.y += 1.0f;
}
else
{
pos.y --;
}
}
bool hitCheck_Stage(D3DXVECTOR3* rayPos, D3DXVECTOR3* rayDir, float* distance)
{
・hitCheck_Stage関数では、マップの座標、スケールを元に、ワールド変換行列を作成し
逆行列を算出しています。 その逆行列を使い、受け取ったレイを逆トランスフォームします。
・hitCheck_RayMeshを呼び出し、メッシュの格納されている配列番号(enum)と、逆トランスフォーム後の
レイ情報、最終的な接触点距離を格納する為のdistanceを引数としています。
hitCheck_RayMesh(eMeshID::MAP, &InvRayPos, &InvRayDir, distance)
・Raymesh関数で TRUE が返ってくるとと、この関数でも true が返ります。
}
BOOL hitCheck_RayMesh( int meshNum, // メッシュ番号
D3DXVECTOR3* pos, // レイの始点座標
D3DXVECTOR3* direction, // レイの方向ベクトル
float* distance ) //
{
BOOL hit;
FLOAT u, v, dist;
DWORD faceIndex;
Mesh::sObj* obj = &Mesh::table[meshNum];
D3DXIntersect( obj->mesh, // ID3DXBaseMeshインターフェイスへのポインター
pos, // レイの始点座標
direction, // レイの方向ベクトル
&hit, // レイがメッシュの三角面に接触するときTRUEを返す
&faceIndex, // pHitがTRUEの場合に、レイの始点に最も近い面のインデックス値を指す
&u, // 重心ヒット座標U
&v, // 重心ヒット座標V
&dist, // 接触点までの距離(ベクトルを正規化しておくと純粋な距離がでる)
NULL, // 全ての接触面情報を受け取ることができる
NULL ); // 全ての接触面情報の件数
if( hit )
{
*(distance) = (float)dist;
return TRUE;
}
return FALSE;
}
このように、接触点距離を1番最初の関数内にあるray.distanceに格納し
自キャラY座標と計算を行い、床との距離を求めています。
この流れで一応、平面上での歩行はできているのですが、床とレイ始点までの距離が0?(重なる?)になると
判定がなくなりめり込んでしまうので、 床と接触をしている場合は常に pos.y に 1.0f をプラスしています。
長くなりましたが何が言いたいのかというと、この状態だと緩やかな斜面はめり込みもせず問題ないのですが
ちょっと急な斜面になりますと、地面にうまってしまいます。
もう一つは、下記のような段差
-----
|
---------
で、飛び降りると目にもとまらぬ速さで着地してしまいます。 もっとふわっと降りてほしいのですが・・・
問題点は、・pos.yに直接、算出した床との距離を代入してしまっている点。
・pos.y += 1.0f や pos.y --;
がとっても怪しいと感じているのですが、どのようにしたらいいかも分からず挫折寸前です・・・
長くなりましたが、何かご教授もらえたら幸いです。 よろしくお願いします。
とりあえず、次のレスで載せておきます。