Bullet 2.76 Physics SDK マニュアル
6. 衝突フィルタリング(衝突選択)
Bulletには、どのオブジェクトがどのオブジェクトと衝突するかどうかを決める方法として、マスク、ブロードフェーズフィルターコールバック、ニアコールバックの3つを提供しています。マスクによる衝突選択は、コールバックよりも多くのツールチェインが発生することにを覚えておいてください。つまり、マスクで目的が十分に達成できるのであれば、軽く、単純なマスクを使用してください。
もちろん、マスクだけで無理に行うわけではなく、状況に合わせて最もよい方法を使ってください。そのほうがパフォーマンスもよくなると思います。
マスクを使った衝突フィルタリング
Bulletは、他オブジェクトと衝突させるかどうかを決める方法として、ビット単位のマスクをサポートしています。
int myGroup = 1;
int collideMask = 4;
world->addCollisionObject(object,myGroup,collideMask);
ブロードフェーズ衝突判定では、マスクが一致した(needsBroadphaseCollision内の)オブジェクトグループである場合のみ、ペアキャッシュに登録されます。
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
32bitよりも多くのマスクが必要となったり、その他要因で衝突判定を有効/無効化したい場合は、望んだ対象のみが衝突するような独自のロジックをコールバックに組み込むようにしてください。
ブロードフェーズフィルターコールバック
ブロードフェーズフィルターコールバックは、衝突判定パイプラインのごく初期の段階で呼ばれ、衝突する可能性のあるペアとして生成されるのを防ぐことができます。
struct YourOwnFilterCallback : public btOverlapFilterCallback
{
// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
{
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
//add some additional logic here that modified 'collides'
return collides;
}
};
このクラスをコールバックとして登録するには、インスタンスを生成して以下のように実行します。
btOverlapFilterCallback * filterCallback = new YourOwnFilterCallback();
dynamicsWorld->getPairCache()->setOverlapFilterCallback(filterCallback);
独自のニアコールバックを使った衝突フィルタリング
ブロードフェーズで生成されたすべてのペアを対象としたナローフェーズコールバックを登録することができます。btCollisionDispatcher::dispatchAllCollisionPairsは、btCollisionDispatcher::needsCollisionテストを通過したすべてのペアに対してナローフェーズのニアコールバックを呼び出します。このニアコールバックは以下のようにカスタマイズが可能です。
void MyNearCallback(btBroadphasePair& collisionPair,
btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) {
// Do your collision logic here
// Only dispatch the Bullet collision information if you want the physics to continue
dispatcher.defaultNearCallback(collisionPair, dispatcher, dispatchInfo);
}
mDispatcher->setNearCallback(MyNearCallback);
btCollisionDispatcherから独自クラスを派生させる
より適切な粒度で衝突判定を行いたい場合は、btCollisionDispatcherを派生させて独自のクラスを作成し、以下のメソッドをオーバーライドしてください。
virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1);
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;