サンプル

特定ボーンのみへのバウンディングボリュームの設定

MascotCapsule エクステンション Collision Package では、モデルデータである SkinnedMesh の特定のボーンを選択して バウンディングボリューム( BV ) を作成・設定することができます。不必要な BV を作成することなく、必要なボーンにのみ BV を設定することで衝突判定の計算コストを抑えることができます。


特定ボーンのみへのバウンディングボリュームの設定

目次





1. 特定ボーンへの BV 設定の手順

SkinnedMesh の特定ボーンへの BV の設定は、

  1. FigureからmcxBVFigureを作成
  2. SkinnedMesh の特定ボーンから BV を作成する
  3. 作成した BV を BVFigure の特定ボーンに設定する

という手順で行ないます。

さらに、BVFigure に SkinnedMesh と同じ変換行列・キーフレームを設定すれば、ここで作成された BV は自動的にボーンの座標変換・アニメーションに合わせて作成元のボーンに追従します。
本サンプルでは、SkinnedMesh のアニメーションに追従する BV について解説します。



2. 特定ボーンへの BV 設定のサンプルコード

ここでは、特定ボーンへの BV の設定を中心にサンプルコードを説明します。

2.1. ボーン構造のみを持つ BVFigure の作成

特定ボーンへの BV の設定にはまず、BV を設定したい SkinnedMesh からボーン構造のみを持つ BVFigure を作成します。この BVFigure の作成には mcx_BVBuilder_createBVFigureOnlyBone 関数を使用します。この関数によって作成される BVFigure はボーン構造のみの BVFigure で、各ボーンに対して BV が設定されていません。またここでは同時に、ワールド座標への変換行列を設定しています。

/**
  * m3dTransform transModel;
  * float matrix [ 16 ] ;
  * hi_bool ret = HI_FALSE;
  */


/* ボーン構造のみを持つ BVFigure の生成 */
pmcx -> pBvfig = IMICRO3Dv4es_mcx_BVBuilder_createBVFigureOnlyBonef(
pMe -> pIM3D, pMe -> pAlc, ( m3dSkinnedMesh * ) pmc -> pModel, &pMe -> e );

/* SkinnedMeshからWorldへの変換行列を得る */
ret = IMICRO3Dv4es_m3dNode_getTransformTo( pMe -> pIM3D,
( m3dNode * ) pmc -> pModel, ( m3dNode * ) pmc -> pWorld, &transModel, &pMe -> e );

IMICRO3Dv4es_m3dTransform_get( pMe -> pIM3D, &transModel, matrix );

/* BVFigure に SkinnedMesh の変換行列を設定 */
IMICRO3Dv4es_mcx_BVFigure_setTransformf( pMe -> pIM3D, pmcx -> pBvfig, matrix, &pMe -> e );

2.2. 特定ボーンに対応する BV の作成と設定

特定ボーンに対して、対象となるボーンの形状に沿った BV を作成するためには、mcx_BVBuilder_createBoneBV 関数を使用します。このとき、対象となるボーンを引数として渡す必要があります。モデルデータの各ボーンは、対象となるモデルを表す SkinnedMesh 配下の Group 、Mesh および、そのサブクラスが表す各ノードに対応しています。そのため、対象となるボーンを表す Node をシーングラフ中から取得する必要があります。
所望の BV が得られたら、それを対象となるボーンに設定します。この設定には mcx_BVFigure_setBVToBone 関数を使用します。このとき、設定対象となるのは BVFigure が保持するボーン構造です。

/**
  * m3dNode* boneNode = NULL;
  * boneTbl は各ノードのユーザ ID から
  * ボーン ID への変換を行なうためのテーブル。
  * GROUP_UID はモデルデータの Skeleton の root を表す
  * Group オブジェクトのユーザ ID を表す。
  * hi_sint32 boneNum は BVFigure が持つボーン総数を表す。
  */


/* 対象 Bone を表す Node を取得 */
for ( nodeID = 0; nodeID < boneNum; nodeID++ ) {
/* 変換テーブルを見て、各 Node が保持する BoneID が対象 Bone のID と一致する Node を取得 */
if ( pmcx -> boneTbl[ nodeID ] == pmcx -> boneID ) {

boneNode = ( m3dNode * )IMICRO3Dv4es_m3dObject3D_find(
pMe -> pIM3D, ( m3dObject3D * ) pmc -> pWorld,
( GROUP_UID + nodeID ) );
break;

}
}

/* 対象 Bone のバウンディングボリュームを取得 */
pmcx -> pBvbone = IMICRO3Dv4es_mcx_BVBuilder_createBoneBV_m3gf(
pMe -> pIM3D, pMe -> pAlc, ( m3dSkinnedMesh * ) pmc -> pModel, boneNode,
MCX_SHAPE_TYPE_SPHERE, 1.f, MCX_BV_ROTATE_NONE, &pMe -> e );

/* 対象 Bone に生成されたバウンディングボリュームを設定 */
IMICRO3Dv4es_mcx_BVFigure_setBVToBonef( pMe -> pIM3D, pmcx -> pBvfig, pmcx -> pBvbone, pmcx -> boneID, &pMe ->e );

また、SkinnedMesh のアニメーションに合わせて BV を動かすため、フレーム時間を更新する際には、BVFigure にもフレーム時間の更新を反映する必要があります。

/* 現在時刻の設定 */
IMICRO3Dv4es_m3dObject3D_animate( pMe -> pIM3D, ( m3dObject3D * ) pmc -> pWorld, pMe -> total_time, &pMe -> e );

/* BVFigure への現在時刻の設定 */
IMICRO3Dv4es_mcx_BVFigure_setPosturef( pMe -> pIM3D, Pmcx -> pBvfig, NULL, 0, pMe -> total_time, &pMe -> e );
特定ボーンのみへのバウンディングボリュームの設定  特定ボーンのみへのバウンディングボリュームの設定


このページの先頭へ戻る