Browse Source

fix translated GeomNode problem

David Rose 24 years ago
parent
commit
63f4a07801

+ 24 - 1
panda/src/collide/qpcollisionLevelState.I

@@ -191,7 +191,9 @@ get_inv_space(int n) const {
 ////////////////////////////////////////////////////////////////////
 //     Function: qpCollisionLevelState::get_local_bound
 //       Access: Public
-//  Description:
+//  Description: Returns the bounding volume of the indicated
+//               collider, transformed into the current node's
+//               transform space.
 ////////////////////////////////////////////////////////////////////
 INLINE const GeometricBoundingVolume *qpCollisionLevelState::
 get_local_bound(int n) const {
@@ -207,6 +209,27 @@ get_local_bound(int n) const {
   return *(_local_bounds + n);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpCollisionLevelState::get_parent_bound
+//       Access: Public
+//  Description: Returns the bounding volume of the indicated
+//               collider, transformed into the previous node's
+//               transform space, but not transformed by the current
+//               node's transform.  This is appropriate for testing
+//               against the bounding volume of the current node
+//               (which does not have its own transform applied to
+//               it).
+////////////////////////////////////////////////////////////////////
+INLINE const GeometricBoundingVolume *qpCollisionLevelState::
+get_parent_bound(int n) const {
+  nassertr(n >= 0 && n < (int)_colliders.size(), NULL);
+  nassertr(has_collider(n), NULL);
+  nassertr(n >= 0 && n < (int)_parent_bounds.size(), NULL);
+
+  // But it can figure out this equivalent line.
+  return *(_parent_bounds + n);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpCollisionLevelState::omit_collider
 //       Access: Public

+ 42 - 0
panda/src/collide/qpcollisionLevelState.cxx

@@ -29,6 +29,7 @@ void qpCollisionLevelState::
 clear() {
   _colliders.clear();
   _local_bounds.clear();
+  _parent_bounds.clear();
   _current = 0;
   _colliders_with_geom = 0;
 }
@@ -71,6 +72,7 @@ prepare_collider(const ColliderDef &def) {
   if (def._node->get_collide_geom()) {
     _colliders_with_geom |= get_mask(index);
   }
+  _parent_bounds = _local_bounds;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -85,6 +87,16 @@ prepare_collider(const ColliderDef &def) {
 ////////////////////////////////////////////////////////////////////
 bool qpCollisionLevelState::
 any_in_bounds() {
+#ifndef NDEBUG
+  int indent_level = 0;
+  if (collide_cat.is_spam()) {
+    indent_level = _node_path.get_num_nodes() * 2;
+    collide_cat.spam();
+    indent(collide_cat.spam(false), indent_level)
+      << "Considering " << _node_path.get_node_path() << "\n";
+  }
+#endif  // NDEBUG
+
   const BoundingVolume &node_bv = node()->get_bound();
   if (node_bv.is_of_type(GeometricBoundingVolume::get_class_type())) {
     const GeometricBoundingVolume *node_gbv;
@@ -108,6 +120,15 @@ any_in_bounds() {
             get_local_bound(c);
           if (col_gbv != (GeometricBoundingVolume *)NULL) {
             is_in = (node_gbv->contains(col_gbv) != 0);
+
+#ifndef NDEBUG
+            if (collide_cat.is_spam()) {
+              collide_cat.spam();
+              indent(collide_cat.spam(false), indent_level)
+                << "Comparing " << c << ": " << *col_gbv
+                << " to " << *node_gbv << ", is_in = " << is_in << "\n";
+            }
+#endif  // NDEBUG
           }
         }
 
@@ -120,6 +141,22 @@ any_in_bounds() {
     }
   }
 
+#ifndef NDEBUG
+  if (collide_cat.is_spam()) {
+    int num_active_colliders = 0;
+    int num_colliders = get_num_colliders();
+    for (int c = 0; c < num_colliders; c++) {
+      if (has_collider(c)) {
+        num_active_colliders++;
+      }
+    }
+
+    collide_cat.spam();
+    indent(collide_cat.spam(false), indent_level)
+      << _node_path.get_node_path() << " has " << num_active_colliders
+      << " interested colliders.\n";
+  }
+#endif  // NDEBUG
   return has_any_collider();
 }
 
@@ -131,6 +168,11 @@ any_in_bounds() {
 ////////////////////////////////////////////////////////////////////
 void qpCollisionLevelState::
 apply_transform() {
+  // The "parent" bounds list remembers the bounds list of the
+  // previous node.
+  _parent_bounds = _local_bounds;
+
+  // Recompute the bounds list of this node (if we have a transform).
   const TransformState *node_transform = node()->get_transform();
   if (!node_transform->is_identity()) {
     CPT(TransformState) inv_transform = 

+ 8 - 1
panda/src/collide/qpcollisionLevelState.h

@@ -75,10 +75,16 @@ public:
   INLINE const LMatrix4f &get_space(int n) const;
   INLINE const LMatrix4f &get_inv_space(int n) const;
   INLINE const GeometricBoundingVolume *get_local_bound(int n) const;
+  INLINE const GeometricBoundingVolume *get_parent_bound(int n) const;
 
   INLINE void omit_collider(int n);
 
-  //private:
+private:
+  // ColliderMask 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;
 
   INLINE ColliderMask get_mask(int n) const;
@@ -92,6 +98,7 @@ public:
 
   typedef PTA(CPT(GeometricBoundingVolume)) BoundingVolumes;
   BoundingVolumes _local_bounds;
+  BoundingVolumes _parent_bounds;
 };
 
 #include "qpcollisionLevelState.I"

+ 21 - 12
panda/src/collide/qpcollisionTraverser.cxx

@@ -380,15 +380,22 @@ r_traverse(qpCollisionLevelState &level_state) {
           entry._inv_wrt_space =
             entry._into_space * level_state.get_inv_space(c);
 
-          const GeometricBoundingVolume *col_gbv =
-            level_state.get_local_bound(c);
-
-          compare_collider_to_node(entry, col_gbv, node_gbv);
+          compare_collider_to_node(entry, 
+                                   level_state.get_parent_bound(c),
+                                   level_state.get_local_bound(c),
+                                   node_gbv);
         }
       }
     }
 
   } else if (node->is_geom_node() && level_state.has_any_collide_geom()) {
+#ifndef NDEBUG
+    if (collide_cat.is_spam()) {
+      collide_cat.spam()
+        << "Reached " << *node << "\n";
+    }
+#endif
+    
     qpGeomNode *gnode;
     DCAST_INTO_V(gnode, node);
     const BoundingVolume &node_bv = gnode->get_bound();
@@ -417,10 +424,10 @@ r_traverse(qpCollisionLevelState &level_state) {
         entry._inv_wrt_space =
           entry._into_space * level_state.get_inv_space(c);
 
-        const GeometricBoundingVolume *col_gbv =
-          level_state.get_local_bound(c);
-
-        compare_collider_to_geom_node(entry, col_gbv, node_gbv);
+        compare_collider_to_geom_node(entry, 
+                                      level_state.get_parent_bound(c),
+                                      level_state.get_local_bound(c),
+                                      node_gbv);
       }
     }
   }
@@ -439,12 +446,13 @@ r_traverse(qpCollisionLevelState &level_state) {
 ////////////////////////////////////////////////////////////////////
 void qpCollisionTraverser::
 compare_collider_to_node(qpCollisionEntry &entry,
+                         const GeometricBoundingVolume *from_parent_gbv,
                          const GeometricBoundingVolume *from_node_gbv,
                          const GeometricBoundingVolume *into_node_gbv) {
   bool within_node_bounds = true;
-  if (from_node_gbv != (GeometricBoundingVolume *)NULL &&
+  if (from_parent_gbv != (GeometricBoundingVolume *)NULL &&
       into_node_gbv != (GeometricBoundingVolume *)NULL) {
-    within_node_bounds = (into_node_gbv->contains(from_node_gbv) != 0);
+    within_node_bounds = (into_node_gbv->contains(from_parent_gbv) != 0);
   }
 
   if (within_node_bounds) {
@@ -479,12 +487,13 @@ compare_collider_to_node(qpCollisionEntry &entry,
 ////////////////////////////////////////////////////////////////////
 void qpCollisionTraverser::
 compare_collider_to_geom_node(qpCollisionEntry &entry,
+                              const GeometricBoundingVolume *from_parent_gbv,
                               const GeometricBoundingVolume *from_node_gbv,
                               const GeometricBoundingVolume *into_node_gbv) {
   bool within_node_bounds = true;
-  if (from_node_gbv != (GeometricBoundingVolume *)NULL &&
+  if (from_parent_gbv != (GeometricBoundingVolume *)NULL &&
       into_node_gbv != (GeometricBoundingVolume *)NULL) {
-    within_node_bounds = (into_node_gbv->contains(from_node_gbv) != 0);
+    within_node_bounds = (into_node_gbv->contains(from_parent_gbv) != 0);
   }
 
   if (within_node_bounds) {

+ 2 - 0
panda/src/collide/qpcollisionTraverser.h

@@ -62,9 +62,11 @@ private:
   void r_traverse(qpCollisionLevelState &level_state);
 
   void compare_collider_to_node(qpCollisionEntry &entry,
+                                const GeometricBoundingVolume *from_parent_gbv,
                                 const GeometricBoundingVolume *from_node_gbv,
                                 const GeometricBoundingVolume *into_node_gbv);
   void compare_collider_to_geom_node(qpCollisionEntry &entry,
+                                     const GeometricBoundingVolume *from_parent_gbv,
                                      const GeometricBoundingVolume *from_node_gbv,
                                      const GeometricBoundingVolume *into_node_gbv);
   void compare_collider_to_solid(qpCollisionEntry &entry,