diff --git a/panda/src/collide/collisionLevelState.I b/panda/src/collide/collisionLevelState.I index 4023daeec7..653444e6b4 100644 --- a/panda/src/collide/collisionLevelState.I +++ b/panda/src/collide/collisionLevelState.I @@ -25,7 +25,8 @@ INLINE CollisionLevelState:: CollisionLevelState(const NodePath &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), _colliders(parent._colliders), _current(parent._current), + _include_mask(parent._include_mask), _local_bounds(parent._local_bounds) { } @@ -54,6 +56,7 @@ CollisionLevelState(const CollisionLevelState ©) : _node_path(copy._node_path), _colliders(copy._colliders), _current(copy._current), + _include_mask(copy._include_mask), _local_bounds(copy._local_bounds), _parent_bounds(copy._parent_bounds) { @@ -69,6 +72,7 @@ operator = (const CollisionLevelState ©) { _node_path = copy._node_path; _colliders = copy._colliders; _current = copy._current; + _include_mask = copy._include_mask; _local_bounds = copy._local_bounds; _parent_bounds = copy._parent_bounds; } @@ -232,6 +236,39 @@ omit_collider(int 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 // Access: Private diff --git a/panda/src/collide/collisionLevelState.cxx b/panda/src/collide/collisionLevelState.cxx index 87c4486384..e48f99b69c 100644 --- a/panda/src/collide/collisionLevelState.cxx +++ b/panda/src/collide/collisionLevelState.cxx @@ -132,7 +132,7 @@ any_in_bounds() { // Don't even bother testing the bounding volume if there are // no collide bits in common between our collider and this // node. - CollideMask from_mask = cnode->get_from_collide_mask(); + CollideMask from_mask = cnode->get_from_collide_mask() & _include_mask; if (cnode->get_collide_geom() || (from_mask & node()->get_net_collide_mask()) != 0) { // There are bits in common, so go ahead and try the diff --git a/panda/src/collide/collisionLevelState.h b/panda/src/collide/collisionLevelState.h index 1ce7e7735c..e531411a75 100644 --- a/panda/src/collide/collisionLevelState.h +++ b/panda/src/collide/collisionLevelState.h @@ -77,6 +77,9 @@ public: INLINE void omit_collider(int n); + INLINE void set_include_mask(CollideMask include_mask); + INLINE CollideMask get_include_mask() const; + private: // CurrentMask here is a locally-defined value that simply serves // to keep track of the colliders that are still interested in the @@ -92,6 +95,7 @@ private: typedef PTA(ColliderDef) Colliders; Colliders _colliders; CurrentMask _current; + CollideMask _include_mask; typedef PTA(CPT(GeometricBoundingVolume)) BoundingVolumes; BoundingVolumes _local_bounds; diff --git a/panda/src/collide/collisionTraverser.cxx b/panda/src/collide/collisionTraverser.cxx index 8ffca17ef2..3d95951474 100644 --- a/panda/src/collide/collisionTraverser.cxx +++ b/panda/src/collide/collisionTraverser.cxx @@ -602,10 +602,19 @@ r_traverse(CollisionLevelState &level_state) { } } 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(); - if (index >= 0 && index < node->get_num_children()) { - CollisionLevelState next_state(level_state, node->get_child(index)); + int num_children = node->get_num_children(); + 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); }