Commit: 4539f345e8fd2efd0278fb1ce7e5de1126aa93e7
Author: Howard Trickey
Date:   Wed Aug 5 15:02:21 2020 -0400
Branches: newboolean
https://developer.blender.org/rB4539f345e8fd2efd0278fb1ce7e5de1126aa93e7

Fixed bug where normals were sometimes wrong after a difference op.

Needed to check for correct orientation of a face before reusing an
original face.
Also added another test case.

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

M       source/blender/blenlib/intern/boolean.cc
M       source/blender/bmesh/tools/bmesh_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 123733a61c9..6a20ed409df 100644
--- a/source/blender/blenlib/intern/boolean.cc
+++ b/source/blender/blenlib/intern/boolean.cc
@@ -2476,6 +2476,7 @@ static Vector<Facep> merge_tris_for_face(Vector<int> tris,
         Face tryface({tri1[i1], tri1[i2], tri1[i0], tri2[j2]}, -1, -1, {}, {});
         if (tryface.cyclic_equal(*in_face)) {
           if (dbg_level > 0) {
+            std::cout << "inface = " << in_face << "\n";
             std::cout << "quad recovery worked\n";
           }
           ans.append(in_face);
@@ -2761,6 +2762,21 @@ Mesh boolean_trimesh(Mesh &tm_in,
   return tm_out;
 }
 
+static void dump_test_spec(Mesh &pm)
+{
+  std::cout << "test spec = " << pm.vert_size() << " " << pm.face_size() << 
"\n";
+  for (Vertp v : pm.vertices()) {
+    std::cout << v->co_exact[0] << " " << v->co_exact[1] << " " << 
v->co_exact[2] << " # "
+              << v->co[0] << " " << v->co[1] << " " << v->co[2] << "\n";
+  }
+  for (Facep f : pm.faces()) {
+    for (Vertp fv : *f) {
+      std::cout << pm.lookup_vert(fv) << " ";
+    }
+    std::cout << "\n";
+  }
+}
+
 /* Do the boolean operation op on the polygon mesh pm_in.
  * See the header file for a complete description.
  */
@@ -2780,6 +2796,9 @@ Mesh boolean_mesh(Mesh &pm,
     if (dbg_level > 1) {
       write_obj_mesh(pm, "boolean_mesh_in");
       std::cout << pm;
+      if (dbg_level > 2) {
+        dump_test_spec(pm);
+      }
     }
   }
   Mesh *tm_in = pm_triangulated;
diff --git a/source/blender/bmesh/tools/bmesh_boolean.cc 
b/source/blender/bmesh/tools/bmesh_boolean.cc
index c6c9dfdce56..69d8c6e6c16 100644
--- a/source/blender/bmesh/tools/bmesh_boolean.cc
+++ b/source/blender/bmesh/tools/bmesh_boolean.cc
@@ -118,6 +118,19 @@ static bool bmvert_attached_to_wire(const BMVert *bmv)
   return BM_vert_is_wire(bmv);
 }
 
+static bool face_has_verts_in_order(BMesh *bm, BMFace *bmf, const BMVert *v1, 
const BMVert *v2)
+{
+  BMIter liter;
+  BMLoop *l = static_cast<BMLoop *>(BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, 
bmf));
+  while (l != NULL) {
+    if (l->v == v1 && l->next->v == v2) {
+      return true;
+    }
+    l = static_cast<BMLoop *>(BM_iter_step(&liter));
+  }
+  return false;
+}
+
 /* Use the unused _BM_ELEM_TAG_ALT bmflag to mark geometry we will keep. */
 constexpr uint KEEP_FLAG = (1 << 6);
 
@@ -219,7 +232,10 @@ static bool apply_mesh_output_to_bmesh(BMesh *bm, Mesh 
&m_out)
       face_bmverts[i] = new_bmvs[v_index];
     }
     BMFace *bmf = BM_face_exists(face_bmverts.data(), flen);
-    if (bmf != NULL) {
+    /* BM_face_exists checks if the face exists with the vertices in either 
order.
+     * We can only reuse the face if the orientations are the same.
+     */
+    if (bmf != NULL && face_has_verts_in_order(bm, bmf, face_bmverts[0], 
face_bmverts[1])) {
       BM_elem_flag_enable(bmf, KEEP_FLAG);
     }
     else {
diff --git a/tests/gtests/blenlib/BLI_boolean_test.cc 
b/tests/gtests/blenlib/BLI_boolean_test.cc
index 3dc8a61cf3c..47c35a3ea98 100644
--- a/tests/gtests/blenlib/BLI_boolean_test.cc
+++ b/tests/gtests/blenlib/BLI_boolean_test.cc
@@ -17,7 +17,7 @@
 
 namespace blender::meshintersect {
 
-constexpr bool DO_OBJ = true;
+constexpr bool DO_OBJ = false;
 
 /* Build and hold a Mesh from a string spec. Also hold and own resources used 
by Mesh. */
 class MeshBuilder {
@@ -732,4 +732,75 @@ TEST(boolean_polymesh, CubeCyl4)
   }
 }
 
+TEST(boolean_polymesh, CubeCubesubdivDiff)
+{
+  /* A cube intersected by a subdivided cube that intersects first cubes edges 
exactly. */
+  const char *spec = R"(26 22
+  2 1/3 2
+  2 -1/3 2
+  2 -1/3 0
+  2 1/3 0
+  0 -1/3 2
+  0 1/3 2
+  0 1/3 0
+  0 -1/3 0
+  1 1/3 2
+  1 -1/3 2
+  1 1/3 0
+  1 -1/3 0
+  0 -1/3 1
+  0 1/3 1
+  2 1/3 1
+  2 -1/3 1
+  1 1/3 1
+  1 -1/3 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
+  17 9 4 12
+  13 6 7 12
+  15 2 3 14
+  11 7 6 10
+  16 13 5 8
+  9 1 0 8
+  4 9 8 5
+  14 16 8 0
+  2 11 10 3
+  15 1 9 17
+  2 15 17 11
+  3 10 16 14
+  10 6 13 16
+  1 15 14 0
+  5 13 12 4
+  11 17 12 7
+  19 21 20 18
+  21 25 24 20
+  25 23 22 24
+  23 19 18 22
+  18 20 24 22
+  23 25 21 19
+  )";
+
+  MeshBuilder mb(spec);
+  Mesh out = boolean_mesh(
+      mb.mesh,
+      BOOLEAN_DIFFERENCE,
+      2,
+      [](int t) { return t < 16 ? 1 : 0; },
+      false,
+      nullptr,
+      &mb.arena);
+  out.populate_vert();
+  EXPECT_EQ(out.vert_size(), 16);
+  EXPECT_EQ(out.face_size(), 10);
+  if (DO_OBJ) {
+    write_obj_mesh(out, "cubecubesubdivdiff");
+  }
+}
+
 }  // namespace blender::meshintersect

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

Reply via email to