Browse Source

*** empty log message ***

David Rose 25 years ago
parent
commit
5314de5926

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

@@ -67,6 +67,11 @@ make_copy() {
 //  Description: Verifies that the indicated set of points will define
 //  Description: Verifies that the indicated set of points will define
 //               a valid CollisionPolygon: that is, at least three
 //               a valid CollisionPolygon: that is, at least three
 //               non-collinear points, with no points repeated.
 //               non-collinear points, with no points repeated.
+//
+//               This does not check that the polygon defined is
+//               convex; that check is made later, once we have
+//               projected the points to 2-d space where the decision
+//               is easier.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool CollisionPolygon::
 bool CollisionPolygon::
 verify_points(const LPoint3f *begin, const LPoint3f *end) {
 verify_points(const LPoint3f *begin, const LPoint3f *end) {
@@ -477,6 +482,47 @@ is_inside(const LPoint2f &p) const {
 
 
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionPolygon::is_concave
+//       Access: Private
+//  Description: Returns true if the CollisionPolygon is concave
+//               (which is an error), or false otherwise.
+////////////////////////////////////////////////////////////////////
+bool CollisionPolygon::
+is_concave() const {
+  nassertr(_points.size() >= 3, true);
+
+  LPoint2f p0 = _points[0];
+  LPoint2f p1 = _points[1];
+  float dx1 = p1[0] - p0[0];
+  float dy1 = p1[1] - p0[1];
+  p0 = p1;
+  p1 = _points[2];
+
+  float dx2 = p1[0] - p0[0];
+  float dy2 = p1[1] - p0[1];
+  int asum = ((dx1 * dy2 - dx2 * dy1 >= 0.0) ? 1 : 0);
+
+  for (size_t i = 0; i < _points.size() - 1; i++) {
+    p0 = p1;
+    p1 = _points[(i+3) % _points.size()];
+
+    dx1 = dx2;
+    dy1 = dy2;
+    dx2 = p1[0] - p0[0];
+    dy2 = p1[1] - p0[1];
+    int csum = ((dx1 * dy2 - dx2 * dy1 >= 0.0) ? 1 : 0);
+
+    if (csum ^ asum) {
+      // Oops, the polygon is concave.
+      return true;
+    }
+  }
+
+  // The polygon is safely convex.
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CollisionPolygon::setup_points
 //     Function: CollisionPolygon::setup_points
 //       Access: Private
 //       Access: Private
@@ -587,6 +633,20 @@ setup_points(const LPoint3f *begin, const LPoint3f *end) {
     _median += _points[n];
     _median += _points[n];
   }
   }
   _median /= _points.size();
   _median /= _points.size();
+
+#ifndef NDEBUG
+  // Now make sure the points define a convex polygon.
+  if (is_concave()) {
+    collide_cat.error() << "Invalid concave CollisionPolygon defined:\n";
+    const LPoint3f *pi;
+    for (pi = begin; pi != end; ++pi) {
+      collide_cat.error(false) << "  " << (*pi) << "\n";
+    }
+    collide_cat.error(false) 
+      << "  normal " << normal << " with length " << normal.length() << "\n";
+    _points.clear();
+  }
+#endif
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

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

@@ -65,6 +65,7 @@ protected:
 
 
 private:
 private:
   bool is_inside(const LPoint2f &p) const;
   bool is_inside(const LPoint2f &p) const;
+  bool is_concave() const;
 
 
   void setup_points(const LPoint3f *begin, const LPoint3f *end);
   void setup_points(const LPoint3f *begin, const LPoint3f *end);
   LPoint2f to_2d(const LPoint3f &point3d) const;
   LPoint2f to_2d(const LPoint3f &point3d) const;

+ 1 - 1
panda/src/egg/eggPolygon.I

@@ -74,6 +74,6 @@ recompute_polygon_normal() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool EggPolygon::
 INLINE bool EggPolygon::
 triangulate_into(EggGroupNode *container, bool convex_also) const {
 triangulate_into(EggGroupNode *container, bool convex_also) const {
-  EggPolygon *copy = new EggPolygon(*this);
+  PT(EggPolygon) copy = new EggPolygon(*this);
   return copy->triangulate_poly(container, convex_also);
   return copy->triangulate_poly(container, convex_also);
 }
 }

+ 4 - 0
panda/src/egg/eggPolygon.cxx

@@ -307,6 +307,10 @@ decomp_concave(EggGroupNode *container, int asum, int x, int y) const {
 //               otherwise, only concave polygons will be subdivided,
 //               otherwise, only concave polygons will be subdivided,
 //               and convex polygons will be copied unchanged into the
 //               and convex polygons will be copied unchanged into the
 //               container.
 //               container.
+//
+//               It is assumed that the EggPolygon is not already a
+//               child of any other group when this function is
+//               called.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool EggPolygon::
 bool EggPolygon::
 triangulate_poly(EggGroupNode *container, bool convex_also) {
 triangulate_poly(EggGroupNode *container, bool convex_also) {

+ 1 - 0
panda/src/egg2sg/eggLoader.cxx

@@ -1818,6 +1818,7 @@ create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly,
 			  EggGroup::CollideFlags flags) {
 			  EggGroup::CollideFlags flags) {
 
 
   PT(EggGroup) group = new EggGroup;
   PT(EggGroup) group = new EggGroup;
+
   if (!egg_poly->triangulate_into(group, false)) {
   if (!egg_poly->triangulate_into(group, false)) {
     egg2sg_cat.warning()
     egg2sg_cat.warning()
       << "Degenerate collision polygon in " << parent_group->get_name()
       << "Degenerate collision polygon in " << parent_group->get_name()