308.メッシュの三角形の取得

 メッシュの三角形(の集合)を取得したり、その三角形と線分の衝突判定を行うなどの処理があると便利な場合があります。
 例えば剣で戦う場合など、相手のどの部位に当たったのかを知りたいときに、剣とメッシュの三角形と衝突判定(交差判定)を行って、その後の処理ができたりすると便利ですね。
 またでこぼこした床とのレイ判定などにも使えます。

 まずFullSample308を実行してみましょう。以下のような画面が出てきます。
 このサンプルは処理が重いのでリリースモードで実行してください。そうするとそこそこのスピードが出ます。

 

図0308a

 プレイヤーはBボタンで棒を振り回すことができます。右のボックス、および左のモデルに振り回した棒が当たると当たった場所からスパークがでます。
 当たった場所はメッシュの三角形上の点で、アニメーションでスキン処理されているメッシュでもそこに当たります。

Drawコンポーネントで交差判定処理

 このサンプルはUpdate処理の章に入ってますがDrawコンポーネントと密接な関係があります。
 まず、右側のボックスであるEnemyBoxクラスから見ていきましょう。
 使っているのは普通のスタティックメッシュですがIsHitSegmentTriangles()という関数があります。
 この関数の実体は以下です。
bool EnemyBox::IsHitSegmentTriangles(const Vec3& StartPos, const Vec3& EndPos, Vec3& HitPoint) {
    auto PtrDraw = GetComponent<BcPNTStaticDraw>();
    TRIANGLE tri;
    return PtrDraw->HitTestStaticMeshSegmentTriangles(StartPos, EndPos, HitPoint, tri);
}
 ここではBcPNTStaticDraw描画コンポーネントを取得してそのHitTestStaticMeshSegmentTriangles()関数を呼び出しています。この関数は、線分とメッシュ内の三角形と交差判定を行い、交差していたらHitPointに交差点を代入します。
 このサンプルでは使ってませんが交差した三角形も習得できます。

 続いてボーン付きのメッシュです。
 こちらはBoneChara::IsHitSegmentTriangles()関数に記述があります。以下が実体です。
bool BoneChara::IsHitSegmentTriangles(const Vec3& StartPos, const Vec3& EndPos, Vec3& HitPoint) {
    auto PtrDraw = GetComponent<BcPNTBoneModelDraw>();
    TRIANGLE tri;
    return PtrDraw->HitTestSkinedMeshSegmentTriangles(StartPos, EndPos, HitPoint, tri);

}
 こちらも同様にBcPNTBoneModelDraw描画コンポーネントを取り出して、そのHitTestSkinedMeshSegmentTriangles()関数を呼び出しています。この処理で、スキン処理済みの三角形と線分が交差していた場合HitPointに衝突点が入ります。
 こちらも交差した三角形も取得できます。

プレイヤーから呼び出す

 これらの関数を呼び出しているのはプレイヤーです。Player::OnUpdate()に記述があります。以下抜粋です。
void Player::OnUpdate() {
//中略

    Vec3 StartPos, EndPos;
    GetFightBehavior()->GetSowdStartEndLine(StartPos, EndPos);

    auto EnemyPtr = GetStage()->GetSharedGameObject<EnemyBox>(L"EnemyBox");
    Vec3 HitPoint;
    if (EnemyPtr->IsHitSegmentTriangles(StartPos, EndPos, HitPoint)) {
        //スパークの放出
        auto PtrSpark = GetStage()->GetSharedGameObject<MultiSpark>(L"MultiSpark");
        PtrSpark->InsertSpark(HitPoint);
    }

    auto BonePtr = GetStage()->GetSharedGameObject<BoneChara>(L"BoneChara");
    if (BonePtr->IsHitSegmentTriangles(StartPos, EndPos, HitPoint)) {
        //スパークの放出
        auto PtrSpark = GetStage()->GetSharedGameObject<MultiSpark>(L"MultiSpark");
        PtrSpark->InsertSpark(HitPoint);
    }
}
 ここでEnemyBoxかもしくはBoneCharaのポインタを取得して、IsHitSegmentTriangles()関数を呼び出しています。交差していたら交差点をエミッターにしてエフェクトを出しています。

 今回紹介したサンプルは、非常にシンプルbなものです。実際には、衝突したら、相手に何らかのダメージが付くように記述することでしょう。
 そのあたりの処理は皆さんにお任せします。シンプルですが、結構深いと思いますよ。