Darren Ranalli 18 лет назад
Родитель
Сommit
519ae6bdac

+ 1 - 0
panda/src/collide/collide_composite1.cxx

@@ -7,6 +7,7 @@
 #include "collisionHandlerGravity.cxx"
 #include "collisionHandlerGravity.cxx"
 #include "collisionHandlerPhysical.cxx"
 #include "collisionHandlerPhysical.cxx"
 #include "collisionHandlerPusher.cxx"
 #include "collisionHandlerPusher.cxx"
+#include "collisionHandlerFluidPusher.cxx"
 #include "collisionHandlerQueue.cxx"
 #include "collisionHandlerQueue.cxx"
 #include "collisionDSSolid.cxx"
 #include "collisionDSSolid.cxx"
 #include "collisionInvSphere.cxx"
 #include "collisionInvSphere.cxx"

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

@@ -25,6 +25,7 @@
 INLINE CollisionEntry::
 INLINE CollisionEntry::
 CollisionEntry() {
 CollisionEntry() {
   _flags = 0;
   _flags = 0;
+  _t = 1.f;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -125,6 +126,28 @@ get_into_node_path() const {
   return _into_node_path;
   return _into_node_path;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::set_t
+//       Access: Published
+//  Description: Sets a time value for this collision relative to
+//               other CollisionEntries
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionEntry::
+set_t(float t) {
+  _t = t;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionEntry::set_t
+//       Access: Published
+//  Description: returns time value for this collision relative to
+//               other CollisionEntries
+////////////////////////////////////////////////////////////////////
+INLINE float CollisionEntry::
+get_t() const {
+  return _t;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionEntry::get_respect_prev_transform
 //     Function: CollisionEntry::get_respect_prev_transform
 //       Access: Published
 //       Access: Published

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

@@ -36,6 +36,7 @@ CollisionEntry(const CollisionEntry &copy) :
   _from_node_path(copy._from_node_path),
   _from_node_path(copy._from_node_path),
   _into_node_path(copy._into_node_path),
   _into_node_path(copy._into_node_path),
   _into_clip_planes(copy._into_clip_planes),
   _into_clip_planes(copy._into_clip_planes),
+  _t(copy._t),
   _flags(copy._flags),
   _flags(copy._flags),
   _surface_point(copy._surface_point),
   _surface_point(copy._surface_point),
   _surface_normal(copy._surface_normal),
   _surface_normal(copy._surface_normal),
@@ -57,6 +58,7 @@ operator = (const CollisionEntry &copy) {
   _from_node_path = copy._from_node_path;
   _from_node_path = copy._from_node_path;
   _into_node_path = copy._into_node_path;
   _into_node_path = copy._into_node_path;
   _into_clip_planes = copy._into_clip_planes;
   _into_clip_planes = copy._into_clip_planes;
+  _t = copy._t;
   _flags = copy._flags;
   _flags = copy._flags;
   _surface_point = copy._surface_point;
   _surface_point = copy._surface_point;
   _surface_normal = copy._surface_normal;
   _surface_normal = copy._surface_normal;

+ 5 - 0
panda/src/collide/collisionEntry.h

@@ -63,6 +63,9 @@ PUBLISHED:
   INLINE NodePath get_from_node_path() const;
   INLINE NodePath get_from_node_path() const;
   INLINE NodePath get_into_node_path() const;
   INLINE NodePath get_into_node_path() const;
 
 
+  INLINE void set_t(float t);
+  INLINE float get_t() const;
+
   INLINE bool get_respect_prev_transform() const;
   INLINE bool get_respect_prev_transform() const;
 
 
   INLINE void set_surface_point(const LPoint3f &point);
   INLINE void set_surface_point(const LPoint3f &point);
@@ -108,6 +111,7 @@ private:
   NodePath _from_node_path;
   NodePath _from_node_path;
   NodePath _into_node_path;
   NodePath _into_node_path;
   CPT(ClipPlaneAttrib) _into_clip_planes;
   CPT(ClipPlaneAttrib) _into_clip_planes;
+  float _t;
 
 
   enum Flags {
   enum Flags {
     F_has_surface_point       = 0x0001,
     F_has_surface_point       = 0x0001,
@@ -141,6 +145,7 @@ private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
 
 
   friend class CollisionTraverser;
   friend class CollisionTraverser;
+  friend class CollisionHandlerFluidPusher;
 };
 };
 
 
 INLINE ostream &operator << (ostream &out, const CollisionEntry &entry);
 INLINE ostream &operator << (ostream &out, const CollisionEntry &entry);

+ 40 - 0
panda/src/collide/collisionHandler.I

@@ -0,0 +1,40 @@
+// Filename: collisionHandler.I
+// Created by:  WDIG (15Aug07)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandler::wants_all_potential_collidees
+//       Access: Private
+//  Description: Returns true if handler wants to know about all
+//               solids that are within the collider's bounding
+//               volume
+////////////////////////////////////////////////////////////////////
+INLINE bool CollisionHandler::
+wants_all_potential_collidees() const {
+  return _wants_all_potential_collidees;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandler::set_root
+//       Access: Private
+//  Description: Sets the root of the collision traversal. Only set
+//               if wants_all_potential_collidees is true
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionHandler::
+set_root(const NodePath &root) {
+  _root = &root;
+}

+ 10 - 0
panda/src/collide/collisionHandler.cxx

@@ -20,6 +20,16 @@
 
 
 TypeHandle CollisionHandler::_type_handle;
 TypeHandle CollisionHandler::_type_handle;
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionHandler::Constructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+CollisionHandler::
+CollisionHandler() {
+  _wants_all_potential_collidees = false;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionHandler::begin_group
 //     Function: CollisionHandler::begin_group
 //       Access: Public, Virtual
 //       Access: Public, Virtual

+ 12 - 0
panda/src/collide/collisionHandler.h

@@ -22,6 +22,7 @@
 #include "pandabase.h"
 #include "pandabase.h"
 
 
 #include "typedReferenceCount.h"
 #include "typedReferenceCount.h"
+#include "nodePath.h"
 
 
 class CollisionEntry;
 class CollisionEntry;
 
 
@@ -35,10 +36,15 @@ class CollisionEntry;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_COLLIDE CollisionHandler : public TypedReferenceCount {
 class EXPCL_PANDA_COLLIDE CollisionHandler : public TypedReferenceCount {
 public:
 public:
+  CollisionHandler();
+
   virtual void begin_group();
   virtual void begin_group();
   virtual void add_entry(CollisionEntry *entry);
   virtual void add_entry(CollisionEntry *entry);
   virtual bool end_group();
   virtual bool end_group();
 
 
+  INLINE bool wants_all_potential_collidees() const;
+  INLINE void set_root(const NodePath &root);
+
 PUBLISHED:
 PUBLISHED:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;
@@ -55,12 +61,18 @@ public:
   }
   }
   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
   virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
 
 
+protected:
+  bool _wants_all_potential_collidees;
+  const NodePath *_root;
+
 private:
 private:
   static TypeHandle _type_handle;
   static TypeHandle _type_handle;
 
 
   friend class CollisionTraverser;
   friend class CollisionTraverser;
 };
 };
 
 
+#include "collisionHandler.I"
+
 #endif
 #endif
 
 
 
 

+ 41 - 14
panda/src/collide/collisionHandlerFluidPusher.cxx

@@ -102,13 +102,13 @@ handle_entries() {
     7. go to 2
     7. go to 2
   */
   */
   bool okflag = true;
   bool okflag = true;
-
+  
   if (!_horizontal) {
   if (!_horizontal) {
     collide_cat.error() << "collisionHandlerFluidPusher::handle_entries is only supported in "
     collide_cat.error() << "collisionHandlerFluidPusher::handle_entries is only supported in "
       "horizontal mode" << endl;
       "horizontal mode" << endl;
     nassertr(false, false);
     nassertr(false, false);
   }
   }
-
+  
   // for every fluid mover being pushed...
   // for every fluid mover being pushed...
   FromEntries::iterator fei;
   FromEntries::iterator fei;
   for (fei = _from_entries.begin(); fei != _from_entries.end(); ++fei) {
   for (fei = _from_entries.begin(); fei != _from_entries.end(); ++fei) {
@@ -129,17 +129,30 @@ handle_entries() {
       ColliderDef &def = (*ci).second;
       ColliderDef &def = (*ci).second;
       
       
       // extract the collision entries into a vector that we can safely modify
       // extract the collision entries into a vector that we can safely modify
-      Entries SCS(*entries);
+      Entries entries(*entries);
+      Entries next_entries;
+      
+      // extract out the initial set of collision solids
+      CollisionSolids SCS;
+      
+      Entries::iterator ei;
+      for (ei = entries.begin(); ei != entries.end(); ++ei) {
+        SCS.push_back((*ei)->get_into());
+      }
       
       
       // currently we only support spheres as the collider
       // currently we only support spheres as the collider
       const CollisionSphere *sphere;
       const CollisionSphere *sphere;
-      DCAST_INTO_R(sphere, (*SCS.front()).get_from(), 0);
+      DCAST_INTO_R(sphere, (*entries.front()).get_from(), 0);
       // use a slightly larger radius value so that when we move along
       // use a slightly larger radius value so that when we move along
       // collision planes we don't re-collide
       // collision planes we don't re-collide
       float sphere_radius = sphere->get_radius() * 1.001;
       float sphere_radius = sphere->get_radius() * 1.001;
       
       
+      // make a copy of the original from_nodepath that we can mess with
+      // in the process of calculating the final position
+      _from_node_path_copy = from_node_path.copy_to(from_node_path.get_parent());
+      
       LPoint3f N(from_node_path.get_pos_delta(*_root));
       LPoint3f N(from_node_path.get_pos_delta(*_root));
-      const LPoint3f orig_pos(from_node_path.get_pos());
+      const LPoint3f orig_pos(_from_node_path_copy.get_pos());
       // this will hold the final calculated position
       // this will hold the final calculated position
       LPoint3f PosX(orig_pos);
       LPoint3f PosX(orig_pos);
       
       
@@ -157,20 +170,17 @@ handle_entries() {
       // if both of these become true, we're stuck in a 'corner'
       // if both of these become true, we're stuck in a 'corner'
       bool left_halfspace_obstructed = false;
       bool left_halfspace_obstructed = false;
       bool right_halfspace_obstructed = false;
       bool right_halfspace_obstructed = false;
-      LVector3f left_plane_normal;
-      LVector3f right_plane_normal;
       float left_plane_dot = 200.0f;
       float left_plane_dot = 200.0f;
       float right_plane_dot = 200.0f;
       float right_plane_dot = 200.0f;
       
       
       // iterate until the mover runs out of movement or gets stuck
       // iterate until the mover runs out of movement or gets stuck
       while (true) {
       while (true) {
         CollisionEntry *C = 0;
         CollisionEntry *C = 0;
-        Entries::iterator ei;
         // find the first (earliest) collision
         // find the first (earliest) collision
-        for (ei = SCS.begin(); ei != SCS.end(); ++ei) {
+        for (ei = entries.begin(); ei != entries.end(); ++ei) {
           CollisionEntry *entry = (*ei);
           CollisionEntry *entry = (*ei);
           nassertr(entry != (CollisionEntry *)NULL, false);
           nassertr(entry != (CollisionEntry *)NULL, false);
-          if (entry->get_t() < C->get_t()) {
+          if ((C == 0) || (entry->get_t() < C->get_t())) {
             nassertr(from_node_path == entry->get_from_node_path(), false);
             nassertr(from_node_path == entry->get_from_node_path(), false);
             C = entry;
             C = entry;
             break;
             break;
@@ -186,12 +196,12 @@ handle_entries() {
         nassertr(C->has_surface_point(), true);
         nassertr(C->has_surface_point(), true);
         nassertr(C->has_surface_normal(), true);
         nassertr(C->has_surface_normal(), true);
         nassertr(C->has_interior_point(), true);
         nassertr(C->has_interior_point(), true);
-        LVector3f surface_normal = C->get_surface_normal(from_node_path);
+        LVector3f surface_normal = C->get_surface_normal(_from_node_path_copy);
         if (_horizontal) {
         if (_horizontal) {
           surface_normal[2] = 0.0f;
           surface_normal[2] = 0.0f;
         }
         }
         surface_normal.normalize();
         surface_normal.normalize();
-        PosX = C->get_surface_point(from_node_path) + (sphere_radius * surface_normal);
+        PosX = C->get_surface_point(_from_node_path_copy) + (sphere_radius * surface_normal);
         
         
         // check to see if we're stuck, given this collision
         // check to see if we're stuck, given this collision
         float dot = right_unit.dot(surface_normal);
         float dot = right_unit.dot(surface_normal);
@@ -204,7 +214,6 @@ handle_entries() {
               break;
               break;
             }
             }
             left_halfspace_obstructed = true;
             left_halfspace_obstructed = true;
-            left_plane_normal = surface_normal;
           }
           }
         } else {
         } else {
           // negative dot means plane is coming from the right (looking along original
           // negative dot means plane is coming from the right (looking along original
@@ -216,11 +225,29 @@ handle_entries() {
               break;
               break;
             }
             }
             right_halfspace_obstructed = true;
             right_halfspace_obstructed = true;
-            right_plane_normal = surface_normal;
           }
           }
         }
         }
         
         
         // set up new current/last positions, re-calculate collisions
         // set up new current/last positions, re-calculate collisions
+        CPT(TransformState) prev_trans(_from_node_path_copy.get_prev_transform());
+        prev_trans->set_pos(_from_node_path_copy.get_pos());
+        _from_node_path_copy.set_prev_transform(prev_trans);
+        _from_node_path_copy.set_pos(PosX);
+
+        // calculate new collisions given new movement vector
+        CollisionEntry new_entry;
+        new_entry._from_node_path = _from_node_path_copy;
+        new_entry._from = sphere;
+        next_entries.clear();
+        CollisionSolids::iterator csi;
+        for (csi = SCS.begin(); csi != SCS.end(); ++csi) {
+          PT(CollisionEntry) result = (*csi)->test_intersection_from_sphere(new_entry);
+          if (result != (CollisionEntry *)NULL) {
+            next_entries.push_back(result);
+          }
+        }
+        // swap in the new set of collision events
+        entries.swap(next_entries);
       }
       }
       
       
       LVector3f net_shove(PosX - orig_pos);
       LVector3f net_shove(PosX - orig_pos);

+ 5 - 0
panda/src/collide/collisionHandlerFluidPusher.h

@@ -21,6 +21,7 @@
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 
 
+#include "collisionSolid.h"
 #include "collisionHandlerPusher.h"
 #include "collisionHandlerPusher.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -37,8 +38,12 @@ public:
   virtual void add_entry(CollisionEntry *entry);
   virtual void add_entry(CollisionEntry *entry);
 
 
 protected:
 protected:
+  typedef pvector< CPT(CollisionSolid) > CollisionSolids;
+
   virtual bool handle_entries();
   virtual bool handle_entries();
 
 
+  NodePath _from_node_path_copy;
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 0 - 1
panda/src/collide/collisionHandlerPusher.h

@@ -45,7 +45,6 @@ protected:
       const LVector3f &force_normal);
       const LVector3f &force_normal);
   virtual void apply_linear_force(ColliderDef &def, const LVector3f &force);
   virtual void apply_linear_force(ColliderDef &def, const LVector3f &force);
 
 
-private:
   bool _horizontal;
   bool _horizontal;
 
 
 
 

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

@@ -147,7 +147,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
     // is as good as any other.
     // is as good as any other.
     surface_normal.set(1.0, 0.0, 0.0);
     surface_normal.set(1.0, 0.0, 0.0);
   } else {
   } else {
-    surface_normal = -vec / vec_length;
+    surface_normal = vec / -vec_length;
   }
   }
 
 
   LVector3f normal = (has_effective_normal() && sphere->get_respect_effective_normal()) ? get_effective_normal() : surface_normal;
   LVector3f normal = (has_effective_normal() && sphere->get_respect_effective_normal()) ? get_effective_normal() : surface_normal;

+ 5 - 1
panda/src/collide/collisionPolygon.cxx

@@ -414,6 +414,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   LPoint3f orig_center = sphere->get_center() * wrt_mat;
   LPoint3f orig_center = sphere->get_center() * wrt_mat;
   LPoint3f from_center = orig_center;
   LPoint3f from_center = orig_center;
   bool moved_from_center = false;
   bool moved_from_center = false;
+  float t = 1.0f;
 
 
   if (wrt_prev_space != wrt_space) {
   if (wrt_prev_space != wrt_space) {
     // If we have a delta between the previous position and the
     // If we have a delta between the previous position and the
@@ -439,13 +440,15 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
       // at the point along its path that is closest to intersecting
       // at the point along its path that is closest to intersecting
       // the plane.  This may be the actual intersection point, or it
       // the plane.  This may be the actual intersection point, or it
       // may be the starting point or the final point.
       // may be the starting point or the final point.
-      float t = -(dist_to_plane(a) / dot);
+      t = -(dist_to_plane(a) / dot);
       if (t >= 1.0f) {
       if (t >= 1.0f) {
         // Leave it where it is.
         // Leave it where it is.
+        t = 1.0f;
 
 
       } else if (t < 0.0f) {
       } else if (t < 0.0f) {
         from_center = a;
         from_center = a;
         moved_from_center = true;
         moved_from_center = true;
+        t = 0.0f;
 
 
       } else {
       } else {
         from_center = a + t * delta;
         from_center = a + t * delta;
@@ -556,6 +559,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   new_entry->set_surface_normal(normal);
   new_entry->set_surface_normal(normal);
   new_entry->set_surface_point(from_center - normal * dist);
   new_entry->set_surface_point(from_center - normal * dist);
   new_entry->set_interior_point(from_center - normal * (dist + into_depth));
   new_entry->set_interior_point(from_center - normal * (dist + into_depth));
+  new_entry->set_t(t);
 
 
   return new_entry;
   return new_entry;
 }
 }

+ 1 - 0
panda/src/collide/collisionSolid.h

@@ -178,6 +178,7 @@ private:
   friend class CollisionLine;
   friend class CollisionLine;
   friend class CollisionRay;
   friend class CollisionRay;
   friend class CollisionSegment;
   friend class CollisionSegment;
+  friend class CollisionHandlerFluidPusher;
 };
 };
 
 
 INLINE ostream &operator << (ostream &out, const CollisionSolid &cs) {
 INLINE ostream &operator << (ostream &out, const CollisionSolid &cs) {

+ 1 - 0
panda/src/collide/collisionTraverser.cxx

@@ -288,6 +288,7 @@ traverse(const NodePath &root) {
   
   
   Handlers::iterator hi;
   Handlers::iterator hi;
   for (hi = _handlers.begin(); hi != _handlers.end(); ++hi) {
   for (hi = _handlers.begin(); hi != _handlers.end(); ++hi) {
+    (*hi).first->set_root(root);
     (*hi).first->begin_group();
     (*hi).first->begin_group();
   }
   }
 
 

+ 1 - 0
panda/src/collide/collisionTube.cxx

@@ -213,6 +213,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
     into_intersection_point = from_a + t1 * from_direction;
     into_intersection_point = from_a + t1 * from_direction;
   }
   }
   set_intersection_point(new_entry, into_intersection_point, from_radius);
   set_intersection_point(new_entry, into_intersection_point, from_radius);
+  new_entry->set_t(t1);
 
 
   return new_entry;
   return new_entry;
 }
 }