[Bf-blender-cvs] [a3f091d7ced] master: Change Exact Boolean modifier to skip round trip through BMesh.

Howard Trickey noreply at git.blender.org
Mon Feb 22 00:02:01 CET 2021


Commit: a3f091d7ceda77181422625135225e55afa612c8
Author: Howard Trickey
Date:   Sun Feb 21 17:57:03 2021 -0500
Branches: master
https://developer.blender.org/rBa3f091d7ceda77181422625135225e55afa612c8

Change Exact Boolean modifier to skip round trip through BMesh.

The Exact modifier code had been written to avoid using BMesh but
in the initial release the modifier still converted all Meshes to
BMeshes, and then after running the boolean code on the BMeshes,
converted the result back to a Mesh.
This change skips that. Most of the work here is in getting the
Custom Data layers right. The approach taken is to merge default
layers from all operand meshes into the final result, and then
use the original verts, edges, polys, and loops to copy or interpolate
the appropriate custom data layers from all operands into the result.

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

M	source/blender/blenkernel/BKE_customdata.h
A	source/blender/blenkernel/BKE_mesh_boolean_convert.h
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/blenkernel/intern/customdata.c
A	source/blender/blenkernel/intern/mesh_boolean_convert.cc
M	source/blender/blenlib/intern/mesh_boolean.cc
M	source/blender/modifiers/intern/MOD_boolean.c

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

diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 57fdafaf8d9..ed319948160 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -249,6 +249,13 @@ void CustomData_copy_data(const struct CustomData *source,
                           int source_index,
                           int dest_index,
                           int count);
