diff --git a/panda/src/collide/collisionLevelState.I b/panda/src/collide/collisionLevelState.I index 653444e6b4..6e06498d75 100644 --- a/panda/src/collide/collisionLevelState.I +++ b/panda/src/collide/collisionLevelState.I @@ -25,7 +25,7 @@ INLINE CollisionLevelState:: CollisionLevelState(const NodePath &node_path) : _node_path(node_path), - _current(0), + _current(CollisionLevelState::CurrentMask::all_off()), _include_mask(CollideMask::all_on()) { } @@ -85,7 +85,7 @@ operator = (const CollisionLevelState ©) { //////////////////////////////////////////////////////////////////// INLINE int CollisionLevelState:: get_max_colliders() { - return sizeof(CurrentMask) * 8; + return CurrentMask::get_max_num_bits(); } //////////////////////////////////////////////////////////////////// @@ -129,7 +129,7 @@ get_num_colliders() const { INLINE bool CollisionLevelState:: has_collider(int n) const { nassertr(n >= 0 && n < (int)_colliders.size(), false); - return (_current & get_mask(n)) != 0; + return (_current.get_bit(n)); } //////////////////////////////////////////////////////////////////// @@ -139,7 +139,7 @@ has_collider(int n) const { //////////////////////////////////////////////////////////////////// INLINE bool CollisionLevelState:: has_any_collider() const { - return _current != 0; + return !_current.is_zero(); } //////////////////////////////////////////////////////////////////// @@ -233,7 +233,7 @@ omit_collider(int n) { nassertv(n >= 0 && n < (int)_colliders.size()); nassertv(has_collider(n)); - _current &= ~get_mask(n); + _current.clear_bit(n); } //////////////////////////////////////////////////////////////////// @@ -268,14 +268,3 @@ INLINE CollideMask CollisionLevelState:: get_include_mask() const { return _include_mask; } - -//////////////////////////////////////////////////////////////////// -// Function: CollisionLevelState::get_mask -// Access: Private -// Description: Returns a single bit associated with the nth -// collider. -//////////////////////////////////////////////////////////////////// -INLINE CollisionLevelState::CurrentMask CollisionLevelState:: -get_mask(int n) const { - return ((CurrentMask)1) << n; -} diff --git a/panda/src/collide/collisionLevelState.cxx b/panda/src/collide/collisionLevelState.cxx index 823a96b699..80f6b72dc8 100644 --- a/panda/src/collide/collisionLevelState.cxx +++ b/panda/src/collide/collisionLevelState.cxx @@ -33,7 +33,7 @@ clear() { _colliders.clear(); _local_bounds.clear(); _parent_bounds.clear(); - _current = 0; + _current.clear(); } //////////////////////////////////////////////////////////////////// @@ -44,7 +44,8 @@ clear() { //////////////////////////////////////////////////////////////////// void CollisionLevelState:: reserve(int num_colliders) { - nassertv(num_colliders <= get_max_colliders()); + nassertv(!CurrentMask::has_max_num_bits() || + num_colliders <= CurrentMask::get_max_num_bits()); _colliders.reserve(num_colliders); _local_bounds.reserve(num_colliders); } @@ -58,7 +59,8 @@ reserve(int num_colliders) { void CollisionLevelState:: prepare_collider(const ColliderDef &def, const NodePath &root) { int index = (int)_colliders.size(); - nassertv(index < get_max_colliders()); + nassertv(!CurrentMask::has_max_num_bits() || + index <= CurrentMask::get_max_num_bits()); _colliders.push_back(def); CollisionSolid *collider = def._collider; @@ -93,11 +95,9 @@ prepare_collider(const ColliderDef &def, const NodePath &root) { _local_bounds.push_back(gbv); } - CurrentMask mask = get_mask(index); - _current |= mask; + _current.set_bit(index); _parent_bounds = _local_bounds; - nassertv(mask != 0); } //////////////////////////////////////////////////////////////////// @@ -137,8 +137,7 @@ any_in_bounds() { // no collide bits in common between our collider and this // node. CollideMask from_mask = cnode->get_from_collide_mask() & _include_mask; - if (cnode->get_collide_geom() || - (from_mask & node()->get_net_collide_mask()) != 0) { + if (!(from_mask & node()->get_net_collide_mask()).is_zero()) { // There are bits in common, so go ahead and try the // bounding volume. const GeometricBoundingVolume *col_gbv = diff --git a/panda/src/collide/collisionLevelState.h b/panda/src/collide/collisionLevelState.h index c08d9522ed..bb4a6fbb86 100644 --- a/panda/src/collide/collisionLevelState.h +++ b/panda/src/collide/collisionLevelState.h @@ -29,6 +29,7 @@ #include "pointerTo.h" #include "plist.h" #include "pStatCollector.h" +#include "bitMask.h" class CollisionSolid; class CollisionNode; @@ -87,9 +88,7 @@ private: // 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 unsigned int CurrentMask; - - INLINE CurrentMask get_mask(int n) const; + typedef BitMaskNative CurrentMask; WorkingNodePath _node_path; diff --git a/panda/src/collide/collisionNode.I b/panda/src/collide/collisionNode.I index d7e9fad8e0..f033dac0fb 100644 --- a/panda/src/collide/collisionNode.I +++ b/panda/src/collide/collisionNode.I @@ -144,6 +144,39 @@ add_solid(CollisionSolid *solid) { return _solids.size() - 1; } +//////////////////////////////////////////////////////////////////// +// Function: CollisionNode::get_collider_sort +// Access: Published +// Description: Returns the collider_sort value that has been set for +// this particular node. See set_collider_sort(). +//////////////////////////////////////////////////////////////////// +INLINE int CollisionNode:: +get_collider_sort() const { + return _collider_sort; +} + +//////////////////////////////////////////////////////////////////// +// Function: CollisionNode::set_collider_sort +// Access: Published +// Description: Sets a particular collider_sort value on this node. +// This controls the order in which colliders (that is, +// "from nodes") are grouped together for the collision +// traversal. +// +// If there are 32 or fewer colliders added to any +// particular CollisionTraverser, then this value has no +// meaning. It is only useful if there are many +// colliders, which may force the CollisionTraverser to +// make multiple passes through the data; in that case, +// it may be a useful optimization to group colliders +// that have similar bounding volumes together (by +// giving them similar sort values). +//////////////////////////////////////////////////////////////////// +INLINE void CollisionNode:: +set_collider_sort(int sort) { + _collider_sort = sort; +} + //////////////////////////////////////////////////////////////////// // Function: CollisionNode::get_default_collide_mask // Access: Published, Static diff --git a/panda/src/collide/collisionNode.cxx b/panda/src/collide/collisionNode.cxx index 0d7318009d..3a36dbe3d7 100644 --- a/panda/src/collide/collisionNode.cxx +++ b/panda/src/collide/collisionNode.cxx @@ -44,7 +44,7 @@ CollisionNode:: CollisionNode(const string &name) : PandaNode(name), _from_collide_mask(get_default_collide_mask()), - _collide_geom(false) + _collider_sort(0) { set_cull_callback(); @@ -300,62 +300,6 @@ output(ostream &out) const { void CollisionNode:: set_from_collide_mask(CollideMask mask) { _from_collide_mask = mask; - - if (_collide_geom) { - _from_collide_mask |= GeomNode::get_default_collide_mask(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: CollisionNode::set_collide_geom -// Access: Published -// Description: Sets the state of the "collide geom" flag for this -// CollisionNode. -// -// This flag is now deprecated, now that GeomNodes have -// their own into_collide_mask, just like CollisionNodes -// do. Instead of using set_collide_geom(), you should -// use the from_collide_mask to control which GeomNodes -// each CollisionNode will intersect with. -// -// In particular, you may be interested in setting -// from_collide_mask to the value returned by -// GeomNode::get_default_collide_mask(), which is the -// default into_collide_mask that all GeomNodes will be -// given (unless they are explicitly given some other -// mask). -//////////////////////////////////////////////////////////////////// -void CollisionNode:: -set_collide_geom(bool flag) { - // Only repeat this warning every five seconds or so--no need to be - // completely spammy. - static double last_warning = -10.0; - double now = ClockObject::get_global_clock()->get_frame_time(); - double elapsed = now - last_warning; - if (elapsed > 5.0) { - last_warning = now; - collide_cat.warning() - << "Using deprecated set_collide_geom(). Replace this with an appropriate call to set_from_collide_mask(), e.g. set_from_collide_mask(GeomNode::get_default_collide_mask()).\n"; - } - - _collide_geom = flag; - - if (_collide_geom) { - _from_collide_mask |= GeomNode::get_default_collide_mask(); - } else { - _from_collide_mask &= ~GeomNode::get_default_collide_mask(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: CollisionNode::get_collide_geom -// Access: Published -// Description: Returns the current state of the collide_geom flag. -// See set_collide_geom(). -//////////////////////////////////////////////////////////////////// -bool CollisionNode:: -get_collide_geom() const { - return _collide_geom; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/collide/collisionNode.h b/panda/src/collide/collisionNode.h index fd6af16f2d..fa1374aa4d 100644 --- a/panda/src/collide/collisionNode.h +++ b/panda/src/collide/collisionNode.h @@ -61,9 +61,6 @@ PUBLISHED: INLINE CollideMask get_from_collide_mask() const; INLINE CollideMask get_into_collide_mask() const; - void set_collide_geom(bool flag); - bool get_collide_geom() const; - INLINE void clear_solids(); INLINE int get_num_solids() const; INLINE CollisionSolid *get_solid(int n) const; @@ -71,6 +68,9 @@ PUBLISHED: INLINE void remove_solid(int n); INLINE int add_solid(CollisionSolid *solid); + INLINE int get_collider_sort() const; + INLINE void set_collider_sort(int sort); + INLINE static CollideMask get_default_collide_mask(); protected: @@ -83,11 +83,11 @@ private: // traversal will take place in App only. Perhaps we will revisit // this later. CollideMask _from_collide_mask; - bool _collide_geom; + int _collider_sort; typedef pvector< PT(CollisionSolid) > Solids; Solids _solids; - + public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg); diff --git a/panda/src/collide/collisionTraverser.cxx b/panda/src/collide/collisionTraverser.cxx index 13e32f44be..5f7c6a1ba7 100644 --- a/panda/src/collide/collisionTraverser.cxx +++ b/panda/src/collide/collisionTraverser.cxx @@ -40,12 +40,23 @@ #include "pStatTimer.h" #include "indent.h" +#include + PStatCollector CollisionTraverser::_collisions_pcollector("App:Collisions"); PStatCollector CollisionTraverser::_cnode_volume_pcollector("Collision Volumes:CollisionNode"); PStatCollector CollisionTraverser::_gnode_volume_pcollector("Collision Volumes:GeomNode"); PStatCollector CollisionTraverser::_geom_volume_pcollector("Collision Volumes:Geom"); +// This function object class is used in prepare_colliders(), below. +class SortByColliderSort { +public: + inline bool operator () (const CollisionTraverser::OrderedColliderDef &a, + const CollisionTraverser::OrderedColliderDef &b) const { + return DCAST(CollisionNode, a._node_path.node())->get_collider_sort() < DCAST(CollisionNode, b._node_path.node())->get_collider_sort(); + } +}; + //////////////////////////////////////////////////////////////////// // Function: CollisionTraverser::Constructor // Access: Published @@ -466,10 +477,11 @@ prepare_colliders(CollisionTraverser::LevelStates &level_states, // correct. level_state.reserve(min(num_colliders, max_colliders)); + OrderedColliders sorted = _ordered_colliders; + sort(sorted.begin(), sorted.end(), SortByColliderSort()); + OrderedColliders::iterator oci; - for (oci = _ordered_colliders.begin(); - oci != _ordered_colliders.end(); - ++oci) { + for (oci = sorted.begin(); oci != sorted.end(); ++oci) { NodePath cnode_path = (*oci)._node_path; if (!cnode_path.is_same_graph(root)) { diff --git a/panda/src/collide/collisionTraverser.h b/panda/src/collide/collisionTraverser.h index c72b4cb038..545d9aa918 100644 --- a/panda/src/collide/collisionTraverser.h +++ b/panda/src/collide/collisionTraverser.h @@ -142,6 +142,8 @@ private: // pstats category for actual collision detection (vs. bounding heirarchy collision detection) typedef pvector SolidCollideCollectors; SolidCollideCollectors _solid_collide_collectors; + + friend class SortByColliderSort; }; INLINE ostream &operator << (ostream &out, const CollisionTraverser &trav) { diff --git a/panda/src/putil/bitArray.h b/panda/src/putil/bitArray.h index e72dd2c177..7529e9c760 100755 --- a/panda/src/putil/bitArray.h +++ b/panda/src/putil/bitArray.h @@ -45,7 +45,7 @@ class DatagramIterator; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA BitArray { public: - typedef BitMask32 MaskType; + typedef BitMaskNative MaskType; typedef MaskType::WordType WordType; enum { num_bits_per_word = MaskType::num_bits }; diff --git a/panda/src/putil/bitMask.h b/panda/src/putil/bitMask.h index c79f3c73d2..dd681e7b40 100644 --- a/panda/src/putil/bitMask.h +++ b/panda/src/putil/bitMask.h @@ -144,6 +144,15 @@ INLINE ostream &operator << (ostream &out, const BitMask &bitmask) EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, BITMASK32_DEF); typedef BitMask BitMask32; +typedef BitMask BitMask64; + +#if NATIVE_WORDSIZE == 32 +typedef BitMask32 BitMaskNative; +#elif NATIVE_WORDSIZE == 64 +typedef BitMask64 BitMaskNative; +#else +#error No definition for NATIVE_WORDSIZE--should be defined in dtoolbase.h. +#endif // NATIVE_WORDSIZE // Tell GCC that we'll take care of the instantiation explicitly here. #ifdef __GNUC__