[Bf-blender-cvs] [046ac5fccd7] geometry-nodes: Geometry Nodes: Initial mesh boolean node

Hans Goudey noreply at git.blender.org
Mon Oct 26 20:27:30 CET 2020


Commit: 046ac5fccd7595f6b5977e76b00edc942a345eba
Author: Hans Goudey
Date:   Mon Oct 26 14:27:19 2020 -0500
Branches: geometry-nodes
https://developer.blender.org/rB046ac5fccd7595f6b5977e76b00edc942a345eba

Geometry Nodes: Initial mesh boolean node

This uses the code from the rewritten boolean modifier from 2.91 as a node.
The implementation is about as minimal as it can get, since for now the use
case of this node is mostly to test multiple geometry outputs and inputs.

The boolean code requires a BMesh, so the node converts the input meshes
to BMesh, so the bmesh is added as a dependency to the nodes module.

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

M	release/scripts/startup/nodeitems_builtins.py
M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/node.c
M	source/blender/editors/space_node/drawnode.c
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/CMakeLists.txt
M	source/blender/nodes/NOD_geometry.h
M	source/blender/nodes/NOD_static_types.h
A	source/blender/nodes/geometry/nodes/node_geo_boolean.cc

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

diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 82a957fb118..7e79f74b022 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -489,6 +489,7 @@ geometry_node_categories = [
         NodeItem("GeometryNodeTriangulate"),
         NodeItem("GeometryNodeEdgeSplit"),
         NodeItem("GeometryNodeTransform"),
+        NodeItem("GeometryNodeBoolean"),
     ]),
     GeometryNodeCategory("GEO_MATH", "Misc", items=[
         NodeItem("ShaderNodeMapRange"),
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 0ae31989a05..4de2db44698 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1343,6 +1343,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
 #define GEO_NODE_TRIANGULATE 1000
 #define GEO_NODE_EDGE_SPLIT 1001
 #define GEO_NODE_TRANSFORM 1002
+#define GEO_NODE_BOOLEAN 1003
 
 /** \} */
 
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index f7b5e92d11b..e1be00c6a1f 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -4662,6 +4662,7 @@ static void registerGeometryNodes(void)
   register_node_type_geo_triangulate();
   register_node_type_geo_edge_split();
   register_node_type_geo_transform();
+  register_node_type_geo_boolean();
 }
 
 static void registerFunctionNodes(void)
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index b9495519427..5b381bae5dc 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -3140,8 +3140,18 @@ static void node_texture_set_butfunc(bNodeType *ntype)
 
 /* ****************** BUTTON CALLBACKS FOR GEOMETRY NODES ***************** */
 
-static void node_geometry_set_butfunc(bNodeType *UNUSED(ntype))
+static void node_geometry_buts_boolean_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
 {
+  uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE);
+}
+
+static void node_geometry_set_butfunc(bNodeType *ntype)
+{
+  switch (ntype->type) {
+    case GEO_NODE_BOOLEAN:
+      ntype->draw_buttons = node_geometry_buts_boolean_math;
+      break;
+  }
 }
 
 /* ****************** BUTTON CALLBACKS FOR FUNCTION NODES ***************** */
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index c3dbd9f7d30..4a0902913db 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1423,3 +1423,12 @@ typedef enum NodeShaderOutputTarget {
   SHD_OUTPUT_EEVEE = 1,
   SHD_OUTPUT_CYCLES = 2,
 } NodeShaderOutputTarget;
+
+/* Geometry Nodes */
+
+/* Boolean Node */
+typedef enum GeometryNodeBooleanOperation {
+  GEO_NODE_BOOLEAN_INTERSECT = 0,
+  GEO_NODE_BOOLEAN_UNION = 1,
+  GEO_NODE_BOOLEAN_DIFFERENCE = 2,
+} GeometryNodeBooleanOperation;
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 3c69db0efcc..927a2805757 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -368,6 +368,22 @@ static const EnumPropertyItem prop_shader_output_target_items[] = {
     {SHD_OUTPUT_CYCLES, "CYCLES", 0, "Cycles", "Use shaders for Cycles renderer"},
     {0, NULL, 0, NULL, NULL},
 };
+
+static const EnumPropertyItem rna_node_geometry_boolean_method_items[] = {
+    {GEO_NODE_BOOLEAN_INTERSECT,
+     "INTERSECT",
+     0,
+     "Intersect",
+     "Keep the part of the mesh that is common between all operands"},
+    {GEO_NODE_BOOLEAN_UNION, "UNION", 0, "Union", "Combine meshes in an additive way"},
+    {GEO_NODE_BOOLEAN_DIFFERENCE,
+     "DIFFERENCE",
+     0,
+     "Difference",
+     "Combine meshes in a subtractive way"},
+    {0, NULL, 0, NULL, NULL},
+};
+
 #endif
 
 #ifdef RNA_RUNTIME
@@ -8141,6 +8157,20 @@ static void def_tex_bricks(StructRNA *srna)
   RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 }
 