+void CustomData_copy_data_layer(const CustomData *source,
+                                CustomData *dest,
+                                int src_layer_index,
+                                int dst_layer_index,
+                                int src_index,
+                                int dst_index,
+                                int count);
 void CustomData_copy_data_named(const struct CustomData *source,
                                 struct CustomData *dest,
                                 int source_index,
diff --git a/source/blender/blenkernel/BKE_mesh_boolean_convert.h b/source/blender/blenkernel/BKE_mesh_boolean_convert.h
new file mode 100644
index 00000000000..be5cbb305fa
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mesh_boolean_convert.h
@@ -0,0 +1,38 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2019 Blender Foundation.
+ * All rights reserved.
+ */
+
+#pragma once
+
+/** \file
+ * \ingroup bke
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+Mesh *BKE_mesh_boolean(const Mesh **meshes,
+                       const float (*obmats[])[4][4],
+                       const int meshes_len,
+                       const bool use_self,
+                       const int boolean_mode);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 325744f4006..1e7986eedd9 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -172,6 +172,7 @@ set(SRC
   intern/mball.c
   intern/mball_tessellate.c
   intern/mesh.c
+  intern/mesh_boolean_convert.cc
   intern/mesh_convert.c
   intern/mesh_evaluate.c
   intern/mesh_fair.cc
@@ -363,6 +364,7 @@ set(SRC
   BKE_mball.h
   BKE_mball_tessellate.h
   BKE_mesh.h
+  BKE_mesh_boolean_convert.h
   BKE_mesh_fair.h
   BKE_mesh_iterators.h
   BKE_mesh_mapping.h
@@ -728,6 +730,14 @@ if(WITH_TBB)
   )
 endif()
 
+if(WITH_GMP)
+  add_definitions(-DWITH_GMP)
+
+  list(APPEND INC_SYS
+    ${GMP_INCLUDE_DIRS}
+  )
+ endif()
+
 # # Warnings as errors, this is too strict!
 # if(MSVC)
 #    string(APPEND CMAKE_C_FLAGS " /WX")
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 9188d8c1afd..ab57676fde3 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -2881,13 +2881,13 @@ void CustomData_copy_elements(int type, void *src_data_ofs, void *dst_data_ofs,
   }
 }
 
-static void CustomData_copy_data_layer(const CustomData *source,
-                                       CustomData *dest,
-                                       int src_i,
-                                       int dst_i,
-                                       int src_index,
-                                       int dst_index,
-                                       int count)
+void CustomData_copy_data_layer(const CustomData *source,
+                                CustomData *dest,
+                                int src_i,
+                                int dst_i,
+                                int src_index,
+                                int dst_index,
+                                int count)
 {
   const LayerTypeInfo *typeInfo;
 
diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
new file mode 100644
index 00000000000..807bb3534f6
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
@@ -0,0 +1,834 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_boolean_convert.h"
+
+#include "BLI_alloca.h"
+#include "BLI_float2.hh"
+#include "BLI_math.h"
+#include "BLI_mesh_boolean.hh"
+#include "BLI_mesh_intersect.hh"
+#include "BLI_span.hh"
+
+namespace blender::meshintersect {
+
+#ifdef WITH_GMP
+
+constexpr int estimated_max_facelen = 100; /* Used for initial size of some Vectors. */
+
+/* Snap entries that are near 0 or 1 or -1 to those values.
+ * Sometimes Blender's rotation matrices for multiples of 90 degrees have
+ * tiny numbers where there should be zeros. That messes makes some things
+ * every so slightly non-coplanar when users expect coplanarity,
+ * so this is a hack to clean up such matrices.
+ * Would be better to change the transformation code itself.
+ */
+static void clean_obmat(float cleaned[4][4], const float mat[4][4])
+{
+  const float fuzz = 1e-6f;
+  for (int i = 0; i < 4; i++) {
+    for (int j = 0; j < 4; j++) {
+      float f = mat[i][j];
+      if (fabsf(f) <= fuzz) {
+        f = 0.0f;
+      }
+      else if (fabsf(f - 1.0f) <= fuzz) {
+        f = 1.0f;
+      }
+      else if (fabsf(f + 1.0f) <= fuzz) {
+        f = -1.0f;
+      }
+      cleaned[i][j] = f;
+    }
+  }
+}
+
+/* Need to wrap this in a class to use it in an Array. */
+class TransMat {
+ public:
+  float mat[4][4];
+};
+
+/* `MeshesToIMeshInfo` keeps track of information used when combining a number
+ * of `Mesh`es into a single `IMesh` for doing boolean on.
+ * Mostly this means keeping track of the index offsets for various mesh elements. */
+class MeshesToIMeshInfo {
+ public:
+  /* The input meshes, */
+  Span<const Mesh *> meshes;
+  /* Numbering the vertices of the meshes in order of meshes,
+   * at what offset does the vertex range for mesh[i] start? */
+  Array<int> mesh_vert_offset;
+  /* Similarly for edges of meshes. */
+  Array<int> mesh_edge_offset;
+  /* Similarly for polys of meshes. */
+  Array<int> mesh_poly_offset;
+  /* For each Mesh vertex in all the meshes (with concatenated indexing),
+   * what is the IMesh Vert* allocated for it in the intput IMesh? */
+  Array<const Vert *> mesh_to_imesh_vert;
+  /* Similarly for each Mesh poly. */
+  Array<Face *> mesh_to_imesh_face;
+  /* Transformation matrix to transform a coordinate in the corresponding
+   * Mesh to the local space of the first Mesh. */
+  Array<TransMat> to_obj0;
+  /* Total number of input mesh vertices. */
+  int tot_meshes_verts;
+  /* Total number of input mesh edges. */
+  int tot_meshes_edges;
+  /* Total number of input mesh polys. */
+  int tot_meshes_polys;
+
+  int input_mesh_for_imesh_vert(int imesh_v) const;
+  int input_mesh_for_imesh_edge(int imesh_e) const;
+  int input_mesh_for_imesh_face(int imesh_f) const;
+  const MPoly *input_mpoly_for_orig_index(int orig_index,
+                                          const Mesh **r_orig_mesh,
+                                          int *r_orig_mesh_index,
+                                          int *r_index_in_orig_mesh) const;
+  const MVert *input_mvert_for_orig_index(int orig_index,
+                                          const Mesh **r_orig_mesh,
+                                          int *r_index_in_orig_mesh) const;
+  const MEdge *input_medge_for_orig_index(int orig_index,
+                                          const Mesh **r_orig_mesh,
+                                          int *r_index_in_orig_mesh) const;
+};
+
+/* Given an index `imesh_v` in the `IMesh`, return the index of the
+ * input `Mesh` that contained the `MVert` that it came from. */
+int MeshesToIMeshInfo::input_mesh_for_imesh_vert(int imesh_v) const
+{
+  int n = static_cast<int>(mesh_vert_offset.size());
+  for (int i = 0; i < n - 1; ++i) {
+    if (imesh_v < mesh_vert_offset[i + 1]) {
+      return i;
+    }
+  }
+  return n - 1;
+}
+
+/* Given an index `imesh_e` used as an original index in the `IMesh`,
+ * return the index of the input `Mesh` that contained the `MVert` that it came from. */
+int MeshesToIMeshInfo::input_mesh_for_imesh_edge(int imesh_e) const
+{
+  int n = static_cast<int>(mesh_edge_offset.size());
+  for (int i = 0; i < n - 1; ++i) {
+    if (imesh_e < mesh_edge_offset[i + 1]) {
+      return i;
+    }
+  }
+  return n - 1;
+}
+
+/* Given an index `imesh_f` in the `IMesh`, return the index of the
+ * input `Mesh` that contained the `MPoly` that it came from. */
+int MeshesToIMeshInfo::input_mesh_for_imesh_face(int imesh_f) const
+{
+  int n = static_cas

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list