[Bf-blender-cvs] [ab7608af1bd] master: Apply patch D8816, from Zachary(AFWS) for collection boolean operand.

Howard Trickey noreply at git.blender.org
Sun Sep 13 23:00:14 CEST 2020


Commit: ab7608af1bd40548cb79a0312f318a32d2fe8596
Author: Howard Trickey
Date:   Sun Sep 13 16:57:27 2020 -0400
Branches: master
https://developer.blender.org/rBab7608af1bd40548cb79a0312f318a32d2fe8596

Apply patch D8816, from Zachary(AFWS) for collection boolean operand.

Also added code so that exact solver does the whole collection at once.
This patch allows users to use a collection (as an alternative to Object)
for the boolean modifier operand, and therefore get rid of a long modifier stack.

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

M	source/blender/blenlib/intern/mesh_boolean.cc
M	source/blender/blenloader/intern/versioning_290.c
M	source/blender/bmesh/tools/bmesh_boolean.cc
M	source/blender/bmesh/tools/bmesh_boolean.h
M	source/blender/editors/mesh/editmesh_intersect.c
M	source/blender/editors/sculpt_paint/paint_mask.c
M	source/blender/makesdna/DNA_modifier_types.h
M	source/blender/makesrna/intern/rna_modifier.c
M	source/blender/modifiers/intern/MOD_boolean.c

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

diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc
index e92751efe72..a6ab30a3b26 100644
--- a/source/blender/blenlib/intern/mesh_boolean.cc
+++ b/source/blender/blenlib/intern/mesh_boolean.cc
@@ -2068,11 +2068,11 @@ static bool apply_bool_op(BoolOpType bool_optype, const Array<int> &winding)
         return true;
       }
       for (int i = 1; i < nw; ++i) {
-        if (winding[i] == 0) {
-          return true;
+        if (winding[i] == 1) {
+          return false;
         }
       }
-      return false;
+      return true;
     }
     default:
       return false;
@@ -2398,8 +2398,7 @@ static IMesh gwn_boolean(const IMesh &tm,
   IMesh ans;
   Vector<Face *> out_faces;
   out_faces.reserve(tm.face_size());
-  BLI_assert(nshapes == 2); /* TODO: generalize. */
-  UNUSED_VARS_NDEBUG(nshapes);
+  Array<int> winding(nshapes, 0);
   for (int p : pinfo.index_range()) {
     const Patch &patch = pinfo.patch(p);
     /* For test triangle, choose one in the middle of patch list
@@ -2421,40 +2420,41 @@ static IMesh gwn_boolean(const IMesh &tm,
     if (dbg_level > 0) {
       std::cout << "test point = " << test_point_db << "\n";
     }
-    int other_shape = 1 - shape;
-    /* The point_is_inside_shape function has to approximate if the other
-     * shape is not PWN. For most operations, even a hint of being inside
-     * gives good results, but when shape is the cutter in a Difference
-     * operation, we want to be pretty sure that the point is inside other_shape.
-     * E.g., T75827.
-     */
-    bool need_high_confidence = (op == BoolOpType::Difference) && (shape == 1);
-    bool inside = point_is_inside_shape(
-        tm, shape_fn, test_point_db, other_shape, need_high_confidence);
-    if (dbg_level > 0) {
-      std::cout << "test point is " << (inside ? "inside\n" : "outside\n");
-    }
-    bool do_remove;
-    bool do_flip;
-    switch (op) {
-      case BoolOpType::Intersect:
-        do_remove = !inside;
-        do_flip = false;
-        break;
-      case BoolOpType::Union:
-        do_remove = inside;
-        do_flip = false;
-        break;
-      case BoolOpType::Difference:
-        do_remove = (shape == 0) ? inside : !inside;
-        do_flip = (shape == 1);
-        break;
-      default:
-        do_remove = false;
-        do_flip = false;
-        BLI_assert(false);
+    for (int other_shape = 0; other_shape < nshapes; ++other_shape) {
+      if (other_shape == shape) {
+        continue;
+      }
+      /* The point_is_inside_shape function has to approximate if the other
+       * shape is not PWN. For most operations, even a hint of being inside
+       * gives good results, but when shape is a cutter in a Difference
+       * operation, we want to be pretty sure that the point is inside other_shape.
+       * E.g., T75827.
+       */
+      bool need_high_confidence = (op == BoolOpType::Difference) && (shape != 0);
+      bool inside = point_is_inside_shape(
+          tm, shape_fn, test_point_db, other_shape, need_high_confidence);
+      if (dbg_level > 0) {
+        std::cout << "test point is " << (inside ? "inside" : "outside") << " other_shape "
+                  << other_shape << "\n";
+      }
+      winding[other_shape] = inside;
     }
+    /* Find out the "in the output volume" flag for each of the cases of winding[shape] == 0
+     * and winding[shape] == 1. If the flags are different, this patch should be in the output.
+     * Also, if this is a Difference and the shape isn't the first one, need to flip the normals.
+     */
+    winding[shape] = 0;
+    bool in_output_volume_0 = apply_bool_op(op, winding);
+    winding[shape] = 1;
+    bool in_output_volume_1 = apply_bool_op(op, winding);
+    bool do_remove = in_output_volume_0 == in_output_volume_1;
+    bool do_flip = !do_remove && op == BoolOpType::Difference && shape != 0;
     if (dbg_level > 0) {
+      std::cout << "winding = ";
+      for (int i = 0; i < nshapes; ++i) {
+        std::cout << winding[i] << " ";
+      }
+      std::cout << "\niv0=" << in_output_volume_0 << ", iv1=" << in_output_volume_1 << "\n";
       std::cout << "result for patch " << p << ": remove=" << do_remove << ", flip=" << do_flip
                 << "\n";
     }
@@ -3270,13 +3270,7 @@ IMesh boolean_trimesh(IMesh &tm_in,
   if (tm_in.face_size() == 0) {
     return IMesh(tm_in);
   }
-  IMesh tm_si;
-  if (use_self) {
-    tm_si = trimesh_self_intersect(tm_in, arena);
-  }
-  else {
-    tm_si = trimesh_nary_intersect(tm_in, nshapes, shape_fn, use_self, arena);
-  }
+  IMesh tm_si = trimesh_nary_intersect(tm_in, nshapes, shape_fn, use_self, arena);
   if (dbg_level > 1) {
     write_obj_mesh(tm_si, "boolean_tm_si");
     std::cout << "\nboolean_tm_input after intersection:\n" << tm_si;
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index b573fb28474..7805dbdcefa 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -526,19 +526,6 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
         }
       }
     }
-
-    /* Initialize solver for Boolean. */
-    if (!DNA_struct_elem_find(fd->filesdna, "BooleanModifierData", "enum", "solver")) {
-      for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
-        LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
-          if (md->type == eModifierType_Boolean) {
-            BooleanModifierData *bmd = (BooleanModifierData *)md;
-            bmd->solver = eBooleanModifierSolver_Fast;
-            bmd->flag = 0;
-          }
-        }
-      }
-    }
   }
 
   for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
