2
0
Эх сурвалжийг харах

*** empty log message ***

David Rose 25 жил өмнө
parent
commit
4bb778c586

+ 4 - 1
panda/src/collide/Sources.pp

@@ -20,7 +20,9 @@
     collisionNode.cxx collisionNode.h collisionPlane.I \
     collisionPlane.cxx collisionPlane.h collisionPolygon.I \
     collisionPolygon.cxx collisionPolygon.h collisionRay.I \
-    collisionRay.cxx collisionRay.h collisionSolid.I collisionSolid.cxx \
+    collisionRay.cxx collisionRay.h collisionSegment.I \
+    collisionSegment.cxx collisionSegment.h \
+    collisionSolid.I collisionSolid.cxx \
     collisionSolid.h collisionSphere.I collisionSphere.cxx \
     collisionSphere.h collisionTraverser.I collisionTraverser.cxx \
     collisionTraverser.h config_collide.cxx config_collide.h
@@ -34,6 +36,7 @@
     collisionHandlerQueue.h collisionLevelState.I collisionLevelState.h \
     collisionNode.I collisionNode.h collisionPlane.I collisionPlane.h \
     collisionPolygon.I collisionPolygon.h collisionRay.I collisionRay.h \
+    collisionSegment.I collisionSegment.h \
     collisionSolid.I collisionSolid.h collisionSphere.I \
     collisionSphere.h collisionTraverser.I collisionTraverser.h
 

+ 51 - 0
panda/src/collide/collisionPolygon.cxx

@@ -8,6 +8,7 @@
 #include "collisionEntry.h"
 #include "collisionSphere.h"
 #include "collisionRay.h"
+#include "collisionSegment.h"
 #include "config_collide.h"
 
 #include <boundingSphere.h>