+/* -- Geometry Nodes --------------------------------------------------------- */
+
+static void def_geo_boolean(StructRNA *srna)
+{
+  PropertyRNA *prop;
+
+  prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE);
+  RNA_def_property_enum_sdna(prop, NULL, "custom1");
+  RNA_def_property_enum_items(prop, rna_node_geometry_boolean_method_items);
+  RNA_def_property_enum_default(prop, GEO_NODE_BOOLEAN_INTERSECT);
+  RNA_def_property_ui_text(prop, "Operation", "");
+  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
 /* -------------------------------------------------------------------------- */
 
 static void rna_def_shader_node(BlenderRNA *brna)
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index ffaabecb406..67b990d0e0f 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -29,6 +29,7 @@ set(INC
   ../blenkernel
   ../blenlib
   ../blentranslation
+  ../bmesh
   ../depsgraph
   ../functions
   ../gpu
@@ -138,6 +139,7 @@ set(SRC
   function/node_function_util.cc
 
   geometry/nodes/node_geo_common.cc
+  geometry/nodes/node_geo_boolean.cc
   geometry/nodes/node_geo_edge_split.cc
   geometry/nodes/node_geo_transform.cc
   geometry/nodes/node_geo_triangulate.cc
@@ -301,6 +303,7 @@ set(SRC
 set(LIB
   bf_functions
   bf_intern_sky
+  bf_bmesh
 )
 
 if(WITH_PYTHON)
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 27d8f3a898c..14d115e89b2 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -26,9 +26,10 @@ void register_node_tree_type_geo(void);
 
 void register_node_type_geo_group(void);
 
-void register_node_type_geo_triangulate(void);
+void register_node_type_geo_boolean(void);
 void register_node_type_geo_edge_split(void);
 void register_node_type_geo_transform(void);
+void register_node_type_geo_triangulate(void);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 5cfc9148f34..731c9f99bf1 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -269,6 +269,7 @@ DefNode(FunctionNode, FN_NODE_RANDOM_FLOAT, 0,                  "RANDOM_FLOAT",
 DefNode(GeometryNode, GEO_NODE_TRIANGULATE, 0, "TRIANGULATE", Triangulate, "Triangulate", "")
 DefNode(GeometryNode, GEO_NODE_EDGE_SPLIT, 0, "EDGE_SPLIT", EdgeSplit, "Edge Split", "")
 DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform", "")
+DefNode(GeometryNode, GEO_NODE_BOOLEAN, def_geo_boolean, "BOOLEAN", Boolean, "Boolean", "")
 
 
 /* undefine macros */
diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
new file mode 100644
index 00000000000..f37b2d6d611
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_alloca.h"
+#include "BLI_math_matrix.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+
+#include "RNA_enum_types.h"
+
+#include "BKE_mesh.h"
+
+#include "bmesh.h"
+#include "tools/bmesh_boolean.h"
+
+#include "node_geometry_util.hh"
+
+static bNodeSocketTemplate geo_node_boolean_in[] = {
+    {SOCK_GEOMETRY, N_("Geometry A")},
+    {SOCK_GEOMETRY, N_("Geometry B")},
+    {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_boolean_out[] = {
+    {SOCK_GEOMETRY, N_("Geometry")},
+    {-1, ""},
+};
+
+static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
+{
+  return BM_elem_flag_test(f, BM_ELEM_DRAW) ? 1 : 0;
+}
+
+static Mesh *mesh_boolean_calc(Mesh *mesh_a, Mesh *mesh_b, int boolean_mode)
+{
+  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh_a, mesh_b);
+
+  BMesh *bm;
+  {
+    struct BMeshCreateParams bmesh_create_params = {.use_toolflags = false};
+    bm = BM_mesh_create(&allocsize, &bmesh_create_params);
+  }
+
+  {
+    struct BMeshFromMeshParams bmesh_from_mesh_params = {.calc_face_normal = true};
+    BM_mesh_bm_from_me(bm, mesh_a, &bmesh_from_mesh_params);
+    BM_mesh_bm_from_me(bm, mesh_b, &bmesh_from_mesh_params);
+  }
+
+  const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
+  int tottri;
+  BMLoop *(*looptris)[3] = (BMLoop *
+                            (*)[3])(MEM_malloc_arrayN(looptris_tot, sizeof(*looptris), __func__));
+  BM_mesh_calc_tessellation_beauty(bm, looptris, &tottri);
+
+  const int i_faces_end = mesh_a->totpoly;
+
+  /* We need face normals because of 'BM_face_split_edgenet'
+   * we could calculate on the fly too (before calling split). */
+
+  int i = 0;
+  BMIter iter;
+  BMFace *bm_face;
+  BM_ITER_MESH (bm_face, &iter, bm, BM_FACES_OF_MESH) {
+    normalize_v3(bm_face->no);
+
+    /* Temp tag to test which side split faces are from. */
+    BM_elem_flag_enable(bm_face, BM_ELEM_DRAW);
+
+    i++;
+    if (i == i_faces_end) {
+      break;
+    }
+  }
+
+  BM_mesh_boolean(bm, looptris, tottri, bm_face_isect_pair, NULL, 2, false, boolean_mode);
+
+  Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh_a);
+  BM_mesh_free(bm);
+  result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
+  MEM_freeN(looptris);
+
+  return result;
+}
+
+namespace blender::nodes {
+static void geo_boolean_exec(bNode *node, GVa

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list