Commit: 7f5a4053f519f41becffb34e0babf0ca4ec47ad4
Author: Howard Trickey
Date:   Sun Aug 9 13:38:37 2020 -0400
Branches: newboolean
https://developer.blender.org/rB7f5a4053f519f41becffb34e0babf0ca4ec47ad4

Remove degenerate triangles before intersecting.

===================================================================

M       source/blender/blenlib/intern/mesh_intersect.cc
M       tests/gtests/blenlib/BLI_boolean_test.cc

===================================================================

diff --git a/source/blender/blenlib/intern/mesh_intersect.cc 
b/source/blender/blenlib/intern/mesh_intersect.cc
index aaa7ad2627a..cfb7af28e23 100644
--- a/source/blender/blenlib/intern/mesh_intersect.cc
+++ b/source/blender/blenlib/intern/mesh_intersect.cc
@@ -157,7 +157,14 @@ void Plane::make_canonical()
   else {
     mpq_class den = norm_exact[2];
     norm_exact = mpq3(0, 0, 1);
-    d_exact = d_exact / den;
+    if (den != 0) {
+      d_exact = d_exact / den;
+    }
+    else {
+      std::cout << "unexpected zero normal in Plane::make_canonical\n";
+      std::cout << "Plane = " << *this << "\n";
+      d_exact = 0;
+    }
   }
   norm = double3(norm_exact[0].get_d(), norm_exact[1].get_d(), 
norm_exact[2].get_d());
   d = d_exact.get_d();
@@ -2715,10 +2722,8 @@ static CoplanarClusterInfo find_clusters(const Mesh &tm, 
const Array<BoundingBox
   return ans;
 }
 
