From 65885e5069df2a0c2927ece0df84349f1f747dc1 Mon Sep 17 00:00:00 2001 From: enn0x Date: Sat, 12 Nov 2011 23:26:53 +0000 Subject: [PATCH] Added optional (and more powerful) collision filtering algorithm. --- panda/src/bullet/bulletWorld.I | 3 - panda/src/bullet/bulletWorld.cxx | 131 +++++++++++++++++++++++++++-- panda/src/bullet/bulletWorld.h | 30 ++++++- panda/src/bullet/config_bullet.cxx | 5 ++ panda/src/bullet/config_bullet.h | 1 + 5 files changed, 157 insertions(+), 13 deletions(-) diff --git a/panda/src/bullet/bulletWorld.I b/panda/src/bullet/bulletWorld.I index e2d5ca2d5e..89a76039d3 100644 --- a/panda/src/bullet/bulletWorld.I +++ b/panda/src/bullet/bulletWorld.I @@ -47,9 +47,6 @@ INLINE BulletWorld:: _info.m_sparsesdf.Reset(); - delete _ghost_cb; - delete _filter_cb; - delete _world; delete _solver; delete _configuration; diff --git a/panda/src/bullet/bulletWorld.cxx b/panda/src/bullet/bulletWorld.cxx index e9ad292bf6..f64ef0b797 100644 --- a/panda/src/bullet/bulletWorld.cxx +++ b/panda/src/bullet/bulletWorld.cxx @@ -37,9 +37,11 @@ PStatCollector BulletWorld::_pstat_b2p("App:Bullet:DoPhysics:SyncB2P"); BulletWorld:: BulletWorld() { - // Callbacks - _ghost_cb = new btGhostPairCallback(); - _filter_cb = new btFilterCallback(); + // Init groups filter matrix + for (int i=0; i<32; i++) { + _filter_cb2._collide[i].clear(); + _filter_cb2._collide[i].set_bit(i); + } // Broadphase btScalar dx(bullet_sap_extents); @@ -67,10 +69,23 @@ BulletWorld() { // World _world = new btSoftRigidDynamicsWorld(_dispatcher, _broadphase, _solver, _configuration); - _world->getPairCache()->setInternalGhostPairCallback(_ghost_cb); - _world->getPairCache()->setOverlapFilterCallback(_filter_cb); _world->setGravity(btVector3(0.0f, 0.0f, 0.0f)); + // Ghost-pair callback + _world->getPairCache()->setInternalGhostPairCallback(&_ghost_cb); + + // Filter callback + switch (bullet_filter_algorithm) { + case FA_mask: + _world->getPairCache()->setOverlapFilterCallback(&_filter_cb1); + break; + case FA_groups_mask: + _world->getPairCache()->setOverlapFilterCallback(&_filter_cb2); + break; + default: + bullet_cat.error() << "no proper filter algorithm!" << endl; + } + // SoftBodyWorldInfo _info.m_dispatcher = _dispatcher; _info.m_broadphase = _broadphase; @@ -711,11 +726,38 @@ get_collision_object(PandaNode *node) { } //////////////////////////////////////////////////////////////////// -// Function: BulletWorld::FilterCallback::needBroadphaseCollision +// Function: BulletWorld::get_collision_object +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void BulletWorld:: +set_group_collision_flag(unsigned int group1, unsigned int group2, bool enable) { + + if (bullet_filter_algorithm != FA_groups_mask) { + bullet_cat.warning() << "filter algorithm is not 'groups-mask'" << endl; + } + + _filter_cb2._collide[group1].set_bit_to(group2, enable); + _filter_cb2._collide[group2].set_bit_to(group1, enable); +} + +//////////////////////////////////////////////////////////////////// +// Function: BulletWorld::get_collision_object +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +bool BulletWorld:: +get_group_collision_flag(unsigned int group1, unsigned int group2) const { + + return _filter_cb2._collide[group1].get_bit(group2); +} + +//////////////////////////////////////////////////////////////////// +// Function: BulletWorld::FilterCallback1::needBroadphaseCollision // Access: Published // Description: //////////////////////////////////////////////////////////////////// -bool BulletWorld::btFilterCallback:: +bool BulletWorld::btFilterCallback1:: needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const { btCollisionObject *obj0 = (btCollisionObject *) proxy0->m_clientObject; @@ -736,6 +778,39 @@ needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) co return (mask0 & mask1) != 0; } +//////////////////////////////////////////////////////////////////// +// Function: BulletWorld::FilterCallback2::needBroadphaseCollision +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +bool BulletWorld::btFilterCallback2:: +needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const { + + btCollisionObject *obj0 = (btCollisionObject *) proxy0->m_clientObject; + btCollisionObject *obj1 = (btCollisionObject *) proxy1->m_clientObject; + + nassertr(obj0, false); + nassertr(obj1, false); + + PandaNode *node0 = (PandaNode *) obj0->getUserPointer(); + PandaNode *node1 = (PandaNode *) obj1->getUserPointer(); + + nassertr(node0, false); + nassertr(node1, false); + + CollideMask mask0 = node0->get_into_collide_mask(); + CollideMask mask1 = node1->get_into_collide_mask(); + + for (int i=0; i<32; i++) { + if (mask0.get_bit(i)) { + if ((_collide[i] & mask1) != 0) + return true; + } + } + + return false; +} + //////////////////////////////////////////////////////////////////// // Function: BulletWorld::BroadphaseAlgorithm ostream operator // Description: @@ -778,3 +853,45 @@ operator >> (istream &in, BulletWorld::BroadphaseAlgorithm &algorithm) { return in; } +//////////////////////////////////////////////////////////////////// +// Function: BulletWorld::FilterAlgorithm ostream operator +// Description: +//////////////////////////////////////////////////////////////////// +ostream & +operator << (ostream &out, BulletWorld::FilterAlgorithm algorithm) { + + switch (algorithm) { + case BulletWorld::FA_mask: + return out << "mask"; + + case BulletWorld::FA_groups_mask: + return out << "groups-mask"; + }; + + return out << "**invalid BulletWorld::FilterAlgorithm(" << (int)algorithm << ")**"; +} + +//////////////////////////////////////////////////////////////////// +// Function: BulletWorld::FilterAlgorithm istream operator +// Description: +//////////////////////////////////////////////////////////////////// +istream & +operator >> (istream &in, BulletWorld::FilterAlgorithm &algorithm) { + string word; + in >> word; + + if (word == "mask") { + algorithm = BulletWorld::FA_mask; + } + else if (word == "groups-mask") { + algorithm = BulletWorld::FA_groups_mask; + } + else { + bullet_cat.error() + << "Invalid BulletWorld::FilterAlgorithm: " << word << "\n"; + algorithm = BulletWorld::FA_mask; + } + + return in; +} + diff --git a/panda/src/bullet/bulletWorld.h b/panda/src/bullet/bulletWorld.h index d23caa6900..8ed8671c65 100644 --- a/panda/src/bullet/bulletWorld.h +++ b/panda/src/bullet/bulletWorld.h @@ -137,12 +137,21 @@ PUBLISHED: BulletPersistentManifold *get_manifold(int idx) const; MAKE_SEQ(get_manifolds, get_num_manifolds, get_manifold); + // Collision filtering + void set_group_collision_flag(unsigned int group1, unsigned int group2, bool enable); + bool get_group_collision_flag(unsigned int group1, unsigned int group2) const; + // Configuration enum BroadphaseAlgorithm { BA_sweep_and_prune, BA_dynamic_aabb_tree, }; + enum FilterAlgorithm { + FA_mask, + FA_groups_mask, + }; + public: static btCollisionObject *get_collision_object(PandaNode *node); @@ -167,20 +176,30 @@ private: static PStatCollector _pstat_p2b; static PStatCollector _pstat_b2p; - struct btFilterCallback : public btOverlapFilterCallback { + struct btFilterCallback1 : public btOverlapFilterCallback { virtual bool needBroadphaseCollision( btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const; }; + struct btFilterCallback2 : public btOverlapFilterCallback { + virtual bool needBroadphaseCollision( + btBroadphaseProxy* proxy0, + btBroadphaseProxy* proxy1) const; + + CollideMask _collide[32]; + }; + btBroadphaseInterface *_broadphase; btCollisionConfiguration *_configuration; btCollisionDispatcher *_dispatcher; btConstraintSolver *_solver; btSoftRigidDynamicsWorld *_world; - btGhostPairCallback *_ghost_cb; - btFilterCallback *_filter_cb; + btGhostPairCallback _ghost_cb; + + btFilterCallback1 _filter_cb1; + btFilterCallback2 _filter_cb2; btSoftBodyWorldInfo _info; @@ -220,6 +239,11 @@ operator << (ostream &out, BulletWorld::BroadphaseAlgorithm algorithm); EXPCL_PANDABULLET istream & operator >> (istream &in, BulletWorld::BroadphaseAlgorithm &algorithm); +EXPCL_PANDABULLET ostream & +operator << (ostream &out, BulletWorld::FilterAlgorithm algorithm); +EXPCL_PANDABULLET istream & +operator >> (istream &in, BulletWorld::FilterAlgorithm &algorithm); + #include "bulletWorld.I" #endif // __BULLET_WORLD_H__ diff --git a/panda/src/bullet/config_bullet.cxx b/panda/src/bullet/config_bullet.cxx index 45edad4369..b2e8448dfb 100644 --- a/panda/src/bullet/config_bullet.cxx +++ b/panda/src/bullet/config_bullet.cxx @@ -73,6 +73,11 @@ ConfigVariableEnum bullet_broadphase_algorithm PRC_DESC("Specifies the broadphase algorithm to be used by the physics " "engine. Default value is 'aabb' (dynamic aabb tree).")); +ConfigVariableEnum bullet_filter_algorithm +("bullet-filter-algorithm", BulletWorld::FA_mask, +PRC_DESC("Specifies the algorithm to be used by the physics engine for " + "collision filtering. Default value is 'mask'.")); + ConfigVariableDouble bullet_sap_extents ("bullet-sap-extents", 1000.0, PRC_DESC("Specifies the world extent in all directions. The config variable " diff --git a/panda/src/bullet/config_bullet.h b/panda/src/bullet/config_bullet.h index a99640a1e4..b9c9ea4ac1 100644 --- a/panda/src/bullet/config_bullet.h +++ b/panda/src/bullet/config_bullet.h @@ -31,6 +31,7 @@ NotifyCategoryDecl(bullet, EXPCL_PANDABULLET, EXPTP_PANDABULLET); extern ConfigVariableInt bullet_max_objects; extern ConfigVariableInt bullet_gc_lifetime; extern ConfigVariableEnum bullet_broadphase_algorithm; +extern ConfigVariableEnum bullet_filter_algorithm; extern ConfigVariableDouble bullet_sap_extents; extern ConfigVariableBool bullet_enable_contact_events; extern ConfigVariableInt bullet_solver_iterations;