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