Browse Source

correct confusion between info_surface_normal and from_surface_normal

David Rose 23 years ago
parent
commit
350dd5cda1

+ 79 - 0
panda/src/collide/collisionEntry.I

@@ -294,6 +294,46 @@ get_into_surface_normal() const {
   return _into_surface_normal;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::set_from_surface_normal
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionEntry::
+set_from_surface_normal(const LVector3f &normal) {
+  _from_surface_normal = normal;
+  _flags |= F_has_from_surface_normal;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::has_from_surface_normal
+//       Access: Public
+//  Description: Returns true if the detected collision knows the
+//               surface normal of the collided-into object at the
+//               point of the collision, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool CollisionEntry::
+has_from_surface_normal() const {
+  return (_flags & (F_has_into_surface_normal | F_has_from_surface_normal)) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::get_from_surface_normal
+//       Access: Public
+//  Description: Returns the surface normal of the collided-into
+//               object at the point of the collision, in the space of
+//               the collided-from object.  It is an error to call
+//               this if has_from_surface_normal() returns false.
+////////////////////////////////////////////////////////////////////
+INLINE const LVector3f &CollisionEntry::
+get_from_surface_normal() const {
+  nassertr(has_from_surface_normal(), _from_surface_normal);
+  if ((_flags & F_has_from_surface_normal) == 0) {
+    ((CollisionEntry *)this)->compute_from_surface_normal();
+  }
+  return _from_surface_normal;
+}
+
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionEntry::set_into_depth
@@ -333,3 +373,42 @@ get_into_depth() const {
   nassertr(has_into_depth(), 0.0);
   return _into_depth;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::set_from_depth
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionEntry::
+set_from_depth(float depth) {
+  _from_depth = depth;
+  _flags |= F_has_from_depth;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::has_from_depth
+//       Access: Public
+//  Description: Returns true if the collision entry knows how "deep"
+//               the collision was from the collided-from object; that
+//               is, how far from the surface of the collided-from
+//               object the colliding object has penetrated.
+////////////////////////////////////////////////////////////////////
+INLINE bool CollisionEntry::
+has_from_depth() const {
+  return (_flags & F_has_from_depth) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::get_from_depth
+//       Access: Public
+//  Description: Returns how "deep" the collision was from the
+//               collided-from object; that is, how far from the
+//               surface of the collided-from object the colliding
+//               object has penetrated.  It is an error to call this
+//               if has_from_depth() returns false.
+////////////////////////////////////////////////////////////////////
+INLINE float CollisionEntry::
+get_from_depth() const {
+  nassertr(has_from_depth(), 0.0);
+  return _from_depth;
+}

+ 13 - 0
panda/src/collide/collisionEntry.cxx

@@ -64,3 +64,16 @@ operator = (const CollisionEntry &copy) {
   _into_surface_normal = copy._into_surface_normal;
   _into_depth = copy._into_depth;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::compute_from_surface_normal
+//       Access: Private
+//  Description: Computes the "from" surface normal by converting the
+//               "into" surface normal into the colliding object's
+//               space.
+////////////////////////////////////////////////////////////////////
+void CollisionEntry::
+compute_from_surface_normal() {
+  _from_surface_normal = get_into_surface_normal() * get_inv_wrt_space();
+  _flags |= F_has_from_surface_normal;
+}

+ 16 - 2
panda/src/collide/collisionEntry.h

@@ -78,11 +78,21 @@ PUBLISHED:
   INLINE bool has_into_surface_normal() const;
   INLINE const LVector3f &get_into_surface_normal() const;
 
+  INLINE void set_from_surface_normal(const LVector3f &normal);
+  INLINE bool has_from_surface_normal() const;
+  INLINE const LVector3f &get_from_surface_normal() const;
+
   INLINE void set_into_depth(float depth);
   INLINE bool has_into_depth() const;
   INLINE float get_into_depth() const;
 
+  INLINE void set_from_depth(float depth);
+  INLINE bool has_from_depth() const;
+  INLINE float get_from_depth() const;
+
 private:
+  void compute_from_surface_normal();
+
   CPT(CollisionSolid) _from;
   CPT(CollisionSolid) _into;
 
@@ -97,8 +107,10 @@ private:
   enum Flags {
     F_has_into_intersection_point = 0x0001,
     F_has_into_surface_normal     = 0x0002,
-    F_has_into_depth              = 0x0004,
-    F_has_from_velocity           = 0x0008,
+    F_has_from_surface_normal     = 0x0004,
+    F_has_into_depth              = 0x0008,
+    F_has_from_depth              = 0x0010,
+    F_has_from_velocity           = 0x0020,
   };
 
   int _flags;
@@ -106,7 +118,9 @@ private:
   LVector3f _from_velocity;
   LPoint3f _into_intersection_point;
   LVector3f _into_surface_normal;
+  LVector3f _from_surface_normal;
   float _into_depth;
+  float _from_depth;
 
 public:
   static TypeHandle get_class_type() {

+ 5 - 5
panda/src/collide/collisionHandlerPusher.cxx

@@ -117,8 +117,8 @@ handle_entries() {
           nassertr(entry != (CollisionEntry *)NULL, false);
           nassertr(from_node == entry->get_from_node(), false);
           
-          if (!entry->has_into_surface_normal() ||
-              !entry->has_into_depth()) {
+          if (!entry->has_from_surface_normal() ||
+              !entry->has_from_depth()) {
 #ifndef NDEBUG          
             if (collide_cat.is_debug()) {
               collide_cat.debug()
@@ -129,8 +129,8 @@ handle_entries() {
             
           } else {
             // Shove it just enough to clear the volume.
-            if (entry->get_into_depth() != 0.0f) {
-              LVector3f normal = entry->get_into_surface_normal();
+            if (entry->get_from_depth() != 0.0f) {
+              LVector3f normal = entry->get_from_surface_normal();
               if (_horizontal) {
                 normal[2] = 0.0f;
               }
@@ -141,7 +141,7 @@ handle_entries() {
 
               ShoveData sd;
               sd._vector = normal;
-              sd._length = entry->get_into_depth();
+              sd._length = entry->get_from_depth();
               sd._valid = true;
               sd._entry = entry;
               

+ 7 - 4
panda/src/collide/collisionPlane.cxx

@@ -141,11 +141,13 @@ test_intersection_from_sphere(CollisionHandler *record,
   }
   PT(CollisionEntry) new_entry = new CollisionEntry(entry);
 
-  LVector3f into_normal = get_normal() * entry.get_inv_wrt_space();
-  float into_depth = from_radius - dist;
+  LVector3f from_normal = get_normal() * entry.get_inv_wrt_space();
+  float from_depth = from_radius - dist;
 
-  new_entry->set_into_surface_normal(into_normal);
-  new_entry->set_into_depth(into_depth);
+  new_entry->set_into_surface_normal(get_normal());
+  new_entry->set_from_surface_normal(from_normal);
+  new_entry->set_from_depth(from_depth);
+  new_entry->set_into_intersection_point(from_center);
 
   record->add_entry(new_entry);
   return 1;
@@ -184,6 +186,7 @@ test_intersection_from_ray(CollisionHandler *record,
   PT(CollisionEntry) new_entry = new CollisionEntry(entry);
 
   LPoint3f into_intersection_point = from_origin + t * from_direction;
+  new_entry->set_into_surface_normal(get_normal());
   new_entry->set_into_intersection_point(into_intersection_point);
 
   record->add_entry(new_entry);

+ 8 - 11
panda/src/collide/collisionPolygon.cxx

@@ -364,17 +364,18 @@ test_intersection_from_sphere(CollisionHandler *record,
   }
   PT(CollisionEntry) new_entry = new CollisionEntry(entry);
 
-  LVector3f into_normal = get_normal() * entry.get_inv_wrt_space();
-  float into_depth = from_radius - dist;
+  LVector3f from_normal = get_normal() * entry.get_inv_wrt_space();
+  float from_depth = from_radius - dist;
   if (moved_from_center) {
     // We have to base the depth of intersection on the sphere's final
     // resting point, not the point from which we tested the
     // intersection.
-    into_depth = from_radius - dist_to_plane(orig_center);
+    from_depth = from_radius - dist_to_plane(orig_center);
   }
 
-  new_entry->set_into_surface_normal(into_normal);
-  new_entry->set_into_depth(into_depth);
+  new_entry->set_into_surface_normal(get_normal());
+  new_entry->set_from_surface_normal(from_normal);
+  new_entry->set_from_depth(from_depth);
   new_entry->set_into_intersection_point(from_center);
 
   record->add_entry(new_entry);
@@ -423,11 +424,9 @@ test_intersection_from_ray(CollisionHandler *record,
   }
   PT(CollisionEntry) new_entry = new CollisionEntry(entry);
 
+  new_entry->set_into_surface_normal(get_normal());
   new_entry->set_into_intersection_point(plane_point);
 
-  LVector3f into_normal = get_normal() * entry.get_inv_wrt_space();
-  new_entry->set_into_surface_normal(into_normal);
-
   record->add_entry(new_entry);
   return 1;
 }
@@ -476,11 +475,9 @@ test_intersection_from_segment(CollisionHandler *record,
   }
   PT(CollisionEntry) new_entry = new CollisionEntry(entry);
 
+  new_entry->set_into_surface_normal(get_normal());
   new_entry->set_into_intersection_point(plane_point);
 
-  LVector3f into_normal = get_normal() * entry.get_inv_wrt_space();
-  new_entry->set_into_surface_normal(into_normal);
-
   record->add_entry(new_entry);
   return 1;
 }

+ 8 - 2
panda/src/collide/collisionSphere.cxx

@@ -150,10 +150,16 @@ test_intersection_from_sphere(CollisionHandler *record,
   LPoint3f into_intersection_point = into_normal * (dist - from_radius);
   float into_depth = into_radius + from_radius - dist;
 
-  new_entry->set_into_surface_normal(into_normal * entry.get_inv_wrt_space());
-  new_entry->set_into_intersection_point(into_intersection_point * entry.get_inv_wrt_space());
+  new_entry->set_into_surface_normal(into_normal);
+  new_entry->set_into_intersection_point(into_intersection_point);
   new_entry->set_into_depth(into_depth);
 
+  // This is a bit of a hack.  This result is incorrect if there is a
+  // scale between the colliding object and this sphere.  We need to
+  // account for that scale, but to account for it correctly
+  // (especially including non-uniform scales) is rather complicated.
+  new_entry->set_from_depth(into_depth);
+
   record->add_entry(new_entry);
   return 1;
 }