mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 01:44:06 -04:00
64-bit collision traverser; add CollisionNode::set_collider_sort()
This commit is contained in:
parent
846e46b8c7
commit
05b0adcbb5
@ -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;
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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) {
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -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__
|
||||
|
Loading…
x
Reference in New Issue
Block a user