@@ -597,6 +584,20 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
         }
       }
     }
+
+    /* Solver and Collections for Boolean. */
+    if (!DNA_struct_elem_find(fd->filesdna, "BooleanModifierData", "char", "solver")) {
+      for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
+        LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
+          if (md->type == eModifierType_Boolean) {
+            BooleanModifierData *bmd = (BooleanModifierData *)md;
+            bmd->solver = eBooleanModifierSolver_Fast;
+            bmd->flag = eBooleanModifierFlag_Object;
+          }
+        }
+      }
+    }
+
     /* Keep this block, even when empty. */
   }
 }
diff --git a/source/blender/bmesh/tools/bmesh_boolean.cc b/source/blender/bmesh/tools/bmesh_boolean.cc
index d2f73dd63ec..56585cb722e 100644
--- a/source/blender/bmesh/tools/bmesh_boolean.cc
+++ b/source/blender/bmesh/tools/bmesh_boolean.cc
@@ -194,6 +194,7 @@ static bool apply_mesh_output_to_bmesh(BMesh *bm, IMesh &m_out)
   /* Initially mark all existing faces as "don't keep", except hidden faces.
    * Also, save current #BMFace pointers as creating faces will disturb the table. */
   Array<BMFace *> old_bmfs(bm->totface);
+  BM_mesh_elem_index_ensure(bm, BM_FACE);
   for (int f = 0; f < bm->totface; ++f) {
     BMFace *bmf = BM_face_at_index(bm, f);
     old_bmfs[f] = bmf;
@@ -331,6 +332,7 @@ static bool bmesh_boolean(BMesh *bm,
                           const int looptris_tot,
                           int (*test_fn)(BMFace *f, void *user_data),
                           void *user_data,
+                          int nshapes,
                           const bool use_self,
                           const bool use_separate_all,
                           const BoolOpType boolean_mode)
@@ -339,10 +341,9 @@ static bool bmesh_boolean(BMesh *bm,
   IMesh m_triangulated;
   IMesh m_in = mesh_from_bm(bm, looptris, looptris_tot, &m_triangulated, &arena);
   std::function<int(int)> shape_fn;
-  int nshapes;
   if (use_self && boolean_mode == BoolOpType::None) {
     /* Unary knife operation. Want every face where test_fn doesn't return -1. */
-    nshapes = 1;
+    BLI_assert(nshapes == 1);
     shape_fn = [bm, test_fn, user_data](int f) {
       BMFace *bmf = BM_face_at_index(bm, f);
       if (test_fn(bmf, user_data) != -1) {
@@ -352,15 +353,11 @@ static bool bmesh_boolean(BMesh *bm,
     };
   }
   else {
-    nshapes = 2;
     shape_fn = [bm, test_fn, user_data](int f) {
       BMFace *bmf = BM_face_at_index(bm, f);
       int test_val = test_fn(bmf, user_data);
-      if (test_val == 0) {
-        return 0;
-      }
-      if (test_val == 1) {
-        return 1;
+      if (test_val >= 0) {
+        return test_val;
       }
       return -1;
     };
@@ -403,6 +400,7 @@ bool BM_mesh_boolean(BMesh *bm,
                      const int looptris_tot,
                      int (*test_fn)(BMFace *f, void *user_data),
                      void *user_data,
+                     const int nshapes,
                      const bool use_self,
                      const int boolean_mode)
 {
@@ -412,6 +410,7 @@ bool BM_mesh_boolean(BMesh *bm,
       looptris_tot,
       test_fn,
       user_data,
+      nshapes,
       use_self,
       false,
       static_cast<blender::meshintersect::BoolOpType>(boolean_mode));
@@ -430,6 +429,7 @@ bool BM_mesh_boolean_knife(BMesh *bm,
                            const int looptris_tot,
                            int (*test_fn)(BMFace *f, void *user_data),
                            void *user_data,
+                           const int nshapes,
                            const bool use_self,
                            const bool use_separate_all)
 {
@@ -438,6 +438,7 @@ bool BM_mesh_boolean_knife(BMesh *bm,
                                                looptris_tot,
                                                test_fn,
                                                user_data,
+                                               nshapes,
                                                use_self,
                                                use_separate_all,
                                                blender::meshintersect::BoolOpType::None);
@@ -448,6 +449,7 @@ bool BM_mesh_boolean(BMesh *UNUSED(bm),
                      const int UNUSED(looptris_tot),
           

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list