64-bit collision traverser; add CollisionNode::set_collider_sort()

This commit is contained in:
David Rose 2007-04-05 15:34:36 +00:00
parent 846e46b8c7
commit 05b0adcbb5
10 changed files with 80 additions and 93 deletions

View File

@ -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 &copy) {
////////////////////////////////////////////////////////////////////
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;
}

View File

@ -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 =

View File

@ -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;

View File

@ -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

View File

@ -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;
}
////////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -40,12 +40,23 @@
#include "pStatTimer.h"
#include "indent.h"
#include <algorithm>
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)) {

View File

@ -142,6 +142,8 @@ private:
// pstats category for actual collision detection (vs. bounding heirarchy collision detection)
typedef pvector<PStatCollector> SolidCollideCollectors;
SolidCollideCollectors _solid_collide_collectors;
friend class SortByColliderSort;
};
INLINE ostream &operator << (ostream &out, const CollisionTraverser &trav) {

View File

@ -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 };

View File

@ -144,6 +144,15 @@ INLINE ostream &operator << (ostream &out, const BitMask<WType, nbits> &bitmask)
EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, BITMASK32_DEF);
typedef BitMask<PN_uint32, 32> BitMask32;
typedef BitMask<PN_uint64, 64> 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__