[Bf-blender-cvs] [3e30fd75ab0] newboolean: Fix bugs re triangle sorting.

Howard Trickey noreply at git.blender.org
Sun Aug 2 23:15:50 CEST 2020


Commit: 3e30fd75ab0948ba91e3651accf3b1655f2e54c0
Author: Howard Trickey
Date:   Sun Aug 2 17:13:54 2020 -0400
Branches: newboolean
https://developer.blender.org/rB3e30fd75ab0948ba91e3651accf3b1655f2e54c0

Fix bugs re triangle sorting.

Several somewhat self-compensating bugs in the routine that sorts
triangles around an edge let to a bug visible with a unit cube
subtracting a unit cylinder with 4 sides. Fixed.

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

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

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

diff --git a/source/blender/blenlib/intern/boolean.cc b/source/blender/blenlib/intern/boolean.cc
index 0072877ceee..fa8eb3e3e1d 100644
--- a/source/blender/blenlib/intern/boolean.cc
+++ b/source/blender/blenlib/intern/boolean.cc
@@ -549,6 +549,9 @@ class CellsInfo {
 
 static void merge_cells(int merge_to, int merge_from, CellsInfo &cinfo, PatchesInfo &pinfo)
 {
+  if (merge_to == merge_from) {
+    return;
+  }
   Cell &merge_from_cell = cinfo.cell(merge_from);
   Cell &merge_to_cell = cinfo.cell(merge_to);
   int final_merge_to = merge_to;
@@ -839,13 +842,14 @@ static Array<int> sort_tris_around_edge(const Mesh &tm,
     }
     std::cout << "sort_tris_around_edge " << e << "\n";
     std::cout << "tris = " << tris << "\n";
+    std::cout << "t0 = " << t0 << "\n";
   }
   Vector<int> g1{tris[0]};
   Vector<int> g2;
   Vector<int> g3;
   Vector<int> g4;
   Vector<int> *groups[] = {&g1, &g2, &g3, &g4};
-  const Face &tri0 = *tm.face(t0);
+  const Face &triref = *tm.face(tris[0]);
   for (int i : tris.index_range()) {
     if (i == 0) {
       continue;
@@ -854,9 +858,9 @@ static Array<int> sort_tris_around_edge(const Mesh &tm,
     BLI_assert(t < tm.face_size() || (t == EXTRA_TRI_INDEX && extra_tri != nullptr));
     const Face &tri = (t == EXTRA_TRI_INDEX) ? *extra_tri : *tm.face(t);
     if (dbg_level > 2) {
-      std::cout << "classifying tri " << t << " with respect to " << t0 << "\n";
+      std::cout << "classifying tri " << t << " with respect to " << tris[0] << "\n";
     }
-    int group_num = sort_tris_class(tri, tri0, e);
+    int group_num = sort_tris_class(tri, triref, e);
     if (dbg_level > 2) {
       std::cout << "  classify result : " << group_num << "\n";
     }
@@ -881,14 +885,14 @@ static Array<int> sort_tris_around_edge(const Mesh &tm,
     }
   }
   if (g3.size() > 1) {
-    Array<int> g3sorted = sort_tris_around_edge(tm, tmtopo, e, g3, g3[0], extra_tri);
+    Array<int> g3sorted = sort_tris_around_edge(tm, tmtopo, e, g3, t0, extra_tri);
     std::copy(g3sorted.begin(), g3sorted.end(), g3.begin());
     if (dbg_level > 1) {
       std::cout << "g3 sorted: " << g3 << "\n";
     }
   }
   if (g4.size() > 1) {
-    Array<int> g4sorted = sort_tris_around_edge(tm, tmtopo, e, g4, g4[0], extra_tri);
+    Array<int> g4sorted = sort_tris_around_edge(tm, tmtopo, e, g4, t0, extra_tri);
     std::copy(g4sorted.begin(), g4sorted.end(), g4.begin());
     if (dbg_level > 1) {
       std::cout << "g4 sorted: " << g4 << "\n";
@@ -987,8 +991,8 @@ static void find_cells_from_edge(const Mesh &tm,
       cell.add_patch(rnext_index);
       cell.check_for_zero_volume(pinfo, tm);
       if (dbg_level > 0) {
-        std::cout << "  p" << rnext_index << "." << (rnext_flipped ? "cell_above" : "cell_below")
-                  << " = c" << c << "\n";
+        std::cout << "  reuse r_follow: p" << rnext_index << "."
+                  << (rnext_flipped ? "cell_above" : "cell_below") << " = c" << c << "\n";
       }
     }
     else if (*r_follow_cell == NO_INDEX && *rnext_prev_cell != NO_INDEX) {
@@ -998,12 +1002,16 @@ static void find_cells_from_edge(const Mesh &tm,
       cell.add_patch(r_index);
       cell.check_for_zero_volume(pinfo, tm);
       if (dbg_level > 0) {
-        std::cout << "  p" << r_index << "." << (r_flipped ? "cell_below" : "cell_above") << " = c"
-                  << c << "\n";
+        std::cout << "  reuse rnext prev: rprev_p" << r_index << "."
+                  << (r_flipped ? "cell_below" : "cell_above") << " = c" << c << "\n";
       }
     }
     else {
       if (*r_follow_cell != *rnext_prev_cell) {
+        if (dbg_level > 0) {
+          std::cout << " merge cell " << *rnext_prev_cell << " into cell " << *r_follow_cell
+                    << "\n";
+        }
         merge_cells(*r_follow_cell, *rnext_prev_cell, cinfo, pinfo);
       }
     }
diff --git a/tests/gtests/blenlib/BLI_boolean_test.cc b/tests/gtests/blenlib/BLI_boolean_test.cc
index 3527312da20..ccd0d6d85fb 100644
--- a/tests/gtests/blenlib/BLI_boolean_test.cc
+++ b/tests/gtests/blenlib/BLI_boolean_test.cc
@@ -600,4 +600,54 @@ TEST(boolean_polymesh, CubeCubeStep)
   }
 }
 
+TEST(boolean_polymesh, CubeCyl4)
+{
+  const char *spec = R"(16 12
+  0 1 -1
+  0 1 1
+  1 0 -1
+  1 0 1
+  0 -1 -1
+  0 -1 1
+  -1 0 -1
+  -1 0 1
+  -1 -1 -1
+  -1 -1 1
+  -1 1 -1
+  -1 1 1
+  1 -1 -1
+  1 -1 1
+  1 1 -1
+  1 1 1
+  0 1 3 2
+  2 3 5 4
+  3 1 7 5
+  4 5 7 6
+  6 7 1 0
+  0 2 4 6
+  8 9 11 10
+  10 11 15 14
+  14 15 13 12
+  12 13 9 8
+  10 14 12 8
+  15 11 9 13
+  )";
+
+  MeshBuilder mb(spec);
+  Mesh out = boolean_mesh(
+      mb.mesh,
+      BOOLEAN_DIFFERENCE,
+      2,
+      [](int t) { return t < 6 ? 1 : 0; },
+      false,
+      nullptr,
+      &mb.arena);
+  out.populate_vert();
+  EXPECT_EQ(out.vert_size(), 16);
+  EXPECT_EQ(out.face_size(), 20);
+  if (DO_OBJ) {
+    write_obj_mesh(out, "cubecyl4");
+  }
+}
+
 }  // namespace blender::meshintersect



More information about the Bf-blender-cvs mailing list