Bullet PhysicsのSoftBodyが前から気になっていたので試してみます。ソフトボディーと聞いてまず”ぬいぐるみ”を思い浮かべたので、ぬいぐるみっぽい動きを実現することを目標にします。
まずは、任意形状のポリゴンモデルをSoftBody機能を使って動かすために必要な準備やパラメータ設定を調べ、実験用プログラムを作成します。
Soft Body
物理エンジンでよく使われる剛体とは異なり、衝突など力が加えられると変形する物体のシミュレーションです。使い所の難しい機能ですが、うまく使えばグラフィック表現が格段に上がるはずです。
Bullet Physicsの準備
基本的な操作は剛体と同じです。ソフトボディーを扱うための専用クラスを使用、いくつかの追加処理が必要です。
初期化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//ソフトボディーと剛体の衝突設定 pCollConfig = new btSoftBodyRigidBodyCollisionConfiguration; //Dispatcher&Solver 剛体と同じ pDispatcher = new btCollisionDispatcher(pCollConfig); pSolver = new btSequentialImpulseConstraintSolver; //Broadphase 剛体と同じ btVector3 worldAabbMin(-1000,-1000,-1000); btVector3 worldAabbMax(1000,1000,1000); pBroadphase = new btAxisSweep3(worldAabbMin, worldAabbMax, MAX_PROXIES); //pBroadphase = new btDbvtBroadphase; //いくつか用意されているものを状況に合わせて選択 // ソフトボディー管理情報 // align16 SIMD計算 pSoftBodyWorldInfo = new(_aligned_malloc(sizeof(btSoftBodyWorldInfo),__alignof(btSoftBodyWorldInfo)) ) btSoftBodyWorldInfo; pSoftBodyWorldInfo->m_dispatcher = pDispatcher; pSoftBodyWorldInfo->m_broadphase = pBroadphase; pSoftBodyWorldInfo->m_gravity.setValue(0,-10,0); pSoftBodyWorldInfo->m_sparsesdf.Initialize(); //m_sparsesdfの扱いに注意 // SoftBody&Rigid物理ワールド作成 pDynamicsWorld = new btSoftRigidDynamicsWorld(pDispatcher, pBroadphase, pSolver, pCollConfig, nullptr); pDynamicsWorld->setDebugDrawer(nullptr); pDynamicsWorld->setGravity(btVector3(0,-10,0)); |
削除、終了処理
newで作成し、ポインタをBulletクラスに渡した場合、Bullet側で削除処理は行われない。newしたものは、すべて自分でdeleteする。Bulletクラス内部で作成されたものは一部を除きデストラクタで削除される。したがって、newしたものを管理するクラスなどを作成する必要あり(物理ワールドクラスだけでは難しい)。
メモリリーク
newしたものをすべてdeleteしてもメモリリーク発生。
btSoftBodyWorldInfoのm_sparsesdf(btSparseSdf)というメンバ変数に注意。内部で確保したメモリをデストラクタで解放しない(バグ?仕様?)。
btSparseSdf::Reset()で確保したメモリを解放。忘れずに。
ソフトボディーの作成
頂点や拘束などの設定を登録していくことで作成しますが、作成支援クラス(btSoftBodyHelpers)を使うことで面倒な作成処理をせずにソフトボディーを簡単に作成できます。細かい作成処理は必要になった時に調べることにして、とりあえずやってみる。
任意形状(3角形ポリゴン)のソフトボディー作成
btSoftBodyHelpers::CreateFromTriMesh()
にポリゴン情報を渡すだけ。
パラメータ調整
そのままでは形状が保てずつぶれてしまうため、形を保持するための設定が必要。必要なものだけ紹介。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
btSoftBody::randomizeConstraints() ランダムに選んだ頂点間を拘束、全体の形状を保つ btSoftBody::generateBendingConstraints() 近くにある頂点同士を拘束、表面を固くする効果 btSoftBody::Material.m_kLST generateBendingConstraintsの固さ設定 0~1 btSoftBody::setPose() 初期位置を保とうとする力を発生させる。効果大だが柔軟性がなくなる。 ※btSoftBody::scale()で大きさを変える場合、setPoseの前に実行 btSoftBody.m_cfg.kMT setPoseの効果 0~1 btSoftBody.m_cfg.collisions |= btSoftBody::fCollision::VF_SS; ソフトボディー同士の衝突有効 |
サンプルプログラム
Bullet Soft Body実験用プログラム
簡単なスクリプトで剛体やソフトボディーを追加、パラメータ調整
“Bullet PhysicsのSoftBodyを使ってみる” をダウンロード BulletSoftBody0.zip – 72 回のダウンロード – 66 KB
書いてあるメモリリークの回避方法のおかげで半日悩んだメモリリークから開放されました。ありがとう!
もしこの情報に出会えなければもう半日くらい悩んだかもしれません。