Browse Source

traverse to all children of LOD node

David Rose 20 years ago
parent
commit
43bbca86fb

+ 38 - 1
panda/src/collide/collisionLevelState.I

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

+ 1 - 1
panda/src/collide/collisionLevelState.cxx

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

+ 4 - 0
panda/src/collide/collisionLevelState.h

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

+ 12 - 3
panda/src/collide/collisionTraverser.cxx

@@ -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()) {
-      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);
       r_traverse(next_state);
     }
     }