計算をマルチスレッドで行うため計算速度が飛躍的に向上します。仕様によりけりですが、一先ず上では連続形式を選択しています。次のm_collisionToleranceは衝突判定の許容誤差(tolerance)を設定します。単位はmと考えておきます。小さ過ぎるとブルブル震えたりと挙動不審になりますが、大き過ぎると衝突判定自体がおかしくなってきます。setBroadPhaseWorldSizeメソッドでは世界の大きさ(立方体の辺の長さ)を決めます。「無限に大きくしておけばいいじゃん」と思うかもしれませんが、それはいけません。これはメモリ効率と精度とパフォーマンスに直結します。世界が小さいほど高精度でハイパフォーマンスで動きます。小さくし過ぎて世界にあるものがはみ出てしまうとエラーになります。これは作るゲームやスケールによるんです。次のsetupSolverInfoメソッドは衝突判定等での計算の繰り返しタイプを以下から設定します:SOLVER_TYPE_2ITERS_SOFTSOLVER_TYPE_2ITERS_MEDIUMSOLVER_TYPE_2ITERS_HARDSOLVER_TYPE_4ITERS_SOFTSOLVER_TYPE_4ITERS_MEDIUMSOLVER_TYPE_4ITERS_HARDSOLVER_TYPE_8ITERS_SOFTSOLVER_TYPE_8ITERS_MEDIUMSOLVER_TYPE_8ITERS_HARD下の方ほど高精度になりますが、当然の事ながらパフォーマンスが激しく落ちていきます。これもゲームが許容する範囲で決めてあげれば良いのかなと思います。次にあるm_gravityは、名前の通り重力の方向(重力加速度)を決めます。0.0f);のように設定します。hkVector4はHavokライブラリが定義する4次ベクトルです(第4引数は省略可能)。他にもい〜〜っぱい設定項目があるのですが、とりあえず以上くらいを設定しておけば世界として成り立ちます。して設定したhkpWorldCinfo構造体をhkpWorldのコンストラクタに渡せば、世界が作られます。);という一行があります。hkpAgentRegisterUtil::registerAllAgentsメソッドは「CollisionDispatcer」という衝突計算の計算方法を管理するクラスをシステムに登録します。これが無いと衝突判定が起こりません。上の一行ではWorldが持っているCollisionDispatcherをシステムに登録しているわけです。床を作ろう�Cで世界が整いました。世界に置く物を作っていきましょう。重力のある世界ではオブジェクトやキャラクタは床が無いとどこまでも落ちていってしまいます。この「床」、実は非常に特別な存在です。床も物ですから重力のある世界に置けば落ちてしまうはずです。地球上の地面は下に落ちません。床にはどのような重たいものが落っこちてきても微動だにしない強さが必要です。ゲームの世界で床を作るには、そういう特殊な性質を付ける必要があるんです。床は、ものすごーくだだっ広くて薄っぺらな箱です。hkpRigidBody(bodyInfo);groundShape->removeReference();world->addEntity(groundBody);groundBody->removeReference();これも上から説明です。衝突の形状を表すオブジェクトは「シェイプ(Shape)」と呼ばれています。上の場合「hkpBoxShape」つまりボックス状の衝突図形を作っています。hkpBoxShapeの第1引数はボックスの縦横高さをhkVector4で指定します。第2引数もあるのですが今は省略で構いません。シェイプはあくまでも衝突形状です。この衝突形状に色々な情報を付加したのが「リジッド(Rigid)」です。そのリジッドの情報を設定するのがhkpRigidBodyCinfoクラスです。massはリジットの質量を設定します。上の床の場合は質量がいらないので0にしています。m_shapeはその名の通りリジットの衝突形状を設定します。m_motionTypeは「慣性テンソル」という物理パラメータの種類を設定します。慣性テンソルというのは...えと、まぁ、Wikipediaを見て下さい。言えば、物の回転しにくさです。野球ボールは手首できゅいきゅい回転させられますが、長ーい棒の真ん中を持って回すと抵抗があります。ここにはhkpMotion::MotionType列挙型で指定されている列挙子を設定します。上のMOTION_FIXEDというのは大変に特殊な慣性テンソルで、何物にも屈しません。どれほど大きくて重たいものが当たってもびくともしない物ができあがります。m_position.setメソッドはリジットの位置を設定します。ついでにですが、m_rotationという回転姿勢を定義するパラメータもあります。これらのリジットパラメータをhkpRigidBodyクラスのコンストラクタに渡すとリジットが作成できます。作成したリジッドはWorldに登録できます!登録するにはhkpWorld::addEntityメソッドにリジッドを渡します。上のソースで床シェイプ(groundShape)や床リジッド(groundBody)のremoveReferenceメソッドが呼ばれています。このメソッドはいわゆる「参照カウンタ」を減らします。これらのオブジェクトがnewされた段階で内部参照カウンタが1つ増加しています。ワールドに登録するともう一つ増加します。作った自分に削除責任が生じているわけです。そこで作った段階でremoveReferenceメソッドを呼んで削除責任を放棄します。すると、リジットやシェイプの寿命はワールドの寿命と一緒になるわけです。これで世界の中にだだっ広い床ができあがりました。body;world->addEntity(body);body->removeReference();i++;}shape->removeReference();}最初のbx,by,bzはキューブのXYZ方向の辺の長さの「半分」です。続くnx,ny,nzはキューブの各軸方向の数です。2*2*2で8つというわけです。bodies配列には作成した8つのキューブリジッドを保持しておきます。床と同じようにhkpRigidBodyCinfo構造体に必要な情報を格納していきます。シェイプはもちろんキューブ(hkpBoxShape)です。今回はXZ軸が2m、Y軸が4mのキューブを作ります。よって第1引数にその大きさを渡します。次のhkpMassPropertiesは質量等の情報をまとめる構造体です。この構造体をhkpInertiaTensorComputer::computeShapeVolumeMassPropertiesメソッドに渡すと、シェイプの形状から慣性テンソルなど各種情報を自動計算してくれます。上のように第1引数にシェイプ、第2引数に質量を渡すと第3引数の構造体に結果が返ります。bodyInfoはこの構造体の結果を使うと楽です。m_massは質量、m_centerOfMassは重心位置、m_inertiaTensorは慣性テンソル行列で、全部massPropertiesに結果があります。重さと重心と慣性テンソルがあると剛体が定義できるわけです。後はm_shapeにシェイプを、m_motionTypeに慣性テンソルタイプを渡せばOK。リジッドはfor文内で作っています。hkpRigidBodyオブジェクトにbodyInfoを渡せば、その情報通りのリジッドができます。hkpRigidBody::setPositionメソッドは、その名の通りリジッドの位置を移動します。今回は積み木のように積んだ状態で高さ100mの位置にオフセットしています。後はワールドにエントリーすれば世界に置かれます。エントリー後、作成したbodyに対して削除責任を放棄しています。shapeを使いまわしていることに注目です。形状が全く同じであればこれで問題ありません。!これで、世界にだだっ広い床と8つのキューブが置かれました。世界の時間を進めよう世界の時間をすすめると、各リジッドは自分自身にかかる力(物理法則)に従って動き出します。時間を動かす方法は幾つかあるのですが、一番簡単なステップ実行をさせてます:world->stepDeltaTime(1.0f/60.0f)この1行で時間が60分の1秒進みます。時間を進めた後、各キューブを描画するにはその位置(姿勢)が必要です。1.0f);hkTransformは内部に4×4の姿勢行列を持っています。この行列は「列メジャー」、つまり列方向主体です。DirectXは行メジャーです。そのため、行列情報を転置する必要があります。姿勢行列の要素を得るメソッドが実はhkTransformクラスにはありません。そのかわり()演算子が定義されています。引数は「行」「列」の順で、その要素の値を得ることができます。姿勢を得ることができれば、後はもうそれをキューブ描画に適用するだけです。後片付けワールド及びHavokのシステムが必要なくなったら、それを解放します。world;hkBaseSystem::quit();hkMemoryInitUtil::quit();worldをdeleteした段階で世界が抱えているオブジェクトがすべて解放されます。システムの後片付けも必要で、上のようにhkBaseSystem::quitメソッド及びhkMemoryInitUtil::quitメソッドを呼び出します。このように、Havokで簡単な図形を世界において物理現象を起こすのは割と簡単です。どちらかというとヘッダーやライブラリなどを組み込むのが長々として面倒かもしれません。この章の動きを再現するサンプルプログラムを作りましたのでお試しください。