Browse Source

Added optional (and more powerful) collision filtering algorithm.

enn0x 14 years ago
parent
commit
65885e5069

+ 0 - 3
panda/src/bullet/bulletWorld.I

@@ -47,9 +47,6 @@ INLINE BulletWorld::
 
 
   _info.m_sparsesdf.Reset();
   _info.m_sparsesdf.Reset();
 
 
-  delete _ghost_cb;
-  delete _filter_cb;
-
   delete _world;
   delete _world;
   delete _solver;
   delete _solver;
   delete _configuration;
   delete _configuration;

+ 124 - 7
panda/src/bullet/bulletWorld.cxx

@@ -37,9 +37,11 @@ PStatCollector BulletWorld::_pstat_b2p("App:Bullet:DoPhysics:SyncB2P");
 BulletWorld::
 BulletWorld::
 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
   // Broadphase
   btScalar dx(bullet_sap_extents);
   btScalar dx(bullet_sap_extents);
@@ -67,10 +69,23 @@ BulletWorld() {
 
 
   // World
   // World
   _world = new btSoftRigidDynamicsWorld(_dispatcher, _broadphase, _solver, _configuration);
   _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));
   _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
   // SoftBodyWorldInfo
   _info.m_dispatcher = _dispatcher;
   _info.m_dispatcher = _dispatcher;
   _info.m_broadphase = _broadphase;
   _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
 //       Access: Published
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-bool BulletWorld::btFilterCallback::
+bool BulletWorld::btFilterCallback1::
 needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const {
 needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const {
 
 
   btCollisionObject *obj0 = (btCollisionObject *) proxy0->m_clientObject;
   btCollisionObject *obj0 = (btCollisionObject *) proxy0->m_clientObject;
@@ -736,6 +778,39 @@ needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) co
   return (mask0 & mask1) != 0;
   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
 //     Function: BulletWorld::BroadphaseAlgorithm ostream operator
 //  Description:
 //  Description:
@@ -778,3 +853,45 @@ operator >> (istream &in, BulletWorld::BroadphaseAlgorithm &algorithm) {
   return in;
   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;
+}
+

+ 27 - 3
panda/src/bullet/bulletWorld.h

@@ -137,12 +137,21 @@ PUBLISHED:
   BulletPersistentManifold *get_manifold(int idx) const;
   BulletPersistentManifold *get_manifold(int idx) const;
   MAKE_SEQ(get_manifolds, get_num_manifolds, get_manifold);
   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
   // Configuration
   enum BroadphaseAlgorithm {
   enum BroadphaseAlgorithm {
     BA_sweep_and_prune,
     BA_sweep_and_prune,
     BA_dynamic_aabb_tree,
     BA_dynamic_aabb_tree,
   };
   };
 
 
+  enum FilterAlgorithm {
+    FA_mask,
+    FA_groups_mask,
+  };
+
 public:
 public:
   static btCollisionObject *get_collision_object(PandaNode *node);
   static btCollisionObject *get_collision_object(PandaNode *node);
 
 
@@ -167,20 +176,30 @@ private:
   static PStatCollector _pstat_p2b;
   static PStatCollector _pstat_p2b;
   static PStatCollector _pstat_b2p;
   static PStatCollector _pstat_b2p;
 
 
-  struct btFilterCallback : public btOverlapFilterCallback {
+  struct btFilterCallback1 : public btOverlapFilterCallback {
     virtual bool needBroadphaseCollision(
     virtual bool needBroadphaseCollision(
       btBroadphaseProxy* proxy0,
       btBroadphaseProxy* proxy0,
       btBroadphaseProxy* proxy1) const;
       btBroadphaseProxy* proxy1) const;
   };
   };
 
 
+  struct btFilterCallback2 : public btOverlapFilterCallback {
+    virtual bool needBroadphaseCollision(
+      btBroadphaseProxy* proxy0,
+      btBroadphaseProxy* proxy1) const;
+
+    CollideMask _collide[32];
+  };
+
   btBroadphaseInterface *_broadphase;
   btBroadphaseInterface *_broadphase;
   btCollisionConfiguration *_configuration;
   btCollisionConfiguration *_configuration;
   btCollisionDispatcher *_dispatcher;
   btCollisionDispatcher *_dispatcher;
   btConstraintSolver *_solver;
   btConstraintSolver *_solver;
   btSoftRigidDynamicsWorld *_world;
   btSoftRigidDynamicsWorld *_world;
 
 
-  btGhostPairCallback *_ghost_cb;
-  btFilterCallback *_filter_cb;
+  btGhostPairCallback _ghost_cb;
+
+  btFilterCallback1 _filter_cb1;
+  btFilterCallback2 _filter_cb2;
 
 
   btSoftBodyWorldInfo _info;
   btSoftBodyWorldInfo _info;
 
 
@@ -220,6 +239,11 @@ operator << (ostream &out, BulletWorld::BroadphaseAlgorithm algorithm);
 EXPCL_PANDABULLET istream &
 EXPCL_PANDABULLET istream &
 operator >> (istream &in, BulletWorld::BroadphaseAlgorithm &algorithm);
 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"
 #include "bulletWorld.I"
 
 
 #endif // __BULLET_WORLD_H__
 #endif // __BULLET_WORLD_H__

+ 5 - 0
panda/src/bullet/config_bullet.cxx

@@ -73,6 +73,11 @@ ConfigVariableEnum<BulletWorld::BroadphaseAlgorithm> bullet_broadphase_algorithm
 PRC_DESC("Specifies the broadphase algorithm to be used by the physics "
 PRC_DESC("Specifies the broadphase algorithm to be used by the physics "
          "engine. Default value is 'aabb' (dynamic aabb tree)."));
          "engine. Default value is 'aabb' (dynamic aabb tree)."));
 
 
+ConfigVariableEnum<BulletWorld::FilterAlgorithm> 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
 ConfigVariableDouble bullet_sap_extents
 ("bullet-sap-extents", 1000.0,
 ("bullet-sap-extents", 1000.0,
 PRC_DESC("Specifies the world extent in all directions. The config variable "
 PRC_DESC("Specifies the world extent in all directions. The config variable "

+ 1 - 0
panda/src/bullet/config_bullet.h

@@ -31,6 +31,7 @@ NotifyCategoryDecl(bullet, EXPCL_PANDABULLET, EXPTP_PANDABULLET);
 extern ConfigVariableInt bullet_max_objects;
 extern ConfigVariableInt bullet_max_objects;
 extern ConfigVariableInt bullet_gc_lifetime;
 extern ConfigVariableInt bullet_gc_lifetime;
 extern ConfigVariableEnum<BulletWorld::BroadphaseAlgorithm> bullet_broadphase_algorithm;
 extern ConfigVariableEnum<BulletWorld::BroadphaseAlgorithm> bullet_broadphase_algorithm;
+extern ConfigVariableEnum<BulletWorld::FilterAlgorithm> bullet_filter_algorithm;
 extern ConfigVariableDouble bullet_sap_extents;
 extern ConfigVariableDouble bullet_sap_extents;
 extern ConfigVariableBool bullet_enable_contact_events;
 extern ConfigVariableBool bullet_enable_contact_events;
 extern ConfigVariableInt bullet_solver_iterations;
 extern ConfigVariableInt bullet_solver_iterations;