衝突判定形状は次の手順で作成・登録します.
1. 形状を作成する
2. 剛体へ形状を追加する
3. 形状の位置を設定する
以下に順を追って説明します.
まず形状を作成するには次のようにします.
// given PHSdkIf* phSdk CDBoxDesc desc; desc.boxsize = Vec3d(1.0, 1.0, 1.0); CDBoxIf* box = phSdk->CreateShape(desc)->Cast();
衝突判定形状のオブジェクトはPhysicsモジュールが管理します. このため,形状を作成するにはPHSdkクラスのCreateShape関数を使います. PHSdkについては7章を参照してください. 形状を作成するには,まず種類に応じたディスクリプタを作成し,寸法などのパラメータを設定します. この例では直方体クラスCDBoxのディスクリプタを作
成して一辺がの立方体を作成します. ディスクリプタを指定してCreateShapeを呼び出すと,対応す
る種類の形状が作成され, そのインタフェースが返されます. ただし戻り値は形状の基底クラスであるCDShapeのインタフェースですので,派生クラス(ここではCDBox)のインタフェースを得るには 上
のようにCast関数で動的キャストする必要があります.
形状を作成したら,次にその形状を与えたい剛体に登録します.
// given PHSolidIf* solid solid->AddShape(box); // first box
剛体クラスPHSolidについては7章を参照してください. ここで重要なことは,一度作成した形状は1つの剛体にいくつでも登録でき,また異なる複数の剛体にも登録できるという ことです. つまり,同じ形状を複数の剛体間で共有することで,形状の作成コストやメモリ消費を抑えることができます.
AddShape関数で登録した直後の形状は,剛体のローカル座標系の原点に位置しています. これを変更したい場合はSetShapePose関数を使います.
solid->AddShape(box); // second box solid->AddShape(box); // third box // move first shape 1.0 in x-direction solid->SetShapePose(0, Posed(Vec3d(1.0, 0.0, 0.0), Quaterniond()); // rotate second shape 30 degrees along y-axis solid->SetShapePose(1, Posed(Vec3d(), Quaterniond::Rot(Rad(30.0), ’y’)));
SetShapePoseの第1引数は操作する形状の番号です.最初にAddShapeした形状の番号がで,AddShapeするたびに
増加します. 形状の位置や向きは剛体のローカル座標系で指定します. また,形状の位置・向きを取得するにはGetShapePose関数を使います.
以下ではSpringheadでサポートされている形状を種類別に解説します.
Fig. 6.2: Box geometry
直方体(Fig. 6.2)のクラスはCDBoxです.
CDBoxDesc | ||
Vec3f | boxsize | 各辺の長さ |
CDBoxIf | ||
Vec3f GetBoxSize() | ||
void SetBoxSize(Vec3f) | ||
Fig. 6.3: Sphere geometry
球(Fig. 6.3)のクラスはCDSphereです.
CDSphereDesc | ||
float | radius | 半径 |
CDSphereIf | ||
float GetRadius() | ||
void SetRadius(float) | ||
Fig. 6.4: Capsule geometry
カプセル(Fig. 6.4)のクラスはCDCapsuleです. カプセルは円柱の両端に半球がついた形をしています.
CDCapsuleDesc | ||
float | radius | 半球の半径 |
float | length | 円柱の長さ |
CDCapsuleIf | ||
float GetRadius() | ||
void SetRadius(float) | ||
float GetLength() | ||
void SetLength(float) | ||
Fig. 6.5: Round cone geometry
丸コーン(Fig. 6.5)のクラスはCDRoundConeです. 丸コーンはカプセルの両端の半径が非対称になったものです.
CDRoundConeDesc | ||
Vec2f | radius | 各半球の半径 |
float | length | 半球間の距離 |
CDRoundConeIf | ||
Vec2f GetRadius() | ||
void SetRadius(Vec2f) | ||
float GetLength() | ||
void SetLength(float) | ||
void SetWidth(Vec2f) | ||
SetWidth関数は,丸コーンの全長を保存したまま半径を変更します.
Fig. 6.6: Convex mesh geometry
凸メッシュ(Fig. 6.6)のクラスはCDConvexMeshです. 凸メッシュとは凹みや穴を持たない多面体です. 頂点座標を指定することで自由な形を作成することができます.
CDConvexMeshDesc | ||
vector<Vec3f> | vertices | 頂点座標の配列 |
CDConvexMeshIf | ||
Vec3f* GetVertices() | 頂点配列の先頭アドレス | |
int NVertex() | 頂点数 | |
CDFaceIf* GetFace(int i) | ||
int NFace() | 面数 | |
凸メッシュが作成される際,CDConvexMeshDesc::verticesに格納された頂点を内包する最小の凸多面体(凸包)が作成されます. 多面体の面を表すCDFaceのインタフェースを以下に示します.
CDFaceIf | ||
int* GetIndices() | 頂点インデックス配列の先頭アドレス | |
int NIndex() | 面の頂点数 | |
NIndexは面を構成する頂点の数を返します(通常か
です)
るには
// given CDConvexMeshIf* mesh CDFaceIf* face = mesh->GetFace(0); // get 0-th face int* idx = face->GetIndices(); Vec3f v = mesh->GetVertices()[idx[0]]; // get 0-th vertex
とします.