浏览代码

add is_planar

David Rose 21 年之前
父节点
当前提交
a25a78ebbc
共有 3 个文件被更改,包括 60 次插入8 次删除
  1. 1 1
      panda/src/egg/Sources.pp
  2. 57 7
      panda/src/egg/eggPolygon.cxx
  3. 2 0
      panda/src/egg/eggPolygon.h

+ 1 - 1
panda/src/egg/Sources.pp

@@ -6,7 +6,7 @@
 #begin lib_target
   #define TARGET egg
   #define LOCAL_LIBS \
-    linmath putil
+    mathutil linmath putil
     
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx 
 

+ 57 - 7
panda/src/egg/eggPolygon.cxx

@@ -18,6 +18,7 @@
 
 #include "eggPolygon.h"
 #include "eggGroupNode.h"
+#include "plane.h"
 
 #include "indent.h"
 
@@ -28,7 +29,7 @@ TypeHandle EggPolygon::_type_handle;
 
 ////////////////////////////////////////////////////////////////////
 //     Function: EggPolygon::cleanup
-//       Access: Public, Virtual
+//       Access: Published, Virtual
 //  Description: Cleans up modeling errors in whatever context this
 //               makes sense.  For instance, for a polygon, this calls
 //               remove_doubled_verts(true).  For a point, it calls
@@ -46,7 +47,7 @@ cleanup() {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: EggPolygon::calculate_normal
-//       Access: Public
+//       Access: Published
 //  Description: Calculates the true polygon normal--the vector
 //               pointing out of the front of the polygon--based on
 //               the vertices.  This does not return or change the
@@ -89,9 +90,55 @@ calculate_normal(Normald &result, CoordinateSystem cs) const {
   return true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggPolygon::is_planar
+//       Access: Published
+//  Description: Returns true if all of the polygon's vertices lie
+//               within the same plane, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool EggPolygon::
+is_planar() const {
+  Normald normal;
+  if (!calculate_normal(normal)) {
+    // A degenerate polygon--all of the vertices are within one line,
+    // or all in the same point--is technically planar.  Not sure if
+    // this is a useful return value or not.
+    return true;
+  }
+
+  // There should be at least one vertex (actually, at least three)
+  // since we have already shown that the polygon is nondegenerate.
+  nassertr(!empty(), false);
+
+  // Create a plane perpendicular to the polygon's normal, containing
+  // the first vertex.
+  const_iterator vi = begin();
+  LVecBase3d first_point = (*vi)->get_pos3();
+  Planed plane(normal, first_point);
+
+  // And check that all of the remaining vertices are sufficiently
+  // close to the plane.
+  ++vi;
+  while (vi != end()) {
+    LVecBase3d this_point = (*vi)->get_pos3();
+    if (!this_point.almost_equal(first_point)) {
+      double dist = plane.dist_to_plane(this_point);
+      double tol = dist / length(this_point - first_point);
+      if (!IS_THRESHOLD_ZERO(tol, 0.0001)) {
+        // Nope, too far away--the polygon is nonplanar.
+        return false;
+      }
+      ++vi;
+    }
+  }
+
+  // All vertices are close enough to pass.
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggPolygon::triangulate_in_place
-//       Access: Public
+//       Access: Published
 //  Description: Subdivides the polygon into triangles and adds those
 //               triangles to the parent group node in place of the
 //               original polygon.  Returns a pointer to the original
@@ -117,7 +164,7 @@ triangulate_in_place(bool convex_also) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: EggPolygon::write
-//       Access: Public, Virtual
+//       Access: Published, Virtual
 //  Description: Writes the polygon to the indicated output stream in
 //               Egg format.
 ////////////////////////////////////////////////////////////////////
@@ -417,9 +464,12 @@ triangulate_poly(EggGroupNode *container, bool convex_also) {
 
   // It's a convex polygon.
   if (!convex_also) {
-    container->add_child(this);
-
-    return true;
+    // Make sure that it's also coplanar.  If it's not, we should
+    // triangulate it anyway.
+    if (is_planar()) {
+      container->add_child(this);
+      return true;
+    }
   }
 
   v0 = 0;

+ 2 - 0
panda/src/egg/eggPolygon.h

@@ -36,6 +36,8 @@ PUBLISHED:
   virtual bool cleanup();
 
   bool calculate_normal(Normald &result, CoordinateSystem cs = CS_default) const;
+  bool is_planar() const;
+
   INLINE bool recompute_polygon_normal(CoordinateSystem cs = CS_default);
 
   INLINE bool triangulate_into(EggGroupNode *container, bool convex_also) const;