[Bf-blender-cvs] [2307f4f05d1] newboolean: More boolean tests pass.

Howard Trickey noreply at git.blender.org
Sat Jun 13 17:12:15 CEST 2020


Commit: 2307f4f05d1758d67612fad8e1e177115113ecd9
Author: Howard Trickey
Date:   Sat Jun 13 11:11:02 2020 -0400
Branches: newboolean
https://developer.blender.org/rB2307f4f05d1758d67612fad8e1e177115113ecd9

More boolean tests pass.

Fixed bug re confusion of how to sort triangles around an edge.
Fixed bug in first tettet test (inconsistent normals in input).

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

M	source/blender/blenlib/intern/boolean.cc
M	source/blender/bmesh/tools/bmesh_boolean.c
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 ae2fea81cb1..96e789d5d97 100644
--- a/source/blender/blenlib/intern/boolean.cc
+++ b/source/blender/blenlib/intern/boolean.cc
@@ -551,7 +551,7 @@ static int sort_tris_class(const IndexedTriangle &tri,
                            const Edge e,
                            const mpq3 *extra_coord)
 {
-  const int dbg_level = 0;
+  const int dbg_level = 1;
   if (dbg_level > 0) {
     std::cout << "classify  e = " << e << "\n";
   }
@@ -621,7 +621,7 @@ static Array<int> sort_tris_around_edge(const TriMesh &tm,
    * be only 3 or 4 - so OK to make copies of arrays instead of swapping
    * around in a single array.
    */
-  const int dbg_level = 0;
+  const int dbg_level = 2;
   if (tris.size() == 0) {
     return Array<int>();
   }
@@ -682,9 +682,9 @@ static Array<int> sort_tris_around_edge(const TriMesh &tm,
   int *p = ans.begin();
   if (tris[0] == t0) {
     p = std::copy(g1.begin(), g1.end(), p);
-    p = std::copy(g3.begin(), g3.end(), p);
+    p = std::copy(g4.begin(), g4.end(), p);
     p = std::copy(g2.begin(), g2.end(), p);
-    std::copy(g4.begin(), g4.end(), p);
+    std::copy(g3.begin(), g3.end(), p);
   }
   else {
     p = std::copy(g3.begin(), g3.end(), p);
@@ -710,7 +710,7 @@ static void find_cells_from_edge(const TriMesh &tm,
                                  CellsInfo &cinfo,
                                  const Edge e)
 {
-  const int dbg_level = 0;
+  const int dbg_level = 2;
   if (dbg_level > 0) {
     std::cout << "find_cells_from_edge " << e << "\n";
   }
@@ -755,7 +755,11 @@ static void find_cells_from_edge(const TriMesh &tm,
       cell.add_patch(r_index);
       cell.add_patch(rnext_index);
       if (dbg_level > 0) {
-        std::cout << "  assigned new cell " << c << " to both\n";
+        std::cout << "  made new cell " << c << "\n";
+        std::cout << "  p" << r_index << "." << (r_flipped ? "cell_below" : "cell_above") << " = c"
+                  << c << "\n";
+        std::cout << "  p" << rnext_index << "." << (rnext_flipped ? "cell_above" : "cell_below")
+                  << " = c" << c << "\n";
       }
     }
     else if (*r_follow_cell != -1 && *rnext_prev_cell == -1) {
@@ -763,7 +767,8 @@ static void find_cells_from_edge(const TriMesh &tm,
       *rnext_prev_cell = c;
       cinfo.cell(c).add_patch(rnext_index);
       if (dbg_level > 0) {
-        std::cout << "  assigned r_follow_cell " << c << " to other";
+        std::cout << "  p" << r_index << "." << (r_flipped ? "cell_below" : "cell_above") << " = c"
+                  << c << "\n";
       }
     }
     else if (*r_follow_cell == -1 && *rnext_prev_cell != -1) {
@@ -771,7 +776,8 @@ static void find_cells_from_edge(const TriMesh &tm,
       *r_follow_cell = c;
       cinfo.cell(c).add_patch(r_index);
       if (dbg_level > 0) {
-        std::cout << "  assigned rnext_prev_cell " << c << " to other";
+        std::cout << "  p" << rnext_index << "." << (rnext_flipped ? "cell_above" : "cwll_below")
+                  << " = c" << c << "\n";
       }
     }
     else {
@@ -894,7 +900,7 @@ static int find_ambient_cell(const TriMesh &tm,
   int dummy_index = p_sorted_dummy - sorted_tris.begin();
   int prev_tri = (dummy_index == 0) ? sorted_tris[sorted_tris.size() - 1] :
                                       sorted_tris[dummy_index - 1];
-  int next_tri = (dummy_index == static_cast<int>(sorted_tris.size())) ?
+  int next_tri = (dummy_index == static_cast<int>(sorted_tris.size() - 1)) ?
                      sorted_tris[0] :
                      sorted_tris[dummy_index + 1];
   if (dbg_level > 0) {
@@ -1136,7 +1142,23 @@ static TriMesh self_boolean(const TriMesh &tm_in, int bool_optype)
 extern "C" Boolean_trimesh_output *BLI_boolean_trimesh(const Boolean_trimesh_input *input,
                                                        int bool_optype)
 {
-  constexpr int dbg_level = 1;
+  constexpr int dbg_level = 2;
+  if (dbg_level > 0) {
+    std::cout << "BLI_BOOLEAN_TRIMESH op=";
+    switch (bool_optype) {
+      case BOOLEAN_NONE:
+        std::cout << "none\n";
+        break;
+      case BOOLEAN_ISECT:
+        std::cout << "intersect\n";
+        break;
+      case BOOLEAN_UNION:
+        std::cout << "union\n";
+        break;
+      case BOOLEAN_DIFFERENCE:
+        std::cout << "difference\n";
+    }
+  }
   blender::meshintersect::TriMesh tm_in;
   tm_in.vert = blender::Array<blender::mpq3>(input->vert_len);
   for (int v = 0; v < input->vert_len; ++v) {
@@ -1148,6 +1170,19 @@ extern "C" Boolean_trimesh_output *BLI_boolean_trimesh(const Boolean_trimesh_inp
     tm_in.tri[t] = blender::meshintersect::IndexedTriangle(
         input->tri[t][0], input->tri[t][1], input->tri[t][2], t);
   }
+  if (dbg_level > 1) {
+    std::cout << "Input:\n";
+    std::cout << tm_in.vert.size() << " verts:\n";
+    for (uint v = 0; v < tm_in.vert.size(); ++v) {
+      std::cout << v << ": " << tm_in.vert[v] << "\n";
+    }
+    std::cout << "\n" << tm_in.tri.size() << " tris:\n";
+    for (uint t = 0; t < tm_in.tri.size(); ++t) {
+      std::cout << t << ": " << tm_in.tri[t] << "\n";
+    }
+    std::cout << "\n";
+    blender::meshintersect::write_obj_trimesh(tm_in.vert, tm_in.tri, "boolean_input");
+  }
   blender::meshintersect::TriMesh tm_out = self_boolean(tm_in, bool_optype);
   if (dbg_level > 0) {
     blender::meshintersect::write_html_trimesh(
diff --git a/source/blender/bmesh/tools/bmesh_boolean.c b/source/blender/bmesh/tools/bmesh_boolean.c
index af51f8235fe..ce314dcb854 100644
--- a/source/blender/bmesh/tools/bmesh_boolean.c
+++ b/source/blender/bmesh/tools/bmesh_boolean.c
@@ -68,6 +68,25 @@ static void free_trimesh_input(Boolean_trimesh_input *in)
   MEM_freeN(in);
 }
 
+static void apply_trimesh_output_to_bmesh(BMesh *bm, Boolean_trimesh_output *out)
+{
+  /* For now, for testing, just create new BMesh elements for returned subdivided mesh. */
+  int v, t;
+
+  if (out->vert_len > 0 && out->tri_len > 0) {
+    BMVert **new_bmv = MEM_malloc_arrayN(out->vert_len, sizeof(BMVert *), __func__);
+    for (v = 0; v < out->vert_len; v++) {
+      new_bmv[v] = BM_vert_create(bm, out->vert_coord[v], NULL, BM_CREATE_NOP);
+    }
+    for (t = 0; t < out->tri_len; t++) {
+      BMVert *v0 = new_bmv[out->tri[t][0]];
+      BMVert *v1 = new_bmv[out->tri[t][1]];
+      BMVert *v2 = new_bmv[out->tri[t][2]];
+      BM_face_create_quad_tri(bm, v0, v1, v2, NULL, NULL, BM_CREATE_NOP);
+    }
+  }
+}
+
 bool BM_mesh_boolean(BMesh *bm,
                      struct BMLoop *(*looptris)[3],
                      const int looptris_tot,
@@ -81,9 +100,11 @@ bool BM_mesh_boolean(BMesh *bm,
       bm, looptris, looptris_tot, test_fn, user_data);
   Boolean_trimesh_output *out = BLI_boolean_trimesh(in, boolean_mode);
   BLI_assert(out != NULL);
+  bool intersections_found = out->vert_len != in->vert_len || out->tri_len != in->tri_len;
+  apply_trimesh_output_to_bmesh(bm, out);
   free_trimesh_input(in);
   BLI_boolean_trimesh_free(out);
-  return false;
+  return intersections_found;
 }
 
 bool BM_mesh_boolean_knife(BMesh *bm,
@@ -94,27 +115,13 @@ bool BM_mesh_boolean_knife(BMesh *bm,
                            const bool UNUSED(use_self),
                            const bool UNUSED(use_separate_all))
 {
-  int v, t;
-
   Boolean_trimesh_input *in = trimesh_input_from_bm(
       bm, looptris, looptris_tot, test_fn, user_data);
   Boolean_trimesh_output *out = BLI_boolean_trimesh(in, BOOLEAN_NONE);
-
-  /* For now, for testing, just create new BMesh elements for returned subdivided mesh. */
-  if (out->vert_len > 0 && out->tri_len > 0) {
-    BMVert **new_bmv = MEM_malloc_arrayN(out->vert_len, sizeof(BMVert *), __func__);
-    for (v = 0; v < out->vert_len; v++) {
-      new_bmv[v] = BM_vert_create(bm, out->vert_coord[v], NULL, BM_CREATE_NOP);
-    }
-    for (t = 0; t < out->tri_len; t++) {
-      BMVert *v0 = new_bmv[out->tri[t][0]];
-      BMVert *v1 = new_bmv[out->tri[t][1]];
-      BMVert *v2 = new_bmv[out->tri[t][2]];
-      BM_face_create_quad_tri(bm, v0, v1, v2, NULL, NULL, BM_CREATE_NOP);
-    }
-  }
-
+  BLI_assert(out != NULL);
+  bool intersections_found = out->vert_len != in->vert_len || out->tri_len != in->tri_len;
+  apply_trimesh_output_to_bmesh(bm, out);
   free_trimesh_input(in);
   BLI_boolean_trimesh_free(out);
-  return false;
+  return intersections_found;
 }
diff --git a/tests/gtests/blenlib/BLI_boolean_test.cc b/tests/gtests/blenlib/BLI_boolean_test.cc
index b2b6fa308aa..dd3778d7db2 100644
--- a/tests/gtests/blenlib/BLI_boolean_test.cc
+++ b/tests/gtests/blenlib/BLI_boolean_test.cc
@@ -152,14 +152,14 @@ TEST(eboolean, TetTet)
   2.0 0.0 1.0
   1.0 2.0 1.0
   1.0 1.0 3.0
-  0 1 2
-  0 3 1
-  1 3 2
-  2 3 0
-  4 5 6
-  4 7 5
-  5 7 6
-  6 7 4
+  0 2 1
+  0 1 3
+  1 2 3
+  2 0 3
+  4 6 5
+  4 5 7
+  5 6 7
+  6 4 7
   )";
   BT_input bti(spec);
   Boolean_trimesh_output *out = BLI_boolean_trimesh(bti.input(), BOOLEAN_NONE);
@@ -178,3 +178,34 @@ TEST(eboolean, TetTet)
   }
   BLI_boolean_trimesh_free(out2);
 }
+
+TEST(eboolean, TetTet2)
+{
+  const char *spec = R"(8 8
+  0.0 1.0 -1.0
+  0.875 -0.5 -1.0
+  -0.875 -0.5 -1.0
+  0.0 0.0 1.0
+  0.0 1.0 0.0
+  0.875 -0.5 0.0
+  -0.875 -0.5 0.0
+  0.0 0.0 2.0
+  0 3 1
+  0 1 2
+  1 3 2
+  2 3 0
+  4 7 5
+  4 5 6
+  5 7 6
+  6 7 4
+  )";
+
+  BT_input bti(spec);
+  Boolean_trimesh_output *out = BLI_boolean_trimesh(bti.input(), BOOLEAN_UNION);
+  EXPECT_EQ(out->vert_len, 10);
+  EXPECT_EQ(out->tri_len, 16);
+  if (DO_OBJ) {
+    write_obj(out, "tettet2_union");
+  }
+  BLI_boolean_trimesh_free(out);
+}



More information about the Bf-blender-cvs mailing list