David Rose 22 лет назад
Родитель
Сommit
0e369940cf

+ 156 - 169
panda/src/collide/collisionEntry.I

@@ -25,11 +25,6 @@
 INLINE CollisionEntry::
 CollisionEntry() {
   _flags = 0;
-  _from_space = TransformState::make_identity();
-  _into_space = TransformState::make_identity();
-  _wrt_space = TransformState::make_identity();
-  _inv_wrt_space = TransformState::make_identity();
-  _wrt_prev_space = TransformState::make_identity();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -131,134 +126,105 @@ get_into_node_path() const {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::get_from_space
+//     Function: CollisionEntry::get_respect_prev_transform
 //       Access: Published
-//  Description: Returns the global coordinate space of the
-//               CollisionNode returned by get_from_node(), as of the
-//               time of the collision.  This will be equivalent to a
-//               wrt() from the node to render.
+//  Description: Returns true if the collision was detected by a
+//               CollisionTraverser whose respect_prev_transform
+//               flag was set true, meaning we should consider motion
+//               significant in evaluating collisions.
 ////////////////////////////////////////////////////////////////////
-INLINE const TransformState *CollisionEntry::
-get_from_space() const {
-  return _from_space;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::get_into_space
-//       Access: Published
-//  Description: Returns the global coordinate space of the
-//               CollisionNode or GeomNode returned by
-//               get_into_node(), as of the time of the collision.
-////////////////////////////////////////////////////////////////////
-INLINE const TransformState *CollisionEntry::
-get_into_space() const {
-  return _into_space;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::get_wrt_space
-//       Access: Published
-//  Description: Returns the relative transform of the from node as
-//               seen from the into node.
-////////////////////////////////////////////////////////////////////
-INLINE const TransformState *CollisionEntry::
-get_wrt_space() const {
-  return _wrt_space;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::get_inv_wrt_space
-//       Access: Published
-//  Description: Returns the relative transform of the into node as
-//               seen from the from node.
-////////////////////////////////////////////////////////////////////
-INLINE const TransformState *CollisionEntry::
-get_inv_wrt_space() const {
-  return _inv_wrt_space;
+INLINE bool CollisionEntry::
+get_respect_prev_transform() const {
+  return (_flags & F_respect_prev_transform) != 0;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::get_wrt_prev_space
-//       Access: Published
-//  Description: Returns the relative transform of the from node as
-//               seen from the into node, as of the previous frame
-//               (according to set_prev_transform(), set_fluid_pos(),
-//               etc.)
-////////////////////////////////////////////////////////////////////
-INLINE const TransformState *CollisionEntry::
-get_wrt_prev_space() const {
-  return _wrt_prev_space;
-}
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::get_from_mat
+//     Function: CollisionEntry::set_surface_point
 //       Access: Published
-//  Description: Returns the global coordinate space of the
-//               CollisionNode returned by get_from_node(), as of the
-//               time of the collision.  This will be equivalent to a
-//               wrt() from the node to render.
+//  Description: Stores the point, on the surface of the "into"
+//               object, at which a collision is detected.
+//
+//               This point is specified in the coordinate space of
+//               the "into" object.
 ////////////////////////////////////////////////////////////////////
-INLINE const LMatrix4f &CollisionEntry::
-get_from_mat() const {
-  return _from_space->get_mat();
+INLINE void CollisionEntry::
+set_surface_point(const LPoint3f &point) {
+  _surface_point = point;
+  _flags |= F_has_surface_point;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::get_into_mat
+//     Function: CollisionEntry::set_surface_normal
 //       Access: Published
-//  Description: Returns the global coordinate space of the
-//               CollisionNode or GeomNode returned by
-//               get_into_node(), as of the time of the collision.
+//  Description: Stores the surface normal of the "into" object at the
+//               point of the intersection.
+//
+//               This normal is specified in the coordinate space of
+//               the "into" object.
 ////////////////////////////////////////////////////////////////////
-INLINE const LMatrix4f &CollisionEntry::
-get_into_mat() const {
-  return _into_space->get_mat();
+INLINE void CollisionEntry::
+set_surface_normal(const LVector3f &normal) {
+  _surface_normal = normal;
+  _flags |= F_has_surface_normal;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::get_wrt_mat
+//     Function: CollisionEntry::set_interior_point
 //       Access: Published
-//  Description: Returns the relative transform of the from node as
-//               seen from the into node.
+//  Description: Stores the point, within the interior of the "into"
+//               object, which represents the depth to which the
+//               "from" object has penetrated.  This can also be
+//               described as the intersection point on the surface of
+//               the "from" object (which is inside the "into"
+//               object).
+//
+//               This point is specified in the coordinate space of
+//               the "into" object.
 ////////////////////////////////////////////////////////////////////
-INLINE const LMatrix4f &CollisionEntry::
-get_wrt_mat() const {
-  return _wrt_space->get_mat();
+INLINE void CollisionEntry::
+set_interior_point(const LPoint3f &point) {
+  _interior_point = point;
+  _flags |= F_has_interior_point;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::get_inv_wrt_mat
+//     Function: CollisionEntry::has_surface_point
 //       Access: Published
-//  Description: Returns the relative transform of the into node as
-//               seen from the from node.
+//  Description: Returns true if the surface point has been specified,
+//               false otherwise.  See get_surface_point().  Some
+//               types of collisions may not compute the surface
+//               point.
 ////////////////////////////////////////////////////////////////////
-INLINE const LMatrix4f &CollisionEntry::
-get_inv_wrt_mat() const {
-  return _inv_wrt_space->get_mat();
+INLINE bool CollisionEntry::
+has_surface_point() const {
+  return (_flags & F_has_surface_point) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::get_wrt_prev_mat
+//     Function: CollisionEntry::has_surface_normal
 //       Access: Published
-//  Description: Returns the relative transform of the from node as
-//               seen from the into node, as of the previous frame
-//               (according to set_prev_transform(), set_fluid_pos(),
-//               etc.)
+//  Description: Returns true if the surface normal has been specified,
+//               false otherwise.  See get_surface_normal().  Some
+//               types of collisions may not compute the surface
+//               normal.
 ////////////////////////////////////////////////////////////////////
-INLINE const LMatrix4f &CollisionEntry::
-get_wrt_prev_mat() const {
-  return _wrt_prev_space->get_mat();
+INLINE bool CollisionEntry::
+has_surface_normal() const {
+  return (_flags & F_has_surface_normal) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::set_into_intersection_point
+//     Function: CollisionEntry::has_interior_point
 //       Access: Published
-//  Description:
+//  Description: Returns true if the interior point has been specified,
+//               false otherwise.  See get_interior_point().  Some
+//               types of collisions may not compute the interior
+//               point.
 ////////////////////////////////////////////////////////////////////
-INLINE void CollisionEntry::
-set_into_intersection_point(const LPoint3f &point) {
-  _into_intersection_point = point;
-  _flags |= F_has_into_intersection_point;
+INLINE bool CollisionEntry::
+has_interior_point() const {
+  return (_flags & F_has_interior_point) != 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -270,7 +236,7 @@ set_into_intersection_point(const LPoint3f &point) {
 ////////////////////////////////////////////////////////////////////
 INLINE bool CollisionEntry::
 has_into_intersection_point() const {
-  return (_flags & F_has_into_intersection_point) != 0;
+  return has_surface_point();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -281,10 +247,9 @@ has_into_intersection_point() const {
 //               call this if has_into_intersection_point() returns
 //               false.
 ////////////////////////////////////////////////////////////////////
-INLINE const LPoint3f &CollisionEntry::
+INLINE LPoint3f CollisionEntry::
 get_into_intersection_point() const {
-  nassertr(has_into_intersection_point(), _into_intersection_point);
-  return _into_intersection_point;
+  return get_surface_point(get_into_node_path());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -296,9 +261,7 @@ get_into_intersection_point() const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool CollisionEntry::
 has_from_intersection_point() const {
-  // Since we derive the from_intersection_point from the
-  // into_intersection_point, this is really the same question.
-  return has_into_intersection_point();
+  return has_surface_point();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -311,18 +274,7 @@ has_from_intersection_point() const {
 ////////////////////////////////////////////////////////////////////
 INLINE LPoint3f CollisionEntry::
 get_from_intersection_point() const {
-  return get_into_intersection_point() * get_inv_wrt_mat();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::set_into_surface_normal
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void CollisionEntry::
-set_into_surface_normal(const LVector3f &normal) {
-  _into_surface_normal = normal;
-  _flags |= F_has_into_surface_normal;
+  return get_surface_point(get_from_node_path());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -334,7 +286,7 @@ set_into_surface_normal(const LVector3f &normal) {
 ////////////////////////////////////////////////////////////////////
 INLINE bool CollisionEntry::
 has_into_surface_normal() const {
-  return (_flags & F_has_into_surface_normal) != 0;
+  return has_surface_normal();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -345,21 +297,9 @@ has_into_surface_normal() const {
 //               to call this if has_into_surface_normal() returns
 //               false.
 ////////////////////////////////////////////////////////////////////
-INLINE const LVector3f &CollisionEntry::
+INLINE LVector3f CollisionEntry::
 get_into_surface_normal() const {
-  nassertr(has_into_surface_normal(), _into_surface_normal);
-  return _into_surface_normal;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::set_from_surface_normal
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void CollisionEntry::
-set_from_surface_normal(const LVector3f &normal) {
-  _from_surface_normal = normal;
-  _flags |= F_has_from_surface_normal;
+  return get_surface_normal(get_into_node_path());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -371,7 +311,7 @@ set_from_surface_normal(const LVector3f &normal) {
 ////////////////////////////////////////////////////////////////////
 INLINE bool CollisionEntry::
 has_from_surface_normal() const {
-  return (_flags & (F_has_into_surface_normal | F_has_from_surface_normal)) != 0;
+  return has_surface_normal();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -382,25 +322,9 @@ has_from_surface_normal() const {
 //               the collided-from object.  It is an error to call
 //               this if has_from_surface_normal() returns false.
 ////////////////////////////////////////////////////////////////////
-INLINE const LVector3f &CollisionEntry::
+INLINE 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
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void CollisionEntry::
-set_into_depth(float depth) {
-  _into_depth = depth;
-  _flags |= F_has_into_depth;
+  return get_surface_normal(get_from_node_path());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -413,7 +337,7 @@ set_into_depth(float depth) {
 ////////////////////////////////////////////////////////////////////
 INLINE bool CollisionEntry::
 has_into_depth() const {
-  return (_flags & F_has_into_depth) != 0;
+  return has_surface_point() && has_interior_point();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -428,18 +352,7 @@ has_into_depth() const {
 INLINE float CollisionEntry::
 get_into_depth() const {
   nassertr(has_into_depth(), 0.0);
-  return _into_depth;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionEntry::set_from_depth
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void CollisionEntry::
-set_from_depth(float depth) {
-  _from_depth = depth;
-  _flags |= F_has_from_depth;
+  return (get_surface_point(get_into_node_path()) - get_interior_point(get_into_node_path())).length();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -452,7 +365,7 @@ set_from_depth(float depth) {
 ////////////////////////////////////////////////////////////////////
 INLINE bool CollisionEntry::
 has_from_depth() const {
-  return (_flags & F_has_from_depth) != 0;
+  return has_surface_point() && has_interior_point();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -466,8 +379,82 @@ has_from_depth() const {
 ////////////////////////////////////////////////////////////////////
 INLINE float CollisionEntry::
 get_from_depth() const {
-  nassertr(has_from_depth(), 0.0);
-  return _from_depth;
+  return (get_surface_point(get_from_node_path()) - get_interior_point(get_from_node_path())).length();
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::get_wrt_space
+//       Access: Public
+//  Description: Returns the relative transform of the from node as
+//               seen from the into node.
+////////////////////////////////////////////////////////////////////
+INLINE CPT(TransformState) CollisionEntry::
+get_wrt_space() const {
+  return _from_node_path.get_transform(_into_node_path);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::get_inv_wrt_space
+//       Access: Public
+//  Description: Returns the relative transform of the into node as
+//               seen from the from node.
+////////////////////////////////////////////////////////////////////
+INLINE CPT(TransformState) CollisionEntry::
+get_inv_wrt_space() const {
+  return _into_node_path.get_transform(_from_node_path);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::get_wrt_prev_space
+//       Access: Public
+//  Description: Returns the relative transform of the from node as
+//               seen from the into node, as of the previous frame
+//               (according to set_prev_transform(), set_fluid_pos(),
+//               etc.)
+////////////////////////////////////////////////////////////////////
+INLINE CPT(TransformState) CollisionEntry::
+get_wrt_prev_space() const {
+  if (get_respect_prev_transform()) {
+    return _from_node_path.get_prev_transform(_into_node_path);
+  } else {
+    return get_wrt_space();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::get_wrt_mat
+//       Access: Public
+//  Description: Returns the relative transform of the from node as
+//               seen from the into node.
+////////////////////////////////////////////////////////////////////
+INLINE const LMatrix4f &CollisionEntry::
+get_wrt_mat() const {
+  return get_wrt_space()->get_mat();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::get_inv_wrt_mat
+//       Access: Public
+//  Description: Returns the relative transform of the into node as
+//               seen from the from node.
+////////////////////////////////////////////////////////////////////
+INLINE const LMatrix4f &CollisionEntry::
+get_inv_wrt_mat() const {
+  return get_inv_wrt_space()->get_mat();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::get_wrt_prev_mat
+//       Access: Public
+//  Description: Returns the relative transform of the from node as
+//               seen from the into node, as of the previous frame
+//               (according to set_prev_transform(), set_fluid_pos(),
+//               etc.)
+////////////////////////////////////////////////////////////////////
+INLINE const LMatrix4f &CollisionEntry::
+get_wrt_prev_mat() const {
+  return get_wrt_prev_space()->get_mat();
 }
 
 ////////////////////////////////////////////////////////////////////

+ 95 - 25
panda/src/collide/collisionEntry.cxx

@@ -33,15 +33,10 @@ CollisionEntry(const CollisionEntry &copy) :
   _into_node(copy._into_node),
   _from_node_path(copy._from_node_path),
   _into_node_path(copy._into_node_path),
-  _from_space(copy._from_space),
-  _into_space(copy._into_space),
-  _wrt_space(copy._wrt_space),
-  _inv_wrt_space(copy._inv_wrt_space),
-  _wrt_prev_space(copy._wrt_prev_space),
   _flags(copy._flags),
-  _into_intersection_point(copy._into_intersection_point),
-  _into_surface_normal(copy._into_surface_normal),
-  _into_depth(copy._into_depth)
+  _surface_point(copy._surface_point),
+  _surface_normal(copy._surface_normal),
+  _interior_point(copy._interior_point)
 {
 }
 
@@ -58,26 +53,101 @@ operator = (const CollisionEntry &copy) {
   _into_node = copy._into_node;
   _from_node_path = copy._from_node_path;
   _into_node_path = copy._into_node_path;
-  _from_space = copy._from_space;
-  _into_space = copy._into_space;
-  _wrt_space = copy._wrt_space;
-  _inv_wrt_space = copy._inv_wrt_space;
-  _wrt_prev_space = copy._wrt_prev_space;
   _flags = copy._flags;
-  _into_intersection_point = copy._into_intersection_point;
-  _into_surface_normal = copy._into_surface_normal;
-  _into_depth = copy._into_depth;
+  _surface_point = copy._surface_point;
+  _surface_normal = copy._surface_normal;
+  _interior_point = copy._interior_point;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     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.
+//     Function: CollisionEntry::get_surface_point
+//       Access: Published
+//  Description: Returns the point, on the surface of the "into"
+//               object, at which a collision is detected.  This can
+//               be thought of as the first point of intersection.
+//
+//               The point will be converted into whichever coordinate
+//               space the caller specifies.
 ////////////////////////////////////////////////////////////////////
-void CollisionEntry::
-compute_from_surface_normal() {
-  _from_surface_normal = get_into_surface_normal() * get_inv_wrt_mat();
-  _flags |= F_has_from_surface_normal;
+LPoint3f CollisionEntry::
+get_surface_point(const NodePath &space) const {
+  nassertr(has_surface_point(), LPoint3f::zero());
+  return _surface_point * _into_node_path.get_mat(space);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::get_surface_normal
+//       Access: Published
+//  Description: Returns the surface normal of the "into" object at
+//               the point at which a collision is detected.
+//
+//               The normal will be converted into whichever coordinate
+//               space the caller specifies.
+////////////////////////////////////////////////////////////////////
+LVector3f CollisionEntry::
+get_surface_normal(const NodePath &space) const {
+  nassertr(has_surface_normal(), LVector3f::zero());
+  return _surface_normal * _into_node_path.get_mat(space);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::get_interior_point
+//       Access: Published
+//  Description: Returns the point, within the interior of the "into"
+//               object, which represents the depth to which the
+//               "from" object has penetrated.  This can also be
+//               described as the intersection point on the surface of
+//               the "from" object (which is inside the "into"
+//               object).  It can be thought of as the deepest point
+//               of intersection.
+//
+//               The point will be converted into whichever coordinate
+//               space the caller specifies.
+////////////////////////////////////////////////////////////////////
+LPoint3f CollisionEntry::
+get_interior_point(const NodePath &space) const {
+  if (!has_interior_point()) {
+    return get_surface_point(space);
+  }
+  return _interior_point * _into_node_path.get_mat(space);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::get_all
+//       Access: Published
+//  Description: Simultaneously transforms the surface point, surface
+//               normal, and interior point of the collision into the
+//               indicated coordinate space.
+//
+//               Returns true if all three properties are available,
+//               or false if any one of them is not.
+////////////////////////////////////////////////////////////////////
+bool CollisionEntry::
+get_all(const NodePath &space, LPoint3f &surface_point,
+        LVector3f &surface_normal, LPoint3f &interior_point) const {
+  const LMatrix4f &mat = _into_node_path.get_mat(space);
+  bool all_ok = true;
+
+  if (!has_surface_point()) {
+    surface_point = LPoint3f::zero();
+    all_ok = false;
+  } else {
+    surface_point = _surface_point * mat;
+  }
+
+  if (!has_surface_normal()) {
+    surface_normal = LVector3f::zero();
+    all_ok = false;
+  } else {
+    surface_normal = _surface_normal * mat;
+  }
+
+  if (!has_interior_point()) {
+    interior_point = surface_point;
+    all_ok = false;
+  } else {
+    interior_point = _interior_point * mat;
+  }
+
+  return true;
 }

+ 42 - 34
panda/src/collide/collisionEntry.h

@@ -62,41 +62,57 @@ PUBLISHED:
   INLINE const NodePath &get_from_node_path() const;
   INLINE const NodePath &get_into_node_path() const;
 
-  INLINE const TransformState *get_from_space() const;
-  INLINE const TransformState *get_into_space() const;
-  INLINE const TransformState *get_wrt_space() const;
-  INLINE const TransformState *get_inv_wrt_space() const;
-  INLINE const TransformState *get_wrt_prev_space() const;
-
-  INLINE const LMatrix4f &get_from_mat() const;
-  INLINE const LMatrix4f &get_into_mat() const;
-  INLINE const LMatrix4f &get_wrt_mat() const;
-  INLINE const LMatrix4f &get_inv_wrt_mat() const;
-  INLINE const LMatrix4f &get_wrt_prev_mat() const;
+  INLINE bool get_respect_prev_transform() const;
+
+  INLINE void set_surface_point(const LPoint3f &point);
+  INLINE void set_surface_normal(const LVector3f &normal);
+  INLINE void set_interior_point(const LPoint3f &point);
+
+  INLINE bool has_surface_point() const;
+  INLINE bool has_surface_normal() const;
+  INLINE bool has_interior_point() const;
+
+  LPoint3f get_surface_point(const NodePath &space) const;
+  LVector3f get_surface_normal(const NodePath &space) const;
+  LPoint3f get_interior_point(const NodePath &space) const;
+  bool get_all(const NodePath &space,
+               LPoint3f &surface_point,
+               LVector3f &surface_normal,
+               LPoint3f &interior_point) const;
+
+
+  // The following methods are all deprecated in favor of the above
+  // methods.  They are here only temporarily to ease transition.
 
-  INLINE void set_into_intersection_point(const LPoint3f &point);
   INLINE bool has_into_intersection_point() const;
-  INLINE const LPoint3f &get_into_intersection_point() const;
+  INLINE LPoint3f get_into_intersection_point() const;
 
   INLINE bool has_from_intersection_point() const;
   INLINE LPoint3f get_from_intersection_point() const;
 
-  INLINE void set_into_surface_normal(const LVector3f &normal);
   INLINE bool has_into_surface_normal() const;
-  INLINE const LVector3f &get_into_surface_normal() const;
+  INLINE 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 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;
 
+public:
+  INLINE CPT(TransformState) get_wrt_space() const;
+  INLINE CPT(TransformState) get_inv_wrt_space() const;
+  INLINE CPT(TransformState) get_wrt_prev_space() const;
+
+  INLINE const LMatrix4f &get_wrt_mat() const;
+  INLINE const LMatrix4f &get_inv_wrt_mat() const;
+  INLINE const LMatrix4f &get_wrt_prev_mat() const;
+
+
+
 private:
   INLINE void test_intersection(CollisionHandler *record, 
                                 const CollisionTraverser *trav) const;
@@ -109,27 +125,19 @@ private:
   PT(PandaNode) _into_node;
   NodePath _from_node_path;
   NodePath _into_node_path;
-  CPT(TransformState) _from_space;
-  CPT(TransformState) _into_space;
-  CPT(TransformState) _wrt_space;
-  CPT(TransformState) _inv_wrt_space;
-  CPT(TransformState) _wrt_prev_space;
 
   enum Flags {
-    F_has_into_intersection_point = 0x0001,
-    F_has_into_surface_normal     = 0x0002,
-    F_has_from_surface_normal     = 0x0004,
-    F_has_into_depth              = 0x0008,
-    F_has_from_depth              = 0x0010,
+    F_has_surface_point       = 0x0001,
+    F_has_surface_normal      = 0x0002,
+    F_has_interior_point      = 0x0004,
+    F_respect_prev_transform  = 0x0008,
   };
 
   int _flags;
 
-  LPoint3f _into_intersection_point;
-  LVector3f _into_surface_normal;
-  LVector3f _from_surface_normal;
-  float _into_depth;
-  float _from_depth;
+  LPoint3f _surface_point;
+  LVector3f _surface_normal;
+  LPoint3f _interior_point;
 
 public:
   static TypeHandle get_class_type() {

+ 10 - 25
panda/src/collide/collisionHandlerFloor.cxx

@@ -77,12 +77,7 @@ handle_entries() {
       okflag = false;
     } else {
       ColliderDef &def = (*ci).second;
-      if (!def.is_valid()) {
-        collide_cat.error()
-          << "Removing invalid collider " << from_node_path << " from "
-          << get_type() << "\n";
-        _colliders.erase(ci);
-      } else {
+      {
         // Get the maximum height for all collisions with this node.
         bool got_max = false;
         float max_height = 0.0f;
@@ -93,8 +88,8 @@ handle_entries() {
           nassertr(entry != (CollisionEntry *)NULL, false);
           nassertr(from_node_path == entry->get_from_node_path(), false);
           
-          if (entry->has_from_intersection_point()) {
-            LPoint3f point = entry->get_from_intersection_point();
+          if (entry->has_surface_point()) {
+            LPoint3f point = entry->get_surface_point(def._target);
             if (collide_cat.is_debug()) {
               collide_cat.debug()
                 << "Intersection point detected at " << point << "\n";
@@ -121,25 +116,15 @@ handle_entries() {
               _max_velocity * ClockObject::get_global_clock()->get_dt();
             adjust = max(adjust, -max_adjust);
           }
-          
-          if (def._node != (PandaNode *)NULL) {
-            // If we are adjusting a plain PandaNode, get the
-            // transform and adjust just the Z value to preserve
-            // maximum precision.
-            CPT(TransformState) trans = def._node->get_transform();
-            LVecBase3f pos = trans->get_pos();
-            pos[2] += adjust;
-            def._node->set_transform(trans->set_pos(pos));
 
-          } else {
-            // Otherwise, go ahead and do the matrix math to do things
-            // the old and clumsy way.
-            LMatrix4f mat;
-            def.get_mat(mat);
-            mat(3, 2) += adjust;
-            def.set_mat(mat);
-          }
+          CPT(TransformState) trans = def._target.get_transform();
+          LVecBase3f pos = trans->get_pos();
+          pos[2] += adjust;
+          def._target.set_transform(trans->set_pos(pos));
+          def.updated_transform();
+
           apply_linear_force(def, LVector3f(0.0f, 0.0f, adjust));
+
         } else {
           if (collide_cat.is_spam()) {
             collide_cat.spam()

+ 11 - 32
panda/src/collide/collisionHandlerPhysical.I

@@ -18,48 +18,27 @@
 
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionHandlerPhysical::ColliderDef::set_drive_interface
+//     Function: CollisionHandlerPhysical::ColliderDef::set_target
 //       Access: Public
 //  Description:
 ////////////////////////////////////////////////////////////////////
 INLINE void CollisionHandlerPhysical::ColliderDef::
-set_drive_interface(DriveInterface *drive_interface) {
+set_target(const NodePath &target, DriveInterface *drive_interface) {
+  _target = target;
   _drive_interface = drive_interface;
-  _node.clear();
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CollisionHandlerPhysical::ColliderDef::set_node
+//     Function: CollisionHandlerPhysical::ColliderDef::updated_transform
 //       Access: Public
-//  Description:
+//  Description: Called by the handler when it has changed the
+//               transform on the target node, this applies the change
+//               to the drive interface if one is specified.
 ////////////////////////////////////////////////////////////////////
 INLINE void CollisionHandlerPhysical::ColliderDef::
-set_node(PandaNode *node) {
-  _node = node;
-  _drive_interface.clear();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionHandlerPhysical::ColliderDef::set_target
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void CollisionHandlerPhysical::ColliderDef::
-set_target(const NodePath &target) {
-  _target = target;
-  if (!target.is_empty()) {
-    _node = target.node();
+updated_transform() {
+  if (_drive_interface != (DriveInterface *)NULL) {
+    _drive_interface->set_mat(_target.get_mat());
+    _drive_interface->force_dgraph();
   }
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionHandlerPhysical::ColliderDef::is_valid
-//       Access: Public
-//  Description: Returns true if this ColliderDef is still valid;
-//               e.g. it refers to a valid node or drive interface.
-////////////////////////////////////////////////////////////////////
-INLINE bool CollisionHandlerPhysical::ColliderDef::
-is_valid() const {
-  return (_node != (PandaNode *)NULL) ||
-    (_drive_interface != (DriveInterface *)NULL);
-}

+ 21 - 50
panda/src/collide/collisionHandlerPhysical.cxx

@@ -24,43 +24,6 @@
 TypeHandle CollisionHandlerPhysical::_type_handle;
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionHandlerPhysical::ColliderDef::get_mat
-//       Access: Public
-//  Description: Fills mat with the matrix representing the current
-//               position and orientation of this collider.
-////////////////////////////////////////////////////////////////////
-void CollisionHandlerPhysical::ColliderDef::
-get_mat(LMatrix4f &mat) const {
-  if (_node != (PandaNode *)NULL) {
-    mat = _node->get_transform()->get_mat();
-  } else if (_drive_interface != (DriveInterface *)NULL) {
-    mat = _drive_interface->get_mat();
-  } else {
-    collide_cat.error()
-      << "Invalid CollisionHandlerPhysical::ColliderDef\n";
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionHandlerPhysical::ColliderDef::set_mat
-//       Access: Public
-//  Description: Moves this collider to the position and orientation
-//               indicated by the given transform.
-////////////////////////////////////////////////////////////////////
-void CollisionHandlerPhysical::ColliderDef::
-set_mat(const LMatrix4f &mat) {
-  if (_node != (PandaNode *)NULL) {
-    _node->set_transform(TransformState::make_mat(mat));
-  } else if (_drive_interface != (DriveInterface *)NULL) {
-    _drive_interface->set_mat(mat);
-    _drive_interface->force_dgraph();
-  } else {
-    collide_cat.error()
-      << "Invalid CollisionHandlerPhysical::ColliderDef\n";
-  }
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionHandlerPhysical::Constructor
 //       Access: Public
@@ -140,6 +103,27 @@ add_collider(const NodePath &collider, const NodePath &target) {
   _colliders[collider].set_target(target);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandlerPhysical::add_collider
+//       Access: Published
+//  Description: Adds a new collider to the list with a NodePath
+//               that will be updated with the collider's new
+//               position, or updates the existing collider with a new
+//               NodePath object.
+//
+//               The indicated DriveInterface will also be updated
+//               with the target's new transform each frame.  This
+//               method should be used when the target is directly
+//               controlled by a DriveInterface.
+////////////////////////////////////////////////////////////////////
+void CollisionHandlerPhysical::
+add_collider(const NodePath &collider, const NodePath &target,
+             DriveInterface *drive_interface) {
+  nassertv(!collider.is_empty() && collider.node()->is_of_type(CollisionNode::get_class_type()));
+  nassertv(!target.is_empty());
+  _colliders[collider].set_target(target, drive_interface);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionHandlerPhysical::remove_collider
 //       Access: Published
@@ -189,16 +173,3 @@ void CollisionHandlerPhysical::
 add_collider_node(CollisionNode *node, PandaNode *target) {
   add_collider(NodePath(node), NodePath(target));
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: CollisionHandlerPhysical::add_collider_drive
-//       Access: Published
-//  Description: Adds a new collider to the list with a DriveInterface
-//               pointer that needs to be told about the collider's
-//               new position, or updates the existing collider with a
-//               new DriveInterface pointer.
-////////////////////////////////////////////////////////////////////
-void CollisionHandlerPhysical::
-add_collider_drive(CollisionNode *node, DriveInterface *drive_interface) {
-  _colliders[NodePath(node)].set_drive_interface(drive_interface);
-}

+ 7 - 13
panda/src/collide/collisionHandlerPhysical.h

@@ -46,6 +46,8 @@ public:
 
 PUBLISHED:
   void add_collider(const NodePath &collider, const NodePath &target);
+  void add_collider(const NodePath &collider, const NodePath &target,
+                    DriveInterface *drive_interface);
   bool remove_collider(const NodePath &collider);
   bool has_collider(const NodePath &collider) const;
   void clear_colliders();
@@ -54,9 +56,6 @@ PUBLISHED:
   // transition to the above new NodePath-based methods.
   void add_collider_node(CollisionNode *node, PandaNode *target);
 
-  // add_collider_drive() is becoming obsolete.  If you need it, let us know.
-  void add_collider_drive(CollisionNode *node, DriveInterface *drive_interface);
-
 protected:
   typedef pvector< PT(CollisionEntry) > Entries;
   typedef pmap<NodePath, Entries> FromEntries;
@@ -64,17 +63,12 @@ protected:
 
   class ColliderDef {
   public:
-    INLINE void set_drive_interface(DriveInterface *drive_interface);
-    INLINE void set_node(PandaNode *node);
-    INLINE void set_target(const NodePath &target);
-    INLINE bool is_valid() const;
-
-    void get_mat(LMatrix4f &mat) const;
-    void set_mat(const LMatrix4f &mat);
-
-    PT(DriveInterface) _drive_interface;
-    PT(PandaNode) _node;
+    INLINE void set_target(const NodePath &target,
+                           DriveInterface *drive_interface = NULL);
+    INLINE void updated_transform();
+    
     NodePath _target;
+    PT(DriveInterface) _drive_interface;
   };
 
   typedef pmap<NodePath, ColliderDef> Colliders;

+ 18 - 31
panda/src/collide/collisionHandlerPusher.cxx

@@ -91,12 +91,7 @@ handle_entries() {
       okflag = false;
     } else {
       ColliderDef &def = (*ci).second;
-      if (!def.is_valid()) {
-        collide_cat.error()
-          << "Removing invalid collider " << from_node_path << " from "
-          << get_type() << "\n";
-        _colliders.erase(ci);
-      } else {
+      {
         // How to apply multiple shoves from different solids onto the
         // same collider?  One's first intuition is to vector sum all
         // the shoves.  However, this causes problems when two parallel
@@ -113,20 +108,22 @@ handle_entries() {
           CollisionEntry *entry = (*ei);
           nassertr(entry != (CollisionEntry *)NULL, false);
           nassertr(from_node_path == entry->get_from_node_path(), false);
-          
-          if (!entry->has_from_surface_normal() ||
-              !entry->has_from_depth()) {
+
+          LPoint3f surface_point;
+          LVector3f normal;
+          LPoint3f interior_point;
+
+          if (!entry->get_all(def._target, surface_point, normal, interior_point)) {
             #ifndef NDEBUG          
             if (collide_cat.is_debug()) {
               collide_cat.debug()
                 << "Cannot shove on " << from_node_path << " for collision into "
-                << *entry->get_into_node() << "; no normal/depth information.\n";
+                << entry->get_into_node_path() << "; no normal/depth information.\n";
             }
             #endif            
           } else {
             // Shove it just enough to clear the volume.
-            if (entry->get_from_depth() != 0.0f) {
-              LVector3f normal = entry->get_from_surface_normal();
+            if (!surface_point.almost_equal(interior_point)) {
               if (_horizontal) {
                 normal[2] = 0.0f;
               }
@@ -137,7 +134,7 @@ handle_entries() {
 
               ShoveData sd;
               sd._vector = normal;
-              sd._length = entry->get_from_depth();
+              sd._length = (surface_point - interior_point).length();
               sd._valid = true;
               sd._entry = entry;
               
@@ -145,7 +142,7 @@ handle_entries() {
               if (collide_cat.is_debug()) {
                 collide_cat.debug()
                   << "Shove on " << from_node_path << " from "
-                  << *entry->get_into_node() << ": " << sd._vector
+                  << entry->get_into_node_path() << ": " << sd._vector
                   << " times " << sd._length << "\n";
               }
               #endif
@@ -248,23 +245,13 @@ handle_entries() {
           }
           #endif
           
-          if (def._node != (PandaNode *)NULL) {
-            // If we are adjusting a plain PandaNode, get the
-            // transform and adjust just the position to preserve
-            // maximum precision.
-            CPT(TransformState) trans = def._node->get_transform();
-            LVecBase3f pos = trans->get_pos();
-            pos += net_shove * trans->get_mat();
-            def._node->set_transform(trans->set_pos(pos));
-            
-            apply_linear_force(def, force_normal);
-          } else {          
-            // Otherwise, go ahead and do the matrix math to do things
-            // the old and clumsy way.
-            LMatrix4f mat;
-            def.get_mat(mat);
-            def.set_mat(LMatrix4f::translate_mat(net_shove) * mat);
-          }
+          CPT(TransformState) trans = def._target.get_transform();
+          LVecBase3f pos = trans->get_pos();
+          pos += net_shove * trans->get_mat();
+          def._target.set_transform(trans->set_pos(pos));
+          def.updated_transform();
+          
+          apply_linear_force(def, force_normal);
         }
       }
     }

+ 13 - 11
panda/src/collide/collisionPlane.cxx

@@ -108,9 +108,11 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   const CollisionSphere *sphere;
   DCAST_INTO_R(sphere, entry.get_from(), 0);
 
-  LPoint3f from_center = sphere->get_center() * entry.get_wrt_mat();
+  const LMatrix4f &wrt_mat = entry.get_wrt_mat();
+
+  LPoint3f from_center = sphere->get_center() * wrt_mat;
   LVector3f from_radius_v =
-    LVector3f(sphere->get_radius(), 0.0f, 0.0f) * entry.get_wrt_mat();
+    LVector3f(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
   float from_radius = length(from_radius_v);
 
   float dist = dist_to_plane(from_center);
@@ -127,12 +129,10 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   PT(CollisionEntry) new_entry = new CollisionEntry(entry);
 
   LVector3f from_normal = get_normal() * entry.get_inv_wrt_mat();
-  float from_depth = from_radius - dist;
 
-  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 - get_normal() * dist);
+  new_entry->set_surface_normal(get_normal());
+  new_entry->set_surface_point(from_center - get_normal() * dist);
+  new_entry->set_interior_point(from_center - get_normal() * from_radius);
 
   return new_entry;
 }
@@ -147,8 +147,10 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
   const CollisionRay *ray;
   DCAST_INTO_R(ray, entry.get_from(), 0);
 
-  LPoint3f from_origin = ray->get_origin() * entry.get_wrt_mat();
-  LVector3f from_direction = ray->get_direction() * entry.get_wrt_mat();
+  const LMatrix4f &wrt_mat = entry.get_wrt_mat();
+
+  LPoint3f from_origin = ray->get_origin() * wrt_mat;
+  LVector3f from_direction = ray->get_direction() * wrt_mat;
 
   float t;
   if (!_plane.intersects_line(t, from_origin, from_direction)) {
@@ -169,8 +171,8 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
   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);
+  new_entry->set_surface_normal(get_normal());
+  new_entry->set_surface_point(into_intersection_point);
 
   return new_entry;
 }

+ 25 - 22
panda/src/collide/collisionPolygon.cxx

@@ -16,7 +16,6 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-
 #include "collisionPolygon.h"
 #include "collisionHandler.h"
 #include "collisionEntry.h"
@@ -34,6 +33,7 @@
 #include "bamReader.h"
 #include "bamWriter.h"
 #include "geomPolygon.h"
+#include "transformState.h"
 
 #include <algorithm>
 
@@ -273,16 +273,21 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   const CollisionSphere *sphere;
   DCAST_INTO_R(sphere, entry.get_from(), 0);
 
-  LPoint3f orig_center = sphere->get_center() * entry.get_wrt_mat();
+  CPT(TransformState) wrt_space = entry.get_wrt_space();
+  CPT(TransformState) wrt_prev_space = entry.get_wrt_space();
+
+  const LMatrix4f &wrt_mat = wrt_space->get_mat();
+
+  LPoint3f orig_center = sphere->get_center() * wrt_mat;
   LPoint3f from_center = orig_center;
   bool moved_from_center = false;
 
-  if (entry.get_wrt_prev_space() != entry.get_wrt_space()) {
+  if (wrt_prev_space != wrt_space) {
     // If we have a delta between the previous position and the
     // current position, we use that to determine some more properties
     // of the collision.
     LPoint3f b = from_center;
-    LPoint3f a = sphere->get_center() * entry.get_wrt_prev_mat();
+    LPoint3f a = sphere->get_center() * wrt_prev_space->get_mat();
     LVector3f delta = b - a;
 
     // First, there is no collision if the "from" object is moving in
@@ -317,7 +322,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   }
 
   LVector3f from_radius_v =
-    LVector3f(sphere->get_radius(), 0.0f, 0.0f) * entry.get_wrt_mat();
+    LVector3f(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
   float from_radius = length(from_radius_v);
 
   float dist = dist_to_plane(from_center);
@@ -406,15 +411,9 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
     into_depth = from_radius - dist_to_plane(orig_center);
   }
 
-  new_entry->set_into_surface_normal(get_normal());
-  new_entry->set_into_depth(into_depth);
-
-  LVector3f from_normal = get_normal() * entry.get_inv_wrt_mat();
-  LVector3f from_depth_vec = (get_normal() * into_depth) * entry.get_inv_wrt_mat();
-  new_entry->set_from_surface_normal(from_normal);
-  new_entry->set_from_depth(from_depth_vec.length());
-
-  new_entry->set_into_intersection_point(from_center - get_normal() * dist);
+  new_entry->set_surface_normal(get_normal());
+  new_entry->set_surface_point(from_center - get_normal() * dist);
+  new_entry->set_interior_point(from_center - get_normal() * (dist + into_depth));
 
   return new_entry;
 }
@@ -435,8 +434,10 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
   const CollisionRay *ray;
   DCAST_INTO_R(ray, entry.get_from(), 0);
 
-  LPoint3f from_origin = ray->get_origin() * entry.get_wrt_mat();
-  LVector3f from_direction = ray->get_direction() * entry.get_wrt_mat();
+  const LMatrix4f &wrt_mat = entry.get_wrt_mat();
+
+  LPoint3f from_origin = ray->get_origin() * wrt_mat;
+  LVector3f from_direction = ray->get_direction() * wrt_mat;
 
   float t;
   if (!get_plane().intersects_line(t, from_origin, from_direction)) {
@@ -462,8 +463,8 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
   }
   PT(CollisionEntry) new_entry = new CollisionEntry(entry);
 
-  new_entry->set_into_surface_normal(get_normal());
-  new_entry->set_into_intersection_point(plane_point);
+  new_entry->set_surface_normal(get_normal());
+  new_entry->set_surface_point(plane_point);
 
   return new_entry;
 }
@@ -484,8 +485,10 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
   const CollisionSegment *segment;
   DCAST_INTO_R(segment, entry.get_from(), 0);
 
-  LPoint3f from_a = segment->get_point_a() * entry.get_wrt_mat();
-  LPoint3f from_b = segment->get_point_b() * entry.get_wrt_mat();
+  const LMatrix4f &wrt_mat = entry.get_wrt_mat();
+
+  LPoint3f from_a = segment->get_point_a() * wrt_mat;
+  LPoint3f from_b = segment->get_point_b() * wrt_mat;
   LPoint3f from_direction = from_b - from_a;
 
   float t;
@@ -513,8 +516,8 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
   }
   PT(CollisionEntry) new_entry = new CollisionEntry(entry);
 
-  new_entry->set_into_surface_normal(get_normal());
-  new_entry->set_into_intersection_point(plane_point);
+  new_entry->set_surface_normal(get_normal());
+  new_entry->set_surface_point(plane_point);
 
   return new_entry;
 }

+ 20 - 20
panda/src/collide/collisionSphere.cxx

@@ -121,9 +121,11 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   const CollisionSphere *sphere;
   DCAST_INTO_R(sphere, entry.get_from(), 0);
 
-  LPoint3f from_center = sphere->get_center() * entry.get_wrt_mat();
+  const LMatrix4f &wrt_mat = entry.get_wrt_mat();
+
+  LPoint3f from_center = sphere->get_center() * wrt_mat;
   LVector3f from_radius_v =
-    LVector3f(sphere->get_radius(), 0.0f, 0.0f) * entry.get_wrt_mat();
+    LVector3f(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
   float from_radius = length(from_radius_v);
 
   LPoint3f into_center = _center;
@@ -143,26 +145,20 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   }
   PT(CollisionEntry) new_entry = new CollisionEntry(entry);
 
-  float dist = sqrtf(dist2);
-  LVector3f into_normal;
+  LVector3f surface_normal;
   float vec_length = vec.length();
   if (IS_NEARLY_ZERO(vec_length)) {
     // If we don't have a collision normal (e.g. the centers are
     // exactly coincident), then make up an arbitrary normal--any one
     // is as good as any other.
-    into_normal.set(1.0, 0.0, 0.0);
+    surface_normal.set(1.0, 0.0, 0.0);
   } else {
-    into_normal = vec / vec_length;
+    surface_normal = vec / vec_length;
   }
-  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);
-  new_entry->set_into_intersection_point(into_intersection_point);
-  new_entry->set_into_depth(into_depth);
 
-  LVector3f from_depth_vec = (into_normal * into_depth) * entry.get_inv_wrt_mat();
-  new_entry->set_from_depth(from_depth_vec.length());
+  new_entry->set_surface_normal(surface_normal);
+  new_entry->set_surface_point(into_center + surface_normal * into_radius);
+  new_entry->set_interior_point(from_center - surface_normal * from_radius);
 
   return new_entry;
 }
@@ -177,8 +173,10 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
   const CollisionRay *ray;
   DCAST_INTO_R(ray, entry.get_from(), 0);
 
-  LPoint3f from_origin = ray->get_origin() * entry.get_wrt_mat();
-  LVector3f from_direction = ray->get_direction() * entry.get_wrt_mat();
+  const LMatrix4f &wrt_mat = entry.get_wrt_mat();
+
+  LPoint3f from_origin = ray->get_origin() * wrt_mat;
+  LVector3f from_direction = ray->get_direction() * wrt_mat;
 
   double t1, t2;
   if (!intersects_line(t1, t2, from_origin, from_direction)) {
@@ -208,7 +206,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
     // at t1.
     into_intersection_point = from_origin + t1 * from_direction;
   }
-  new_entry->set_into_intersection_point(into_intersection_point);
+  new_entry->set_surface_point(into_intersection_point);
 
   return new_entry;
 }
@@ -223,8 +221,10 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
   const CollisionSegment *segment;
   DCAST_INTO_R(segment, entry.get_from(), 0);
 
-  LPoint3f from_a = segment->get_point_a() * entry.get_wrt_mat();
-  LPoint3f from_b = segment->get_point_b() * entry.get_wrt_mat();
+  const LMatrix4f &wrt_mat = entry.get_wrt_mat();
+
+  LPoint3f from_a = segment->get_point_a() * wrt_mat;
+  LPoint3f from_b = segment->get_point_b() * wrt_mat;
   LVector3f from_direction = from_b - from_a;
 
   double t1, t2;
@@ -256,7 +256,7 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
     // sphere or beyond it.  The first intersection point is at t1.
     into_intersection_point = from_a + t1 * from_direction;
   }
-  new_entry->set_into_intersection_point(into_intersection_point);
+  new_entry->set_surface_point(into_intersection_point);
 
   return new_entry;
 }

+ 8 - 19
panda/src/collide/collisionTraverser.cxx

@@ -452,7 +452,9 @@ r_traverse(CollisionLevelState &level_state) {
     CollisionEntry entry;
     entry._into_node = cnode;
     entry._into_node_path = level_state.get_node_path();
-    entry._into_space = entry._into_node_path.get_net_transform();
+    if (_respect_prev_transform) {
+      entry._flags |= CollisionEntry::F_respect_prev_transform;
+    }
 
     int num_colliders = level_state.get_num_colliders();
     for (int c = 0; c < num_colliders; c++) {
@@ -463,17 +465,6 @@ r_traverse(CollisionLevelState &level_state) {
              cnode->get_into_collide_mask()) != 0) {
           entry._from_node_path = level_state.get_collider_node_path(c);
           entry._from = level_state.get_collider(c);
-          entry._from_space = entry._from_node_path.get_net_transform();
-
-          entry._wrt_space = entry._from_node_path.get_transform(entry._into_node_path);
-          entry._inv_wrt_space = entry._into_node_path.get_transform(entry._from_node_path);
-
-          if (_respect_prev_transform) {
-            entry._wrt_prev_space = entry._from_node_path.get_prev_transform(entry._into_node_path);
-
-          } else {
-            entry._wrt_prev_space = entry._wrt_space;
-          }
 
           compare_collider_to_node(entry, 
                                    level_state.get_parent_bound(c),
@@ -502,7 +493,9 @@ r_traverse(CollisionLevelState &level_state) {
     CollisionEntry entry;
     entry._into_node = gnode;
     entry._into_node_path = level_state.get_node_path();
-    entry._into_space = entry._into_node_path.get_net_transform();
+    if (_respect_prev_transform) {
+      entry._flags |= CollisionEntry::F_respect_prev_transform;
+    }
 
     int num_colliders = level_state.get_num_colliders();
     for (int c = 0; c < num_colliders; c++) {
@@ -510,10 +503,6 @@ r_traverse(CollisionLevelState &level_state) {
         entry._from_node = level_state.get_collider_node(c);
         entry._from_node_path = level_state.get_collider_node_path(c);
         entry._from = level_state.get_collider(c);
-        entry._from_space = entry._from_node_path.get_net_transform();
-
-        entry._wrt_space = entry._from_node_path.get_transform(entry._into_node_path);
-        entry._inv_wrt_space = entry._into_node_path.get_transform(entry._from_node_path);
 
         compare_collider_to_geom_node(entry, 
                                       level_state.get_parent_bound(c),
@@ -641,7 +630,7 @@ compare_collider_to_solid(CollisionEntry &entry,
   }
   if (within_solid_bounds) {
     Colliders::const_iterator ci;
-    ci = _colliders.find(entry.get_from_node());
+    ci = _colliders.find(entry.get_from_node_path());
     nassertv(ci != _colliders.end());
     entry.test_intersection((*ci).second, this);
   }
@@ -663,7 +652,7 @@ compare_collider_to_geom(CollisionEntry &entry, Geom *geom,
   }
   if (within_geom_bounds) {
     Colliders::const_iterator ci;
-    ci = _colliders.find(entry.get_from_node());
+    ci = _colliders.find(entry.get_from_node_path());
     nassertv(ci != _colliders.end());
 
     PTA_Vertexf coords;

+ 6 - 0
panda/src/collide/collisionTraverser.h

@@ -108,6 +108,12 @@ private:
   PT(CollisionHandler) _default_handler;
   TypeHandle _graph_type;
 
+  // A map of NodePaths is slightly dangerous, since there is a
+  // (small) possiblity that a particular NodePath's sorting order
+  // relative to other NodePaths will spontaneously change.  This can
+  // only happen if two NodePaths get collapsed together due to a
+  // removal of a certain kind of instanced node; see the comments in
+  // NodePath.cxx.
   typedef pmap<NodePath,  PT(CollisionHandler) > Colliders;
   Colliders _colliders;
   typedef pvector<NodePath> OrderedColliders;

+ 21 - 18
panda/src/collide/collisionTube.cxx

@@ -31,6 +31,7 @@
 #include "bamReader.h"
 #include "bamWriter.h"
 #include "cmath.h"
+#include "transformState.h"
 
 TypeHandle CollisionTube::_type_handle;
 
@@ -130,19 +131,24 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   const CollisionSphere *sphere;
   DCAST_INTO_R(sphere, entry.get_from(), 0);
 
-  LPoint3f from_a = sphere->get_center() * entry.get_wrt_mat();
+  CPT(TransformState) wrt_space = entry.get_wrt_space();
+  CPT(TransformState) wrt_prev_space = entry.get_wrt_space();
+
+  const LMatrix4f &wrt_mat = wrt_space->get_mat();
+
+  LPoint3f from_a = sphere->get_center() * wrt_mat;
   LPoint3f from_b = from_a;
 
-  if (entry.get_wrt_prev_space() != entry.get_wrt_space()) {
+  if (wrt_prev_space != wrt_space) {
     // If the sphere is moving relative to the tube, it becomes a tube
     // itself.
-    from_a = sphere->get_center() * entry.get_wrt_prev_mat();
+    from_a = sphere->get_center() * wrt_prev_space->get_mat();
   }
 
   LVector3f from_direction = from_b - from_a;
 
   LVector3f from_radius_v =
-    LVector3f(sphere->get_radius(), 0.0f, 0.0f) * entry.get_wrt_mat();
+    LVector3f(sphere->get_radius(), 0.0f, 0.0f) * wrt_mat;
   float from_radius = length(from_radius_v);
 
   double t1, t2;
@@ -189,8 +195,10 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
   const CollisionRay *ray;
   DCAST_INTO_R(ray, entry.get_from(), 0);
 
-  LPoint3f from_origin = ray->get_origin() * entry.get_wrt_mat();
-  LVector3f from_direction = ray->get_direction() * entry.get_wrt_mat();
+  const LMatrix4f &wrt_mat = entry.get_wrt_mat();
+
+  LPoint3f from_origin = ray->get_origin() * wrt_mat;
+  LVector3f from_direction = ray->get_direction() * wrt_mat;
 
   double t1, t2;
   if (!intersects_line(t1, t2, from_origin, from_direction, 0.0f)) {
@@ -235,8 +243,10 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
   const CollisionSegment *segment;
   DCAST_INTO_R(segment, entry.get_from(), 0);
 
-  LPoint3f from_a = segment->get_point_a() * entry.get_wrt_mat();
-  LPoint3f from_b = segment->get_point_b() * entry.get_wrt_mat();
+  const LMatrix4f &wrt_mat = entry.get_wrt_mat();
+
+  LPoint3f from_a = segment->get_point_a() * wrt_mat;
+  LPoint3f from_b = segment->get_point_b() * wrt_mat;
   LVector3f from_direction = from_b - from_a;
 
   double t1, t2;
@@ -683,16 +693,9 @@ set_intersection_point(CollisionEntry *new_entry,
   // our collision was tangential.
   LPoint3f orig_point = into_intersection_point - normal * extra_radius;
 
-  // And the difference between point and orig_point is the depth to
-  // which the object has intersected the tube.
-  float depth = (point - orig_point).length();
-
-  new_entry->set_into_intersection_point(point);
-  new_entry->set_into_surface_normal(normal);
-  new_entry->set_into_depth(depth);
-
-  LVector3f from_depth_vec = (normal * depth) * new_entry->get_inv_wrt_mat();
-  new_entry->set_from_depth(from_depth_vec.length());
+  new_entry->set_surface_point(point);
+  new_entry->set_surface_normal(normal);
+  new_entry->set_interior_point(orig_point);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 27 - 0
panda/src/collide/collisionVisualizer.I

@@ -27,3 +27,30 @@ SolidInfo() {
   _detected_count = 0;
   _missed_count = 0;
 }
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionVisualizer::set_viz_scale
+//       Access: Published
+//  Description: Scales the objects that are drawn to represent the
+//               normals and points of the collisions.  By default,
+//               these objects are drawn at an arbitrary scale which
+//               is appropriate if the scene units are measured in
+//               feet.  Change this scale accordinatly if the scene
+//               units are measured on some other scale or if you need
+//               to observe these objects from farther away.
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionVisualizer::
+set_viz_scale(float viz_scale) {
+  _viz_scale = viz_scale;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionVisualizer::get_viz_scale
+//       Access: Published
+//  Description: Returns the value last set by set_viz_scale().
+////////////////////////////////////////////////////////////////////
+INLINE float CollisionVisualizer::
+get_viz_scale() const {
+  return _viz_scale;
+}

+ 26 - 36
panda/src/collide/collisionVisualizer.cxx

@@ -45,6 +45,7 @@ CollisionVisualizer(const string &name) : PandaNode(name) {
   // We always want to render the CollisionVisualizer node itself
   // (even if it doesn't appear to have any geometry within it).
   set_bound(OmniBoundingVolume());
+  _viz_scale = 1.0f;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -167,28 +168,39 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
       for (pi = viz_info._points.begin(); pi != viz_info._points.end(); ++pi) {
         const CollisionPoint &point = (*pi);
 
-        // Draw a tiny sphere at the collision point.
+        // Draw a small red sphere at the surface point, and a smaller
+        // white sphere at the interior point.
         {
           PT(GeomSphere) sphere = new GeomSphere;
           PTA_Vertexf verts;
-          verts.push_back(point._point);
-          verts.push_back(point._point + LVector3f(0.1f, 0.0f, 0.0f));
+          verts.push_back(point._surface_point);
+          verts.push_back(point._surface_point + 
+                          LVector3f(0.1f * _viz_scale, 0.0f, 0.0f));
           sphere->set_coords(verts);
-          sphere->set_colors(colors, G_OVERALL);
+          sphere->set_colors(colors, G_PER_PRIM);
           sphere->set_num_prims(1);
+          
+          if (point._interior_point != point._surface_point) {
+            verts.push_back(point._interior_point);
+            verts.push_back(point._interior_point + 
+                            LVector3f(0.05f * _viz_scale, 0.0f, 0.0f));
+            sphere->set_num_prims(2);
+          }
+
           CullableObject *object = 
             new CullableObject(sphere, empty_state, xform_data._render_transform);
           
           trav->get_cull_handler()->record_object(object);
         }
 
-        // Draw the normal vector at the collision point.
-        if (!point._normal.almost_equal(LVector3f::zero())) {
+        // Draw the normal vector at the surface point.
+        if (!point._surface_normal.almost_equal(LVector3f::zero())) {
           PT(GeomLine) line = new GeomLine;
         
           PTA_Vertexf verts;
-          verts.push_back(point._point);
-          verts.push_back(point._point + point._normal);
+          verts.push_back(point._surface_point);
+          verts.push_back(point._surface_point + 
+                          point._surface_normal * _viz_scale);
           line->set_coords(verts);
           line->set_colors(colors, G_PER_VERTEX);
           line->set_num_prims(1);
@@ -197,25 +209,6 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
             new CullableObject(line, empty_state, xform_data._render_transform);
           
           trav->get_cull_handler()->record_object(object);
-
-          // Also draw the depth vector.
-          if (point._depth != 0.0) {
-            PT(GeomLine) line = new GeomLine;
-            
-            PTA_Vertexf verts;
-            verts.push_back(point._point);
-            verts.push_back(point._point - point._normal * point._depth);
-            PTA_Colorf colors;
-            colors.push_back(Colorf(0.0f, 0.0f, 1.0f, 1.0f));
-
-            line->set_coords(verts);
-            line->set_colors(colors, G_OVERALL);
-            line->set_num_prims(1);
-            
-            CullableObject *object = 
-              new CullableObject(line, empty_state, xform_data._render_transform);
-            trav->get_cull_handler()->record_object(object);
-          }
         }
       }
     }
@@ -272,18 +265,15 @@ collision_tested(const CollisionEntry &entry, bool detected) {
   if (detected) {
     viz_info._solids[entry.get_into()]._detected_count++;
 
-    if (entry.has_into_intersection_point()) {
+    if (entry.has_surface_point()) {
       CollisionPoint p;
-      p._point = entry.get_into_intersection_point();
-      if (entry.has_into_surface_normal()) {
-        p._normal = entry.get_into_surface_normal();
+      p._surface_point = entry.get_surface_point(entry.get_into_node_path());
+      if (entry.has_surface_normal()) {
+        p._surface_normal = entry.get_surface_normal(entry.get_into_node_path());
       } else {
-        p._normal = LVector3f::zero();
-        p._depth = 0.0;
-      }
-      if (entry.has_into_depth()) {
-        p._depth = entry.get_into_depth();
+        p._surface_normal = LVector3f::zero();
       }
+      p._interior_point = entry.get_interior_point(entry.get_into_node_path());
       viz_info._points.push_back(p);
     }
 

+ 8 - 3
panda/src/collide/collisionVisualizer.h

@@ -41,6 +41,9 @@ PUBLISHED:
   CollisionVisualizer(const string &name);
   virtual ~CollisionVisualizer();
 
+  INLINE void set_viz_scale(float viz_scale);
+  INLINE float get_viz_scale() const;
+
   void clear();
 
 public:
@@ -69,9 +72,9 @@ private:
 
   class CollisionPoint {
   public:
-    LPoint3f _point;
-    LVector3f _normal;
-    float _depth;
+    LPoint3f _surface_point;
+    LVector3f _surface_normal;
+    LPoint3f _interior_point;
   };
   typedef pvector<CollisionPoint> Points;
 
@@ -84,6 +87,8 @@ private:
   typedef map<CPT(TransformState), VizInfo> Data;
   Data _data;
 
+  float _viz_scale;
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;