allow more than 32 colliders in one traverser

This commit is contained in:
David Rose 2005-04-30 21:12:28 +00:00
parent 309479578b
commit 041058a594
8 changed files with 134 additions and 37 deletions

View File

@ -43,6 +43,46 @@ CollisionLevelState(const CollisionLevelState &parent, PandaNode *child) :
{
}
////////////////////////////////////////////////////////////////////
// Function: CollisionLevelState::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE CollisionLevelState::
CollisionLevelState(const CollisionLevelState &copy) :
_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 &copy) {
_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;
}

View File

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

View File

@ -49,12 +49,16 @@ public:
INLINE CollisionLevelState(const NodePath &node_path);
INLINE CollisionLevelState(const CollisionLevelState &parent,
PandaNode *child);
PandaNode *child);
INLINE CollisionLevelState(const CollisionLevelState &copy);
INLINE void operator = (const CollisionLevelState &copy);
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;

View File

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

View File

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

View File

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

View File

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

View File

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