@@ -342,6 +343,56 @@ test_intersection_from_ray(CollisionHandler *record,
   return 1;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionPolygon::test_intersection_from_segment
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+int CollisionPolygon::
+test_intersection_from_segment(CollisionHandler *record,
+			       const CollisionEntry &entry) const {
+  if (_points.size() < 3) {
+    return 0;
+  }
+
+  const CollisionSegment *segment;
+  DCAST_INTO_R(segment, entry.get_from(), 0);
+
+  LPoint3f from_a = segment->get_point_a() * entry.get_wrt_space();
+  LPoint3f from_b = segment->get_point_b() * entry.get_wrt_space();
+  LPoint3f from_direction = from_b - from_a;
+
+  float t;
+  if (!get_plane().intersects_line(t, from_a, from_direction)) {
+    // No intersection.
+    return 0;
+  }
+
+  if (t < 0.0 || t > 1.0) { 
+    // The intersection point is before the start of the segment or
+    // after the end of the segment.
+    return 0;
+  }
+
+  LPoint3f plane_point = from_a + t * from_direction;
+  if (!is_inside(to_2d(plane_point))) {
+    // Outside the polygon's perimeter.
+    return 0;
+  }
+
+  if (collide_cat.is_debug()) {
+    collide_cat.debug()
+      << "intersection detected from " << *entry.get_from_node() << " into " 
+      << *entry.get_into_node() << "\n";
+  }
+  PT(CollisionEntry) new_entry = new CollisionEntry(entry);
+
+  new_entry->set_into_intersection_point(plane_point);
+
+  record->add_entry(new_entry);
+  return 1;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionPolygon::recompute_viz
 //       Access: Public, Virtual

+ 3 - 0
panda/src/collide/collisionPolygon.h

@@ -56,6 +56,9 @@ protected:
   virtual int
   test_intersection_from_ray(CollisionHandler *record,
 			     const CollisionEntry &entry) const;
+  virtual int
+  test_intersection_from_segment(CollisionHandler *record,
+				 const CollisionEntry &entry) const;
 
   virtual void recompute_viz(Node *parent);
 

+ 119 - 0
panda/src/collide/collisionSegment.I

@@ -0,0 +1,119 @@
+// Filename: collisionSegment.I
+// Created by:  drose (30Jan01)
+// 
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::Default Constructor
+//       Access: Public
+//  Description: Creates an invalid segment.  This isn't terribly useful;
+//               it's expected that the user will subsequently adjust
+//               the segment via set_origin()/set_direction() or
+//               set_projection().
+////////////////////////////////////////////////////////////////////
+INLINE CollisionSegment::
+CollisionSegment() :
+  _a(LPoint3f(0.0, 0.0, 0.0)), 
+  _b(LPoint3f(0.0, 0.0, 0.0)) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CollisionSegment::
+CollisionSegment(const LPoint3f &a, const LPoint3f &b) :
+  _a(a), _b(b) 
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CollisionSegment::
+CollisionSegment(float ax, float ay, float az,
+		 float bx, float by, float bz) :
+  _a(ax, ay, az), _b(bx, by, bz)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE CollisionSegment::
+CollisionSegment(const CollisionSegment &copy) :
+  CollisionSolid(copy),
+  _a(copy._a), 
+  _b(copy._b)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::set_point_a
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionSegment::
+set_point_a(const LPoint3f &a) {
+  _a = a;
+  mark_bound_stale();
+  mark_viz_stale();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::set_point_a
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionSegment::
+set_point_a(float x, float y, float z) {
+  set_point_a(LPoint3f(x, y, z));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::get_point_a
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE const LPoint3f &CollisionSegment::
+get_point_a() const {
+  return _a;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::set_point_b
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionSegment::
+set_point_b(const LPoint3f &b) {
+  _b = b;
+  mark_bound_stale();
+  mark_viz_stale();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::set_point_b
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void CollisionSegment::
+set_point_b(float x, float y, float z) {
+  set_point_b(LPoint3f(x, y, z));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::get_point_b
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE const LPoint3f &CollisionSegment::
+get_point_b() const {
+  return _b;
+}

+ 111 - 0
panda/src/collide/collisionSegment.cxx

@@ -0,0 +1,111 @@
+// Filename: collisionSegment.cxx
+// Created by:  drose (30Jan01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "collisionSegment.h"
+#include "collisionHandler.h"
+#include "collisionEntry.h"
+#include "config_collide.h"
+
+#include <geom.h>
+#include <geomNode.h>
+#include <geomLine.h>
+#include <geometricBoundingVolume.h>
+
+TypeHandle CollisionSegment::_type_handle;
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::make_copy
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CollisionSolid *CollisionSegment::
+make_copy() {
+  return new CollisionSegment(*this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::test_intersection
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+int CollisionSegment::
+test_intersection(CollisionHandler *record, const CollisionEntry &entry,
+		  const CollisionSolid *into) const {
+  return into->test_intersection_from_segment(record, entry);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::xform
+//       Access: Public, Virtual
+//  Description: Transforms the solid by the indicated matrix.
+////////////////////////////////////////////////////////////////////
+void CollisionSegment::
+xform(const LMatrix4f &mat) {
+  _a = _a * mat;
+  _b = _b * mat;
+  clear_viz_arcs();
+  mark_bound_stale();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::output
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CollisionSegment::
+output(ostream &out) const {
+  out << "segment, a (" << _a << "), b (" << _b << ")";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::recompute_bound
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CollisionSegment::
+recompute_bound() {
+  BoundedObject::recompute_bound();
+
+  if (_bound->is_of_type(GeometricBoundingVolume::get_class_type())) {
+    GeometricBoundingVolume *gbound;
+    DCAST_INTO_V(gbound, _bound);
+
+    // This makes the assumption that _a and _b are laid out
+    // sequentially in memory.  It works because that's they way
+    // they're defined in the class.
+    nassertv(&_a + 1 == &_b);
+    gbound->around(&_a, &_b + 1);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::recompute_viz
+//       Access: Public, Virtual
+//  Description: Rebuilds the geometry that will be used to render a
+//               visible representation of the collision solid.
+////////////////////////////////////////////////////////////////////
+void CollisionSegment::
+recompute_viz(Node *parent) {
+  if (collide_cat.is_debug()) {
+    collide_cat.debug()
+      << "Recomputing viz for " << *this << " on " << *parent << "\n";
+  }
+
+  GeomLine *segment = new GeomLine;
+  PTA_Vertexf verts;
+  PTA_Colorf colors;
+  verts.push_back(_a);
+  verts.push_back(_b);
+  colors.push_back(Colorf(1.0, 1.0, 1.0, 1.0));
+  segment->set_coords(verts, G_PER_VERTEX);
+  segment->set_colors(colors, G_OVERALL);
+
+  segment->set_num_prims(1);
+
+  GeomNode *viz = new GeomNode("viz-segment");
+  viz->add_geom(segment);
+  add_other_viz(parent, viz);
+}

+ 81 - 0
panda/src/collide/collisionSegment.h

@@ -0,0 +1,81 @@
+// Filename: collisionSegment.h
+// Created by:  drose (30Jan01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef COLLISIONSEGMENT_H
+#define COLLISIONSEGMENT_H
+
+#include <pandabase.h>
+
+#include "collisionSolid.h"
+
+class ProjectionNode;
+
+///////////////////////////////////////////////////////////////////
+// 	 Class : CollisionSegment
+// Description : A finite line segment, with two specific endpoints
+//               but no thickness.  It's similar to a CollisionRay,
+//               except it does not continue to infinity.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA CollisionSegment : public CollisionSolid {
+PUBLISHED:
+  INLINE CollisionSegment();
+  INLINE CollisionSegment(const LPoint3f &a, const LPoint3f &db);
+  INLINE CollisionSegment(float ax, float ay, float az, 
+			  float bx, float by, float bz);
+
+public:
+  INLINE CollisionSegment(const CollisionSegment &copy);
+  virtual CollisionSolid *make_copy();
+
+  virtual int
+  test_intersection(CollisionHandler *record,
+		    const CollisionEntry &entry,
+		    const CollisionSolid *into) const;
+
+  virtual void xform(const LMatrix4f &mat);
+
+  virtual void output(ostream &out) const;
+
+PUBLISHED:
+  INLINE void set_point_a(const LPoint3f &a);
+  INLINE void set_point_a(float x, float y, float z);
+  INLINE const LPoint3f &get_point_a() const;
+
+  INLINE void set_point_b(const LPoint3f &b);
+  INLINE void set_point_b(float x, float y, float z);
+  INLINE const LPoint3f &get_point_b() const;
+
+protected:
+  virtual void recompute_bound();
+
+protected:
+  virtual void recompute_viz(Node *parent);
+
+private:
+  LPoint3f _a, _b;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    CollisionSolid::init_type();
+    register_type(_type_handle, "CollisionSegment",
+		  CollisionSolid::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "collisionSegment.I"
+
+#endif
+
+

+ 50 - 6
panda/src/collide/collisionSolid.cxx

@@ -6,6 +6,9 @@
 #include "collisionSolid.h"
 #include "config_collide.h"
 #include "collisionEntry.h"
+#include "collisionSphere.h"
+#include "collisionRay.h"
+#include "collisionSegment.h"
 
 #include <renderRelation.h>
 #include <geomNode.h>
@@ -93,31 +96,72 @@ write(ostream &out, int indent_level) const {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionSolid::test_intersection_from_sphere
-//       Access: Public, Virtual
+//       Access: Protected, Virtual
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 int CollisionSolid::
 test_intersection_from_sphere(CollisionHandler *,
 			      const CollisionEntry &) const {
-  collide_cat.warning()
-    << get_type() << "::test_intersection_from_sphere() called!\n";
+  report_undefined_intersection_test(CollisionSphere::get_class_type(),
+				     get_type());
   return 0;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionSolid::test_intersection_from_ray
-//       Access: Public, Virtual
+//       Access: Protected, Virtual
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 int CollisionSolid::
 test_intersection_from_ray(CollisionHandler *,
 			   const CollisionEntry &) const {
-  collide_cat.warning()
-    << get_type() << "::test_intersection_from_ray() called!\n";
+  report_undefined_intersection_test(CollisionRay::get_class_type(),
+				     get_type());
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSolid::test_intersection_from_segment
+//       Access: Protected, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+int CollisionSolid::
+test_intersection_from_segment(CollisionHandler *,
+			       const CollisionEntry &) const {
+  report_undefined_intersection_test(CollisionSegment::get_class_type(),
+				     get_type());
   return 0;
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSolid::report_undefined_intersection_test
+//       Access: Protected, Static
+//  Description: Outputs a message the first time an intersection test
+//               is attempted that isn't defined, and explains a bit
+//               about what it means.
+////////////////////////////////////////////////////////////////////
+void CollisionSolid::
+report_undefined_intersection_test(TypeHandle from_type, TypeHandle into_type) {
+#ifndef NDEBUG
+  typedef map<TypeHandle, TypeHandle> Reported;
+  static Reported reported;
+
+  if (reported.insert(Reported::value_type(from_type, into_type)).second) {
+    collide_cat.error()
+      << "Invalid attempt to detect collision from " << from_type << " into " 
+      << into_type << "!\n"
+
+      "This means that a " << from_type << " object attempted to test for a\n"
+      "intersection into a " << into_type << " object.  This intersection\n"
+      "test has not yet been defined; it is possible the " << into_type << "\n"
+      "object is not intended to be collidable.  Consider calling\n"
+      "set_into_collide_mask(0) on the " << into_type << " object, or\n"
+      "set_from_collide_mask(0) on the " << from_type << " object.\n"; 
+  }
+#endif
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionSolid::clear_viz_arcs
 //       Access: Protected

+ 10 - 2
panda/src/collide/collisionSolid.h

@@ -68,6 +68,13 @@ protected:
   virtual int
   test_intersection_from_ray(CollisionHandler *record,
 			     const CollisionEntry &entry) const;
+  virtual int
+  test_intersection_from_segment(CollisionHandler *record,
+				 const CollisionEntry &entry) const;
+
+  static void
+  report_undefined_intersection_test(TypeHandle from_type,
+				     TypeHandle into_type);
 
   INLINE void mark_viz_stale();
   void clear_viz_arcs();
@@ -109,8 +116,9 @@ public:
 private:
   static TypeHandle _type_handle;
 
-friend class CollisionSphere;
-friend class CollisionRay;
+  friend class CollisionSphere;
+  friend class CollisionRay;
+  friend class CollisionSegment;
 };
 
 INLINE ostream &operator << (ostream &out, const CollisionSolid &cs) {

+ 47 - 0
panda/src/collide/collisionSphere.cxx

@@ -5,6 +5,7 @@
 
 #include "collisionSphere.h"
 #include "collisionRay.h"
+#include "collisionSegment.h"
 #include "collisionHandler.h"
 #include "collisionEntry.h"
 #include "config_collide.h"
@@ -173,6 +174,52 @@ test_intersection_from_ray(CollisionHandler *record,
   return 1;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSphere::test_intersection_from_segment
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+int CollisionSphere::
+test_intersection_from_segment(CollisionHandler *record,
+			       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_space();
+  LVector3f from_b = segment->get_point_b() * entry.get_wrt_space();
+  LVector3f from_direction = from_b - from_a;
+
+  double t1, t2;
+  if (!intersects_line(t1, t2, from_a, from_direction)) {
+    // No intersection.
+    return 0;
+  }
+
+  if (t2 < 0.0 || t1 > 1.0) { 
+    // Both intersection points are before the start of the segment or
+    // after the end of the segment.
+    return 0;
+  }
+
+  if (collide_cat.is_debug()) {
+    collide_cat.debug()
+      << "intersection detected from " << *entry.get_from_node() << " into " 
+      << *entry.get_into_node() << "\n";
+  }
+  PT(CollisionEntry) new_entry = new CollisionEntry(entry);
+
+  LPoint3f into_intersection_point;
+  if (t1 < 0.0) {
+    into_intersection_point = from_a + t2 * from_direction;
+  } else {
+    into_intersection_point = from_b + t1 * from_direction;
+  }
+  new_entry->set_into_intersection_point(into_intersection_point);
+
+  record->add_entry(new_entry);
+  return 1;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionSphere::recompute_viz
 //       Access: Public, Virtual

+ 3 - 0
panda/src/collide/collisionSphere.h

@@ -51,6 +51,9 @@ protected:
   virtual int
   test_intersection_from_ray(CollisionHandler *record,
 			     const CollisionEntry &entry) const;
+  virtual int
+  test_intersection_from_segment(CollisionHandler *record,
+				 const CollisionEntry &entry) const;
 
   virtual void recompute_viz(Node *parent);
 

+ 38 - 18
panda/src/collide/config_collide.cxx

@@ -4,19 +4,20 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "config_collide.h"
-#include "collisionNode.h"
-#include "collisionSolid.h"
-#include "collisionSphere.h"
-#include "collisionPlane.h"
-#include "collisionPolygon.h"
-#include "collisionRay.h"
 #include "collisionEntry.h"
 #include "collisionHandler.h"
 #include "collisionHandlerEvent.h"
+#include "collisionHandlerFloor.h"
 #include "collisionHandlerPhysical.h"
 #include "collisionHandlerPusher.h"
-#include "collisionHandlerFloor.h"
 #include "collisionHandlerQueue.h"
+#include "collisionNode.h"
+#include "collisionPlane.h"
+#include "collisionPolygon.h"
+#include "collisionRay.h"
+#include "collisionSegment.h"
+#include "collisionSolid.h"
+#include "collisionSphere.h"
 
 #include <dconfig.h>
 
@@ -24,11 +25,39 @@ Configure(config_collide);
 NotifyCategoryDef(collide, "");
 
 ConfigureFn(config_collide) {
+  init_libcollide();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: init_libcollide
+//  Description: Initializes the library.  This must be called at
+//               least once before any of the functions or classes in
+//               this library can be used.  Normally it will be
+//               called by the static initializers and need not be
+//               called explicitly, but special cases exist.
+////////////////////////////////////////////////////////////////////
+void
+init_libcollide() {
+  static bool initialized = false;
+  if (initialized) {
+    return;
+  }
+  initialized = true;
+
+  CollisionEntry::init_type();
+  CollisionHandler::init_type();
+  CollisionHandlerEvent::init_type();
+  CollisionHandlerFloor::init_type();
+  CollisionHandlerPhysical::init_type();
+  CollisionHandlerPusher::init_type();
+  CollisionHandlerQueue::init_type();
   CollisionNode::init_type();
-  CollisionSolid::init_type();
-  CollisionSphere::init_type();
   CollisionPlane::init_type();
   CollisionPolygon::init_type();
+  CollisionRay::init_type();
+  CollisionSegment::init_type();
+  CollisionSolid::init_type();
+  CollisionSphere::init_type();
 
   //Registration of writeable object's creation
   //functions with BamReader's factory
@@ -36,13 +65,4 @@ ConfigureFn(config_collide) {
   CollisionPlane::register_with_read_factory();
   CollisionPolygon::register_with_read_factory();
   CollisionSphere::register_with_read_factory();
-  CollisionRay::init_type();
-  CollisionEntry::init_type();
-  CollisionHandler::init_type();
-  CollisionHandlerEvent::init_type();
-  CollisionHandlerPhysical::init_type();
-  CollisionHandlerPusher::init_type();
-  CollisionHandlerFloor::init_type();
-  CollisionHandlerQueue::init_type();
 }
-

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

@@ -11,4 +11,6 @@
 
 NotifyCategoryDecl(collide, EXPCL_PANDA, EXPTP_PANDA);
 
+extern EXPCL_PANDA void init_libcollide();
+
 #endif