mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -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::
|
INLINE CollisionLevelState::
|
||||||
CollisionLevelState(const NodePath &node_path) :
|
CollisionLevelState(const NodePath &node_path) :
|
||||||
_node_path(node_path),
|
_node_path(node_path),
|
||||||
_current(0),
|
_current(CollisionLevelState::CurrentMask::all_off()),
|
||||||
_include_mask(CollideMask::all_on())
|
_include_mask(CollideMask::all_on())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ operator = (const CollisionLevelState ©) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE int CollisionLevelState::
|
INLINE int CollisionLevelState::
|
||||||
get_max_colliders() {
|
get_max_colliders() {
|
||||||
return sizeof(CurrentMask) * 8;
|
return CurrentMask::get_max_num_bits();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -129,7 +129,7 @@ get_num_colliders() const {
|
|||||||
INLINE bool CollisionLevelState::
|
INLINE bool CollisionLevelState::
|
||||||
has_collider(int n) const {
|
has_collider(int n) const {
|
||||||
nassertr(n >= 0 && n < (int)_colliders.size(), false);
|
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::
|
INLINE bool CollisionLevelState::
|
||||||
has_any_collider() const {
|
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(n >= 0 && n < (int)_colliders.size());
|
||||||
nassertv(has_collider(n));
|
nassertv(has_collider(n));
|
||||||
|
|
||||||
_current &= ~get_mask(n);
|
_current.clear_bit(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -268,14 +268,3 @@ INLINE CollideMask CollisionLevelState::
|
|||||||
get_include_mask() const {
|
get_include_mask() const {
|
||||||
return _include_mask;
|
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();
|
_colliders.clear();
|
||||||
_local_bounds.clear();
|
_local_bounds.clear();
|
||||||
_parent_bounds.clear();
|
_parent_bounds.clear();
|
||||||
_current = 0;
|
_current.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -44,7 +44,8 @@ clear() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void CollisionLevelState::
|
void CollisionLevelState::
|
||||||
reserve(int num_colliders) {
|
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);
|
_colliders.reserve(num_colliders);
|
||||||
_local_bounds.reserve(num_colliders);
|
_local_bounds.reserve(num_colliders);
|
||||||
}
|
}
|
||||||
@ -58,7 +59,8 @@ reserve(int num_colliders) {
|
|||||||
void CollisionLevelState::
|
void CollisionLevelState::
|
||||||
prepare_collider(const ColliderDef &def, const NodePath &root) {
|
prepare_collider(const ColliderDef &def, const NodePath &root) {
|
||||||
int index = (int)_colliders.size();
|
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);
|
_colliders.push_back(def);
|
||||||
|
|
||||||
CollisionSolid *collider = def._collider;
|
CollisionSolid *collider = def._collider;
|
||||||
@ -93,11 +95,9 @@ prepare_collider(const ColliderDef &def, const NodePath &root) {
|
|||||||
_local_bounds.push_back(gbv);
|
_local_bounds.push_back(gbv);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentMask mask = get_mask(index);
|
_current.set_bit(index);
|
||||||
_current |= mask;
|
|
||||||
|
|
||||||
_parent_bounds = _local_bounds;
|
_parent_bounds = _local_bounds;
|
||||||
nassertv(mask != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -137,8 +137,7 @@ any_in_bounds() {
|
|||||||
// no collide bits in common between our collider and this
|
// no collide bits in common between our collider and this
|
||||||
// node.
|
// node.
|
||||||
CollideMask from_mask = cnode->get_from_collide_mask() & _include_mask;
|
CollideMask from_mask = cnode->get_from_collide_mask() & _include_mask;
|
||||||
if (cnode->get_collide_geom() ||
|
if (!(from_mask & node()->get_net_collide_mask()).is_zero()) {
|
||||||
(from_mask & node()->get_net_collide_mask()) != 0) {
|
|
||||||
// There are bits in common, so go ahead and try the
|
// There are bits in common, so go ahead and try the
|
||||||
// bounding volume.
|
// bounding volume.
|
||||||
const GeometricBoundingVolume *col_gbv =
|
const GeometricBoundingVolume *col_gbv =
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "pointerTo.h"
|
#include "pointerTo.h"
|
||||||
#include "plist.h"
|
#include "plist.h"
|
||||||
#include "pStatCollector.h"
|
#include "pStatCollector.h"
|
||||||
|
#include "bitMask.h"
|
||||||
|
|
||||||
class CollisionSolid;
|
class CollisionSolid;
|
||||||
class CollisionNode;
|
class CollisionNode;
|
||||||
@ -87,9 +88,7 @@ private:
|
|||||||
// 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 unsigned int CurrentMask;
|
typedef BitMaskNative CurrentMask;
|
||||||
|
|
||||||
INLINE CurrentMask get_mask(int n) const;
|
|
||||||
|
|
||||||
WorkingNodePath _node_path;
|
WorkingNodePath _node_path;
|
||||||
|
|
||||||
|
@ -144,6 +144,39 @@ add_solid(CollisionSolid *solid) {
|
|||||||
return _solids.size() - 1;
|
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
|
// Function: CollisionNode::get_default_collide_mask
|
||||||
// Access: Published, Static
|
// Access: Published, Static
|
||||||
|
@ -44,7 +44,7 @@ CollisionNode::
|
|||||||
CollisionNode(const string &name) :
|
CollisionNode(const string &name) :
|
||||||
PandaNode(name),
|
PandaNode(name),
|
||||||
_from_collide_mask(get_default_collide_mask()),
|
_from_collide_mask(get_default_collide_mask()),
|
||||||
_collide_geom(false)
|
_collider_sort(0)
|
||||||
{
|
{
|
||||||
set_cull_callback();
|
set_cull_callback();
|
||||||
|
|
||||||
@ -300,62 +300,6 @@ output(ostream &out) const {
|
|||||||
void CollisionNode::
|
void CollisionNode::
|
||||||
set_from_collide_mask(CollideMask mask) {
|
set_from_collide_mask(CollideMask mask) {
|
||||||
_from_collide_mask = 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_from_collide_mask() const;
|
||||||
INLINE CollideMask get_into_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 void clear_solids();
|
||||||
INLINE int get_num_solids() const;
|
INLINE int get_num_solids() const;
|
||||||
INLINE CollisionSolid *get_solid(int n) const;
|
INLINE CollisionSolid *get_solid(int n) const;
|
||||||
@ -71,6 +68,9 @@ PUBLISHED:
|
|||||||
INLINE void remove_solid(int n);
|
INLINE void remove_solid(int n);
|
||||||
INLINE int add_solid(CollisionSolid *solid);
|
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();
|
INLINE static CollideMask get_default_collide_mask();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -83,7 +83,7 @@ private:
|
|||||||
// traversal will take place in App only. Perhaps we will revisit
|
// traversal will take place in App only. Perhaps we will revisit
|
||||||
// this later.
|
// this later.
|
||||||
CollideMask _from_collide_mask;
|
CollideMask _from_collide_mask;
|
||||||
bool _collide_geom;
|
int _collider_sort;
|
||||||
|
|
||||||
typedef pvector< PT(CollisionSolid) > Solids;
|
typedef pvector< PT(CollisionSolid) > Solids;
|
||||||
Solids _solids;
|
Solids _solids;
|
||||||
|
@ -40,12 +40,23 @@
|
|||||||
#include "pStatTimer.h"
|
#include "pStatTimer.h"
|
||||||
#include "indent.h"
|
#include "indent.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
PStatCollector CollisionTraverser::_collisions_pcollector("App:Collisions");
|
PStatCollector CollisionTraverser::_collisions_pcollector("App:Collisions");
|
||||||
|
|
||||||
PStatCollector CollisionTraverser::_cnode_volume_pcollector("Collision Volumes:CollisionNode");
|
PStatCollector CollisionTraverser::_cnode_volume_pcollector("Collision Volumes:CollisionNode");
|
||||||
PStatCollector CollisionTraverser::_gnode_volume_pcollector("Collision Volumes:GeomNode");
|
PStatCollector CollisionTraverser::_gnode_volume_pcollector("Collision Volumes:GeomNode");
|
||||||
PStatCollector CollisionTraverser::_geom_volume_pcollector("Collision Volumes:Geom");
|
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
|
// Function: CollisionTraverser::Constructor
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -466,10 +477,11 @@ prepare_colliders(CollisionTraverser::LevelStates &level_states,
|
|||||||
// correct.
|
// correct.
|
||||||
level_state.reserve(min(num_colliders, max_colliders));
|
level_state.reserve(min(num_colliders, max_colliders));
|
||||||
|
|
||||||
|
OrderedColliders sorted = _ordered_colliders;
|
||||||
|
sort(sorted.begin(), sorted.end(), SortByColliderSort());
|
||||||
|
|
||||||
OrderedColliders::iterator oci;
|
OrderedColliders::iterator oci;
|
||||||
for (oci = _ordered_colliders.begin();
|
for (oci = sorted.begin(); oci != sorted.end(); ++oci) {
|
||||||
oci != _ordered_colliders.end();
|
|
||||||
++oci) {
|
|
||||||
NodePath cnode_path = (*oci)._node_path;
|
NodePath cnode_path = (*oci)._node_path;
|
||||||
|
|
||||||
if (!cnode_path.is_same_graph(root)) {
|
if (!cnode_path.is_same_graph(root)) {
|
||||||
|
@ -142,6 +142,8 @@ private:
|
|||||||
// pstats category for actual collision detection (vs. bounding heirarchy collision detection)
|
// pstats category for actual collision detection (vs. bounding heirarchy collision detection)
|
||||||
typedef pvector<PStatCollector> SolidCollideCollectors;
|
typedef pvector<PStatCollector> SolidCollideCollectors;
|
||||||
SolidCollideCollectors _solid_collide_collectors;
|
SolidCollideCollectors _solid_collide_collectors;
|
||||||
|
|
||||||
|
friend class SortByColliderSort;
|
||||||
};
|
};
|
||||||
|
|
||||||
INLINE ostream &operator << (ostream &out, const CollisionTraverser &trav) {
|
INLINE ostream &operator << (ostream &out, const CollisionTraverser &trav) {
|
||||||
|
@ -45,7 +45,7 @@ class DatagramIterator;
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA BitArray {
|
class EXPCL_PANDA BitArray {
|
||||||
public:
|
public:
|
||||||
typedef BitMask32 MaskType;
|
typedef BitMaskNative MaskType;
|
||||||
typedef MaskType::WordType WordType;
|
typedef MaskType::WordType WordType;
|
||||||
enum { num_bits_per_word = MaskType::num_bits };
|
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);
|
EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, BITMASK32_DEF);
|
||||||
|
|
||||||
typedef BitMask<PN_uint32, 32> BitMask32;
|
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.
|
// Tell GCC that we'll take care of the instantiation explicitly here.
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
Loading…
x
Reference in New Issue
Block a user