diff --git a/panda/src/collide/collisionLevelState.I b/panda/src/collide/collisionLevelState.I index 0a576919d9..1136b94e3e 100644 --- a/panda/src/collide/collisionLevelState.I +++ b/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 ©) : + _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 ©) { + _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 // Access: Public @@ -197,7 +237,7 @@ omit_collider(int n) { // Description: Returns a single bit associated with the nth // collider. //////////////////////////////////////////////////////////////////// -INLINE CollisionLevelState::ColliderMask CollisionLevelState:: +INLINE CollisionLevelState::CurrentMask CollisionLevelState:: get_mask(int n) const { - return ((ColliderMask)1) << n; + return ((CurrentMask)1) << n; } diff --git a/panda/src/collide/collisionLevelState.cxx b/panda/src/collide/collisionLevelState.cxx index 88f30c4b9f..85486dbf9a 100644 --- a/panda/src/collide/collisionLevelState.cxx +++ b/panda/src/collide/collisionLevelState.cxx @@ -36,12 +36,14 @@ clear() { //////////////////////////////////////////////////////////////////// // Function: CollisionLevelState::reserve // Access: Public -// Description: +// Description: Indicates an intention to add the indicated number of +// colliders to the level state. //////////////////////////////////////////////////////////////////// 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:: prepare_collider(const ColliderDef &def) { int index = (int)_colliders.size(); + nassertv(index < get_max_colliders()); _colliders.push_back(def); CollisionSolid *collider = def._collider; @@ -85,10 +88,12 @@ prepare_collider(const ColliderDef &def) { gbv->xform(def._node_path.get_net_transform()->get_mat()); _local_bounds.push_back(gbv); } - - _current |= get_mask(index); + + CurrentMask mask = get_mask(index); + _current |= mask; _parent_bounds = _local_bounds; + nassertv(mask != 0); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/collide/collisionLevelState.h b/panda/src/collide/collisionLevelState.h index c6743cfb11..1ce7e7735c 100644 --- a/panda/src/collide/collisionLevelState.h +++ b/panda/src/collide/collisionLevelState.h @@ -49,12 +49,16 @@ public: INLINE CollisionLevelState(const NodePath &node_path); INLINE CollisionLevelState(const CollisionLevelState &parent, - PandaNode *child); + PandaNode *child); + INLINE CollisionLevelState(const CollisionLevelState ©); + INLINE void operator = (const CollisionLevelState ©); void clear(); - void reserve(int max_colliders); + void reserve(int num_colliders); void prepare_collider(const ColliderDef &def); + INLINE static int get_max_colliders(); + bool any_in_bounds(); void apply_transform(); @@ -74,20 +78,20 @@ public: INLINE void omit_collider(int n); 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 // current node. Don't confuse it with CollideMask, which is a set // of user-defined bits that specify which CollisionSolids may // 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; typedef PTA(ColliderDef) Colliders; Colliders _colliders; - ColliderMask _current; + CurrentMask _current; typedef PTA(CPT(GeometricBoundingVolume)) BoundingVolumes; BoundingVolumes _local_bounds; diff --git a/panda/src/collide/collisionTraverser.cxx b/panda/src/collide/collisionTraverser.cxx index 9ccbd339a1..73f1661fb9 100644 --- a/panda/src/collide/collisionTraverser.cxx +++ b/panda/src/collide/collisionTraverser.cxx @@ -107,7 +107,7 @@ add_collider(const NodePath &collider, CollisionHandler *handler) { if (hi == _handlers.end()) { _handlers.insert(Handlers::value_type(handler, 1)); } else { - (*hi).second++; + ++(*hi).second; } } @@ -123,7 +123,7 @@ add_collider(const NodePath &collider, CollisionHandler *handler) { if (hi == _handlers.end()) { _handlers.insert(Handlers::value_type(handler, 1)); } else { - (*hi).second++; + ++(*hi).second; } } @@ -226,7 +226,7 @@ get_handler(const NodePath &collider) const { Colliders::const_iterator ci = _colliders.find(collider); if (ci != _colliders.end()) { return (*ci).second; - }; + } return NULL; } @@ -279,15 +279,22 @@ traverse(const NodePath &root) { } #endif // DO_COLLISION_RECORDING - CollisionLevelState level_state(root); - prepare_colliders(level_state, root); - + LevelStates level_states; + prepare_colliders(level_states, root); + Handlers::iterator hi; for (hi = _handlers.begin(); hi != _handlers.end(); ++hi) { (*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(); while (hi != _handlers.end()) { @@ -450,7 +457,7 @@ write(ostream &out, int indent_level) const { CollisionNode *cnode = DCAST(CollisionNode, cnode_path.node()); 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); } } @@ -464,9 +471,13 @@ write(ostream &out, int indent_level) const { // Description: //////////////////////////////////////////////////////////////////// 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; for (oci = _ordered_colliders.begin(); @@ -492,13 +503,26 @@ prepare_colliders(CollisionLevelState &level_state, const NodePath &root) { def._node_path = cnode_path; 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); def._collider = collider; 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(); - for (int c = 0; c < num_colliders; c++) { + for (int c = 0; c < num_colliders; ++c) { if (level_state.has_collider(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(); - for (int c = 0; c < num_colliders; c++) { + for (int c = 0; c < num_colliders; ++c) { if (level_state.has_collider(c)) { entry._from_node = level_state.get_collider_node(c); @@ -610,7 +634,7 @@ r_traverse(CollisionLevelState &level_state) { } else { // Otherwise, visit all the 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)); r_traverse(next_state); } @@ -637,7 +661,7 @@ compare_collider_to_node(CollisionEntry &entry, CollisionNode *cnode; DCAST_INTO_V(cnode, entry._into_node); 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); if (entry._from != entry._into) { const BoundingVolume &solid_bv = entry._into->get_bound(); @@ -678,7 +702,7 @@ compare_collider_to_geom_node(CollisionEntry &entry, GeomNode *gnode; DCAST_INTO_V(gnode, entry._into_node); 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; const Geom *geom = DCAST(Geom, gnode->get_geom(s)); if (geom != (Geom *)NULL) { @@ -862,7 +886,26 @@ r_reset_prev_transform(PandaNode *node) { PandaNode::Children children = node->get_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)); } } + +//////////////////////////////////////////////////////////////////// +// 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]; +} diff --git a/panda/src/collide/collisionTraverser.h b/panda/src/collide/collisionTraverser.h index 5afb32c889..011e426e74 100644 --- a/panda/src/collide/collisionTraverser.h +++ b/panda/src/collide/collisionTraverser.h @@ -87,7 +87,8 @@ PUBLISHED: void write(ostream &out, int indent_level) const; private: - void prepare_colliders(CollisionLevelState &state, const NodePath &root); + typedef pvector LevelStates; + void prepare_colliders(LevelStates &level_states, const NodePath &root); void r_traverse(CollisionLevelState &level_state); @@ -108,6 +109,8 @@ private: void r_reset_prev_transform(PandaNode *node); + PStatCollector &get_pass_collector(int pass); + private: PT(CollisionHandler) _default_handler; TypeHandle _graph_type; @@ -138,6 +141,8 @@ private: static PStatCollector _collisions_pcollector; static PStatCollector _reset_prev_pcollector; PStatCollector _this_pcollector; + typedef pvector PassCollectors; + PassCollectors _pass_collectors; }; INLINE ostream &operator << (ostream &out, const CollisionTraverser &trav) { diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index e04cb855c5..d00accd254 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -221,7 +221,7 @@ protected: virtual void enable_clip_planes(bool enable); virtual void enable_clip_plane(int plane_id, bool enable); 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 set_blend_mode(); diff --git a/panda/src/putil/bitMask.I b/panda/src/putil/bitMask.I index c01581ac6b..1e2eedf597 100644 --- a/panda/src/putil/bitMask.I +++ b/panda/src/putil/bitMask.I @@ -156,13 +156,13 @@ INLINE BitMask:: //////////////////////////////////////////////////////////////////// // Function: BitMask::get_num_bits -// Access: Published +// Access: Published, Static // Description: Returns the number of bits available to set in the // bitmask. //////////////////////////////////////////////////////////////////// template INLINE int BitMask:: -get_num_bits() const { +get_num_bits() { return num_bits; } diff --git a/panda/src/putil/bitMask.h b/panda/src/putil/bitMask.h index bc341e60de..6311d75b3f 100644 --- a/panda/src/putil/bitMask.h +++ b/panda/src/putil/bitMask.h @@ -50,7 +50,7 @@ PUBLISHED: INLINE ~BitMask(); - INLINE int get_num_bits() const; + INLINE static int get_num_bits(); INLINE bool get_bit(int index) const; INLINE void set_bit(int index); INLINE void clear_bit(int index);