mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
allow more than 32 colliders in one traverser
This commit is contained in:
parent
309479578b
commit
041058a594
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -87,7 +87,8 @@ PUBLISHED:
|
||||
void write(ostream &out, int indent_level) const;
|
||||
|
||||
private:
|
||||
void prepare_colliders(CollisionLevelState &state, const NodePath &root);
|
||||
typedef pvector<CollisionLevelState> 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<PStatCollector> PassCollectors;
|
||||
PassCollectors _pass_collectors;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const CollisionTraverser &trav) {
|
||||
|
@ -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();
|
||||
|
@ -156,13 +156,13 @@ INLINE BitMask<WordType, num_bits>::
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BitMask::get_num_bits
|
||||
// Access: Published
|
||||
// Access: Published, Static
|
||||
// Description: Returns the number of bits available to set in the
|
||||
// bitmask.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WordType, int num_bits>
|
||||
INLINE int BitMask<WordType, num_bits>::
|
||||
get_num_bits() const {
|
||||
get_num_bits() {
|
||||
return num_bits;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user