traverse to all children of LOD node

This commit is contained in:
David Rose 2006-02-27 18:49:46 +00:00
parent a30470be19
commit 43bbca86fb
4 changed files with 55 additions and 5 deletions

View File

@ -25,7 +25,8 @@
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(0),
_include_mask(CollideMask::all_on())
{ {
} }
@ -40,6 +41,7 @@ CollisionLevelState(const CollisionLevelState &parent, PandaNode *child) :
_node_path(parent._node_path, child), _node_path(parent._node_path, child),
_colliders(parent._colliders), _colliders(parent._colliders),
_current(parent._current), _current(parent._current),
_include_mask(parent._include_mask),
_local_bounds(parent._local_bounds) _local_bounds(parent._local_bounds)
{ {
} }
@ -54,6 +56,7 @@ CollisionLevelState(const CollisionLevelState &copy) :
_node_path(copy._node_path), _node_path(copy._node_path),
_colliders(copy._colliders), _colliders(copy._colliders),
_current(copy._current), _current(copy._current),
_include_mask(copy._include_mask),
_local_bounds(copy._local_bounds), _local_bounds(copy._local_bounds),
_parent_bounds(copy._parent_bounds) _parent_bounds(copy._parent_bounds)
{ {
@ -69,6 +72,7 @@ operator = (const CollisionLevelState &copy) {
_node_path = copy._node_path; _node_path = copy._node_path;
_colliders = copy._colliders; _colliders = copy._colliders;
_current = copy._current; _current = copy._current;
_include_mask = copy._include_mask;
_local_bounds = copy._local_bounds; _local_bounds = copy._local_bounds;
_parent_bounds = copy._parent_bounds; _parent_bounds = copy._parent_bounds;
} }
@ -232,6 +236,39 @@ omit_collider(int n) {
_current &= ~get_mask(n); _current &= ~get_mask(n);
} }
////////////////////////////////////////////////////////////////////
// Function: CollisionLevelState::set_include_mask
// Access: Public
// Description: Specifies the mask that is applied to the into
// CollideMask of nodes in the scene graph before
// testing for bits in common with the from CollideMask
// of colliders. This is normally all bits on, but you
// may set it to some other mask to restrict certain
// bits from consideration.
//
// This is used by the CollisionTraverser to restrict
// collision with geometry except under the lowest level
// of LOD.
////////////////////////////////////////////////////////////////////
INLINE void CollisionLevelState::
set_include_mask(CollideMask include_mask) {
_include_mask = include_mask;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionLevelState::get_include_mask
// Access: Public
// Description: Returns the mask that is applied to the into
// CollideMask of nodes in the scene graph before
// testing for bits in common with the from CollideMask
// of colliders. See set_include_mask().
////////////////////////////////////////////////////////////////////
INLINE CollideMask CollisionLevelState::
get_include_mask() const {
return _include_mask;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CollisionLevelState::get_mask // Function: CollisionLevelState::get_mask
// Access: Private // Access: Private

View File

@ -132,7 +132,7 @@ any_in_bounds() {
// Don't even bother testing the bounding volume if there are // Don't even bother testing the bounding volume if there are
// 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(); CollideMask from_mask = cnode->get_from_collide_mask() & _include_mask;
if (cnode->get_collide_geom() || if (cnode->get_collide_geom() ||
(from_mask & node()->get_net_collide_mask()) != 0) { (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

View File

@ -77,6 +77,9 @@ public:
INLINE void omit_collider(int n); INLINE void omit_collider(int n);
INLINE void set_include_mask(CollideMask include_mask);
INLINE CollideMask get_include_mask() const;
private: private:
// CurrentMask 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 // to keep track of the colliders that are still interested in the
@ -92,6 +95,7 @@ private:
typedef PTA(ColliderDef) Colliders; typedef PTA(ColliderDef) Colliders;
Colliders _colliders; Colliders _colliders;
CurrentMask _current; CurrentMask _current;
CollideMask _include_mask;
typedef PTA(CPT(GeometricBoundingVolume)) BoundingVolumes; typedef PTA(CPT(GeometricBoundingVolume)) BoundingVolumes;
BoundingVolumes _local_bounds; BoundingVolumes _local_bounds;

View File

@ -602,10 +602,19 @@ r_traverse(CollisionLevelState &level_state) {
} }
} else if (node->is_lod_node()) { } else if (node->is_lod_node()) {
// If it's an LODNode, visit the lowest level of detail. // If it's an LODNode, visit the lowest level of detail with all
// bits, allowing collision with geometry under the lowest level
// of default; and visit all other levels without
// GeomNode::get_default_collide_mask(), allowing only collision
// with CollisionNodes and special geometry under higher levels of
// detail.
int index = DCAST(LODNode, node)->get_lowest_switch(); int index = DCAST(LODNode, node)->get_lowest_switch();
if (index >= 0 && index < node->get_num_children()) { int num_children = node->get_num_children();
CollisionLevelState next_state(level_state, node->get_child(index)); for (int i = 0; i < num_children; ++i) {
CollisionLevelState next_state(level_state, node->get_child(i));
if (i != index) {
next_state.set_include_mask(next_state.get_include_mask() & ~GeomNode::get_default_collide_mask());
}
r_traverse(next_state); r_traverse(next_state);
} }