Ver Fonte

allow more than 32 colliders in one traverser

David Rose há 20 anos atrás
pai
commit
041058a594

+ 42 - 2
panda/src/collide/collisionLevelState.I

@@ -43,6 +43,46 @@ CollisionLevelState(const CollisionLevelState &parent, PandaNode *child) :
 {
 {
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionLevelState::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CollisionLevelState::
+CollisionLevelState(const CollisionLevelState &copy) :
+  _node_path(copy._node_path),
+  _colliders(copy._colliders),
+  _current(copy._current),
+  _local_bounds(copy._local_bounds),
+  _parent_bounds(copy._parent_bounds)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionLevelState::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionLevelState::
+operator = (const CollisionLevelState &copy) {
+  _node_path = copy._node_path;
+  _colliders = copy._colliders;
+  _current = copy._current;
+  _local_bounds = copy._local_bounds;
+  _parent_bounds = copy._parent_bounds;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionLevelState::get_max_colliders
+//       Access: Public, Static
+//  Description: Returns the maximum number of colliders that may be
+//               added to the CollisionLevelState at any one time.
+////////////////////////////////////////////////////////////////////
+INLINE int CollisionLevelState::
+get_max_colliders() {
+  return sizeof(CurrentMask) * 8;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionLevelState::get_node_path
 //     Function: CollisionLevelState::get_node_path
 //       Access: Public
 //       Access: Public
@@ -197,7 +237,7 @@ omit_collider(int n) {
 //  Description: Returns a single bit associated with the nth
 //  Description: Returns a single bit associated with the nth
 //               collider.
 //               collider.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE CollisionLevelState::ColliderMask CollisionLevelState::
+INLINE CollisionLevelState::CurrentMask CollisionLevelState::
 get_mask(int n) const {
 get_mask(int n) const {
-  return ((ColliderMask)1) << n;
+  return ((CurrentMask)1) << n;
 }
 }

+ 11 - 6
panda/src/collide/collisionLevelState.cxx

@@ -36,12 +36,14 @@ clear() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionLevelState::reserve
 //     Function: CollisionLevelState::reserve
 //       Access: Public
 //       Access: Public
-//  Description:
+//  Description: Indicates an intention to add the indicated number of
+//               colliders to the level state.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CollisionLevelState::
 void CollisionLevelState::
-reserve(int max_colliders) {
-  _colliders.reserve(max_colliders);
-  _local_bounds.reserve(max_colliders);
+reserve(int num_colliders) {
+  nassertv(num_colliders <= get_max_colliders());
+  _colliders.reserve(num_colliders);
+  _local_bounds.reserve(num_colliders);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -53,6 +55,7 @@ reserve(int max_colliders) {
 void CollisionLevelState::
 void CollisionLevelState::
 prepare_collider(const ColliderDef &def) {
 prepare_collider(const ColliderDef &def) {
   int index = (int)_colliders.size();
   int index = (int)_colliders.size();
+  nassertv(index < get_max_colliders());
   _colliders.push_back(def);
   _colliders.push_back(def);
 
 
   CollisionSolid *collider = def._collider;
   CollisionSolid *collider = def._collider;
@@ -85,10 +88,12 @@ prepare_collider(const ColliderDef &def) {
     gbv->xform(def._node_path.get_net_transform()->get_mat());
     gbv->xform(def._node_path.get_net_transform()->get_mat());
     _local_bounds.push_back(gbv);
     _local_bounds.push_back(gbv);
   }
   }
-
-  _current |= get_mask(index);
+  
+  CurrentMask mask = get_mask(index); 
+  _current |= mask;
 
 
   _parent_bounds = _local_bounds;
   _parent_bounds = _local_bounds;
+  nassertv(mask != 0);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 10 - 6
panda/src/collide/collisionLevelState.h

@@ -49,12 +49,16 @@ public:
 
 
   INLINE CollisionLevelState(const NodePath &node_path);
   INLINE CollisionLevelState(const NodePath &node_path);
   INLINE CollisionLevelState(const CollisionLevelState &parent, 
   INLINE CollisionLevelState(const CollisionLevelState &parent, 
-                               PandaNode *child);
+                             PandaNode *child);
+  INLINE CollisionLevelState(const CollisionLevelState &copy);
+  INLINE void operator = (const CollisionLevelState &copy);
 
 
   void clear();
   void clear();
-  void reserve(int max_colliders);
+  void reserve(int num_colliders);
   void prepare_collider(const ColliderDef &def);
   void prepare_collider(const ColliderDef &def);
 
 
+  INLINE static int get_max_colliders();
+
   bool any_in_bounds();
   bool any_in_bounds();
   void apply_transform();
   void apply_transform();
   
   
@@ -74,20 +78,20 @@ public:
   INLINE void omit_collider(int n);
   INLINE void omit_collider(int n);
 
 
 private:
 private:
-  // ColliderMask here is a locally-defined value that simply serves
+  // CurrentMask here is a locally-defined value that simply serves
   // to keep track of the colliders that are still interested in the
   // to keep track of the colliders that are still interested in the
   // current node.  Don't confuse it with CollideMask, which is a set
   // current node.  Don't confuse it with CollideMask, which is a set
   // of user-defined bits that specify which CollisionSolids may
   // of user-defined bits that specify which CollisionSolids may
   // possibly intersect with each other.
   // possibly intersect with each other.
-  typedef int ColliderMask;
+  typedef unsigned int CurrentMask;
 
 
-  INLINE ColliderMask get_mask(int n) const;
+  INLINE CurrentMask get_mask(int n) const;
 
 
   WorkingNodePath _node_path;
   WorkingNodePath _node_path;
 
 
   typedef PTA(ColliderDef) Colliders;
   typedef PTA(ColliderDef) Colliders;
   Colliders _colliders;
   Colliders _colliders;
-  ColliderMask _current;
+  CurrentMask _current;
 
 
   typedef PTA(CPT(GeometricBoundingVolume)) BoundingVolumes;
   typedef PTA(CPT(GeometricBoundingVolume)) BoundingVolumes;
   BoundingVolumes _local_bounds;
   BoundingVolumes _local_bounds;

+ 61 - 18
panda/src/collide/collisionTraverser.cxx

@@ -107,7 +107,7 @@ add_collider(const NodePath &collider, CollisionHandler *handler) {
       if (hi == _handlers.end()) {
       if (hi == _handlers.end()) {
         _handlers.insert(Handlers::value_type(handler, 1));
         _handlers.insert(Handlers::value_type(handler, 1));
       } else {
       } else {
-        (*hi).second++;
+        ++(*hi).second;
       }
       }
     }
     }
 
 
@@ -123,7 +123,7 @@ add_collider(const NodePath &collider, CollisionHandler *handler) {
     if (hi == _handlers.end()) {
     if (hi == _handlers.end()) {
       _handlers.insert(Handlers::value_type(handler, 1));
       _handlers.insert(Handlers::value_type(handler, 1));
     } else {
     } else {
-      (*hi).second++;
+      ++(*hi).second;
     }
     }
   }
   }
 
 
@@ -226,7 +226,7 @@ get_handler(const NodePath &collider) const {
   Colliders::const_iterator ci = _colliders.find(collider);
   Colliders::const_iterator ci = _colliders.find(collider);
   if (ci != _colliders.end()) {
   if (ci != _colliders.end()) {
     return (*ci).second;
     return (*ci).second;
-  };
+  }
   return NULL;
   return NULL;
 }
 }
 
 
@@ -279,15 +279,22 @@ traverse(const NodePath &root) {
   }
   }
 #endif  // DO_COLLISION_RECORDING
 #endif  // DO_COLLISION_RECORDING
 
 
-  CollisionLevelState level_state(root);
-  prepare_colliders(level_state, root);
-
+  LevelStates level_states;
+  prepare_colliders(level_states, root);
+  
   Handlers::iterator hi;
   Handlers::iterator hi;
   for (hi = _handlers.begin(); hi != _handlers.end(); ++hi) {
   for (hi = _handlers.begin(); hi != _handlers.end(); ++hi) {
     (*hi).first->begin_group();
     (*hi).first->begin_group();
   }
   }
 
 
-  r_traverse(level_state);
+  // Make a number of passes, one for each group of 32 Colliders (or
+  // whatever number of bits we have available in CurrentMask).
+  for (size_t pass = 0; pass < level_states.size(); ++pass) {
+#ifdef DO_PSTATS
+    PStatTimer pass_timer(get_pass_collector(pass));
+#endif
+    r_traverse(level_states[pass]);
+  }
 
 
   hi = _handlers.begin();
   hi = _handlers.begin();
   while (hi != _handlers.end()) {
   while (hi != _handlers.end()) {
@@ -450,7 +457,7 @@ write(ostream &out, int indent_level) const {
       CollisionNode *cnode = DCAST(CollisionNode, cnode_path.node());
       CollisionNode *cnode = DCAST(CollisionNode, cnode_path.node());
       
       
       int num_solids = cnode->get_num_solids();
       int num_solids = cnode->get_num_solids();
-      for (int i = 0; i < num_solids; i++) {
+      for (int i = 0; i < num_solids; ++i) {
         cnode->get_solid(i)->write(out, indent_level + 4);
         cnode->get_solid(i)->write(out, indent_level + 4);
       }
       }
     }
     }
@@ -464,9 +471,13 @@ write(ostream &out, int indent_level) const {
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void CollisionTraverser::
 void CollisionTraverser::
-prepare_colliders(CollisionLevelState &level_state, const NodePath &root) {
-  level_state.clear();
-  level_state.reserve(_colliders.size());
+prepare_colliders(CollisionTraverser::LevelStates &level_states, 
+                  const NodePath &root) {
+  int num_colliders = _colliders.size();
+  int max_colliders = CollisionLevelState::get_max_colliders();
+
+  CollisionLevelState level_state(root);
+  level_state.reserve(min(num_colliders, max_colliders));
 
 
   OrderedColliders::iterator oci;
   OrderedColliders::iterator oci;
   for (oci = _ordered_colliders.begin(); 
   for (oci = _ordered_colliders.begin(); 
@@ -492,13 +503,26 @@ prepare_colliders(CollisionLevelState &level_state, const NodePath &root) {
       def._node_path = cnode_path;
       def._node_path = cnode_path;
       
       
       int num_solids = cnode->get_num_solids();
       int num_solids = cnode->get_num_solids();
-      for (int s = 0; s < num_solids; s++) {
+      for (int s = 0; s < num_solids; ++s) {
         CollisionSolid *collider = cnode->get_solid(s);
         CollisionSolid *collider = cnode->get_solid(s);
         def._collider = collider;
         def._collider = collider;
         level_state.prepare_collider(def);
         level_state.prepare_collider(def);
+        --num_colliders;
+
+        if (level_state.get_num_colliders() == max_colliders) {
+          // That's the limit.  Save off this level state and make a
+          // new one.
+          level_states.push_back(level_state);
+          level_state.reserve(min(num_colliders, max_colliders));
+          level_state.clear();
+        }
       }
       }
     }
     }
   }
   }
+
+  if (level_state.get_num_colliders() != 0) {
+    level_states.push_back(level_state);
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -531,7 +555,7 @@ r_traverse(CollisionLevelState &level_state) {
     }
     }
 
 
     int num_colliders = level_state.get_num_colliders();
     int num_colliders = level_state.get_num_colliders();
-    for (int c = 0; c < num_colliders; c++) {
+    for (int c = 0; c < num_colliders; ++c) {
       if (level_state.has_collider(c)) {
       if (level_state.has_collider(c)) {
         entry._from_node = level_state.get_collider_node(c);
         entry._from_node = level_state.get_collider_node(c);
 
 
@@ -572,7 +596,7 @@ r_traverse(CollisionLevelState &level_state) {
     }
     }
 
 
     int num_colliders = level_state.get_num_colliders();
     int num_colliders = level_state.get_num_colliders();
-    for (int c = 0; c < num_colliders; c++) {
+    for (int c = 0; c < num_colliders; ++c) {
       if (level_state.has_collider(c)) {
       if (level_state.has_collider(c)) {
         entry._from_node = level_state.get_collider_node(c);
         entry._from_node = level_state.get_collider_node(c);
 
 
@@ -610,7 +634,7 @@ r_traverse(CollisionLevelState &level_state) {
   } else {
   } else {
     // Otherwise, visit all the children.
     // Otherwise, visit all the children.
     int num_children = node->get_num_children();
     int num_children = node->get_num_children();
-    for (int i = 0; i < num_children; i++) {
+    for (int i = 0; i < num_children; ++i) {
       CollisionLevelState next_state(level_state, node->get_child(i));
       CollisionLevelState next_state(level_state, node->get_child(i));
       r_traverse(next_state);
       r_traverse(next_state);
     }
     }
@@ -637,7 +661,7 @@ compare_collider_to_node(CollisionEntry &entry,
     CollisionNode *cnode;
     CollisionNode *cnode;
     DCAST_INTO_V(cnode, entry._into_node);
     DCAST_INTO_V(cnode, entry._into_node);
     int num_solids = cnode->get_num_solids();
     int num_solids = cnode->get_num_solids();
-    for (int s = 0; s < num_solids; s++) {
+    for (int s = 0; s < num_solids; ++s) {
       entry._into = cnode->get_solid(s);
       entry._into = cnode->get_solid(s);
       if (entry._from != entry._into) {
       if (entry._from != entry._into) {
         const BoundingVolume &solid_bv = entry._into->get_bound();
         const BoundingVolume &solid_bv = entry._into->get_bound();
@@ -678,7 +702,7 @@ compare_collider_to_geom_node(CollisionEntry &entry,
     GeomNode *gnode;
     GeomNode *gnode;
     DCAST_INTO_V(gnode, entry._into_node);
     DCAST_INTO_V(gnode, entry._into_node);
     int num_geoms = gnode->get_num_geoms();
     int num_geoms = gnode->get_num_geoms();
-    for (int s = 0; s < num_geoms; s++) {
+    for (int s = 0; s < num_geoms; ++s) {
       entry._into = (CollisionSolid *)NULL;
       entry._into = (CollisionSolid *)NULL;
       const Geom *geom = DCAST(Geom, gnode->get_geom(s));
       const Geom *geom = DCAST(Geom, gnode->get_geom(s));
       if (geom != (Geom *)NULL) {
       if (geom != (Geom *)NULL) {
@@ -862,7 +886,26 @@ r_reset_prev_transform(PandaNode *node) {
 
 
   PandaNode::Children children = node->get_children();
   PandaNode::Children children = node->get_children();
   int num_children = children.get_num_children();
   int num_children = children.get_num_children();
-  for (int i = 0; i < num_children; i++) {
+  for (int i = 0; i < num_children; ++i) {
     r_reset_prev_transform(children.get_child(i));
     r_reset_prev_transform(children.get_child(i));
   }
   }
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionTraverser::get_pass_collector
+//       Access: Private
+//  Description: Returns the PStatCollector suitable for timing the
+//               nth pass.
+////////////////////////////////////////////////////////////////////
+PStatCollector &CollisionTraverser::
+get_pass_collector(int pass) {
+  nassertr(pass >= 0, _this_pcollector);
+  while ((int)_pass_collectors.size() <= pass) {
+    ostringstream name;
+    name << "pass " << (_pass_collectors.size() + 1);
+    PStatCollector col(_this_pcollector, name.str());
+    _pass_collectors.push_back(col);
+  }
+
+  return _pass_collectors[pass];
+}

+ 6 - 1
panda/src/collide/collisionTraverser.h

@@ -87,7 +87,8 @@ PUBLISHED:
   void write(ostream &out, int indent_level) const;
   void write(ostream &out, int indent_level) const;
 
 
 private:
 private:
-  void prepare_colliders(CollisionLevelState &state, const NodePath &root);
+  typedef pvector<CollisionLevelState> LevelStates;
+  void prepare_colliders(LevelStates &level_states, const NodePath &root);
 
 
   void r_traverse(CollisionLevelState &level_state);
   void r_traverse(CollisionLevelState &level_state);
 
 
@@ -108,6 +109,8 @@ private:
 
 
   void r_reset_prev_transform(PandaNode *node);
   void r_reset_prev_transform(PandaNode *node);
 
 
+  PStatCollector &get_pass_collector(int pass);
+
 private:
 private:
   PT(CollisionHandler) _default_handler;
   PT(CollisionHandler) _default_handler;
   TypeHandle _graph_type;
   TypeHandle _graph_type;
@@ -138,6 +141,8 @@ private:
   static PStatCollector _collisions_pcollector;
   static PStatCollector _collisions_pcollector;
   static PStatCollector _reset_prev_pcollector;
   static PStatCollector _reset_prev_pcollector;
   PStatCollector _this_pcollector;
   PStatCollector _this_pcollector;
+  typedef pvector<PStatCollector> PassCollectors;
+  PassCollectors _pass_collectors;
 };
 };
 
 
 INLINE ostream &operator << (ostream &out, const CollisionTraverser &trav) {
 INLINE ostream &operator << (ostream &out, const CollisionTraverser &trav) {

+ 1 - 1
panda/src/display/graphicsStateGuardian.h

@@ -221,7 +221,7 @@ protected:
   virtual void enable_clip_planes(bool enable);
   virtual void enable_clip_planes(bool enable);
   virtual void enable_clip_plane(int plane_id, bool enable);
   virtual void enable_clip_plane(int plane_id, bool enable);
   virtual void begin_bind_clip_planes();
   virtual void begin_bind_clip_planes();
-  virtual void bind_clip_plane(const NodePath &plane, int pane_id);
+  virtual void bind_clip_plane(const NodePath &plane, int plane_id);
   virtual void end_bind_clip_planes();
   virtual void end_bind_clip_planes();
 
 
   virtual void set_blend_mode();
   virtual void set_blend_mode();

+ 2 - 2
panda/src/putil/bitMask.I

@@ -156,13 +156,13 @@ INLINE BitMask<WordType, num_bits>::
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BitMask::get_num_bits
 //     Function: BitMask::get_num_bits
-//       Access: Published
+//       Access: Published, Static
 //  Description: Returns the number of bits available to set in the
 //  Description: Returns the number of bits available to set in the
 //               bitmask.
 //               bitmask.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class WordType, int num_bits>
 template<class WordType, int num_bits>
 INLINE int BitMask<WordType, num_bits>::
 INLINE int BitMask<WordType, num_bits>::
-get_num_bits() const {
+get_num_bits() {
   return num_bits;
   return num_bits;
 }
 }
 
 

+ 1 - 1
panda/src/putil/bitMask.h

@@ -50,7 +50,7 @@ PUBLISHED:
 
 
   INLINE ~BitMask();
   INLINE ~BitMask();
 
 
-  INLINE int get_num_bits() const;
+  INLINE static int get_num_bits();
   INLINE bool get_bit(int index) const;
   INLINE bool get_bit(int index) const;
   INLINE void set_bit(int index);
   INLINE void set_bit(int index);
   INLINE void clear_bit(int index);
   INLINE void clear_bit(int index);