-/* Does TriMesh tm have any triangles with zero area? */
-static bool has_degenerate_tris(const Mesh &tm)
+static bool face_is_degenerate(Facep f)
 {
-  for (Facep f : tm.faces()) {
     const Face &face = *f;
     Vertp v0 = face[0];
     Vertp v1 = face[1];
@@ -2740,10 +2745,36 @@ static bool has_degenerate_tris(const Mesh &tm)
     if (ab.x == 0 && ab.y == 0 && ab.z == 0) {
       return true;
     }
+
+  return false;
+
+}
+
+/* Does TriMesh tm have any triangles with zero area? */
+static bool has_degenerate_tris(const Mesh &tm)
+{
+  for (Facep f : tm.faces()) {
+    if (face_is_degenerate(f)) {
+      return true;
+    }
   }
   return false;
 }
 
+static Mesh remove_degenerate_tris(const Mesh &tm_in)
+{
+  Mesh ans;
+  Vector<Facep> new_faces;
+  new_faces.reserve(tm_in.face_size());
+  for (Facep f : tm_in.faces()) {
+    if (!face_is_degenerate(f)) {
+      new_faces.append(f);
+    }
+  }
+  ans.set_faces(new_faces);
+  return ans;
+}
+
 /* This is the main routine for calculating the self_intersection of a 
triangle mesh. */
 Mesh trimesh_self_intersect(const Mesh &tm_in, MArena *arena)
 {
@@ -2755,7 +2786,7 @@ Mesh trimesh_nary_intersect(
     const Mesh &tm_in, int nshapes, std::function<int(int)> shape_fn, bool 
use_self, MArena *arena)
 {
   constexpr int dbg_level = 0;
-  if (dbg_level > 2) {
+  if (dbg_level > 0) {
     std::cout << "\nTRIMESH_NARY_INTERSECT nshapes=" << nshapes << " 
use_self=" << use_self
               << "\n";
     for (Facep f : tm_in.faces()) {
@@ -2769,13 +2800,21 @@ Mesh trimesh_nary_intersect(
       }
     }
   }
+  /* Usually can use tm_in but if it has degenerate or illegal triangles,
+   * then need to work on a copy of it without those triangles.
+   */
+  const Mesh *tm_clean = &tm_in;
+  Mesh tm_cleaned;
   if (has_degenerate_tris(tm_in)) {
-    std::cout << "IMPLEMENT ME - remove degenerate and illegal tris\n";
-    BLI_assert(false);
+    tm_cleaned = remove_degenerate_tris(tm_in);
+    tm_clean = &tm_cleaned;
+    if (dbg_level > 1) {
+      std::cout << "cleaned input mesh:\n" << tm_cleaned;
+    }
   }
-  Array<BoundingBox> tri_bb = calc_face_bounding_boxes(tm_in);
-  TriOverlaps tri_ov(tm_in, tri_bb, nshapes, shape_fn, use_self);
-  CoplanarClusterInfo clinfo = find_clusters(tm_in, tri_bb);
+  Array<BoundingBox> tri_bb = calc_face_bounding_boxes(*tm_clean);
+  TriOverlaps tri_ov(*tm_clean, tri_bb, nshapes, shape_fn, use_self);
+  CoplanarClusterInfo clinfo = find_clusters(*tm_clean, tri_bb);
   if (dbg_level > 1) {
     std::cout << clinfo;
   }
@@ -2787,18 +2826,18 @@ Mesh trimesh_nary_intersect(
 #  endif
   Array<CDT_data> cluster_subdivided(clinfo.tot_cluster());
   for (int c : clinfo.index_range()) {
-    cluster_subdivided[c] = calc_cluster_subdivided(clinfo, c, tm_in, arena);
+    cluster_subdivided[c] = calc_cluster_subdivided(clinfo, c, *tm_clean, 
arena);
   }
-  blender::Array<Mesh> tri_subdivided(tm_in.face_size());
-  calc_subdivided_tris(tri_subdivided, tm_in, clinfo, tri_ov, arena);
-  for (int t : tm_in.face_index_range()) {
+  blender::Array<Mesh> tri_subdivided(tm_clean->face_size());
+  calc_subdivided_tris(tri_subdivided, *tm_clean, clinfo, tri_ov, arena);
+  for (int t : tm_clean->face_index_range()) {
     int c = clinfo.tri_cluster(t);
     if (c != NO_INDEX) {
       BLI_assert(tri_subdivided[t].face_size() == 0);
-      tri_subdivided[t] = extract_subdivided_tri(cluster_subdivided[c], tm_in, 
t, arena);
+      tri_subdivided[t] = extract_subdivided_tri(cluster_subdivided[c], 
*tm_clean, t, arena);
     }
     else if (tri_subdivided[t].face_size() == 0) {
-      tri_subdivided[t] = extract_single_tri(tm_in, t);
+      tri_subdivided[t] = extract_single_tri(*tm_clean, t);
     }
   }
   Mesh combined = union_tri_subdivides(tri_subdivided);
diff --git a/tests/gtests/blenlib/BLI_boolean_test.cc 
b/tests/gtests/blenlib/BLI_boolean_test.cc
index 47c35a3ea98..474e963deeb 100644
--- a/tests/gtests/blenlib/BLI_boolean_test.cc
+++ b/tests/gtests/blenlib/BLI_boolean_test.cc
@@ -410,6 +410,42 @@ TEST(boolean_trimesh, TetBesideTetTrimesh)
   }
 }
 
+TEST(boolean_trimesh, DegenerateTris)
+{
+  const char *spec = R"(10 10
+  0 0 0
+  2 0 0
+  1 2 0
+  1 1 2
+  0 0 1
+  2 0 1
+  1 2 1
+  1 1 3
+  0 0 0
+  1 0 0
+  0 2 1
+  0 8 1
+  0 1 3
+  1 2 3
+  2 0 3
+  4 6 5
+  4 5 7
+  5 6 7
+  6 4 7
+  0 1 9
+  )";
+
+  MeshBuilder mb(spec);
+  Mesh out = boolean_trimesh(
+      mb.mesh, BOOLEAN_ISECT, 2, [](int t) { return t < 5 ? 0 : 1; }, false, 
&mb.arena);
+  out.populate_vert();
+  EXPECT_EQ(out.vert_size(), 4);
+  EXPECT_EQ(out.face_size(), 4);
+  if (DO_OBJ) {
+    write_obj_mesh(out, "degenerate_tris_tm");
+  }
+}
+
 TEST(boolean_polymesh, TetTet)
 {
   const char *spec = R"(8 8

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to