Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/nodeitems_builtins.py1
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/intern/node.c1
-rw-r--r--source/blender/nodes/CMakeLists.txt3
-rw-r--r--source/blender/nodes/NOD_geometry.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_boolean.cc150
7 files changed, 158 insertions, 0 deletions
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/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..329a9620bc5 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -27,6 +27,7 @@ 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);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 5cfc9148f34..6cff4d03d0c 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, 0, "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..129794f8175
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
@@ -0,0 +1,150 @@
+/*
+ * 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 "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+
+#include "BKE_mesh.h"
+
+#include "BLI_alloca.h"
+#include "BLI_math_matrix.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 *BM_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];
+ looptris = (BMLoop * (*)[3])(MEM_malloc_arrayN(looptris_tot, sizeof(*looptris), __func__));
+ BM_mesh_calc_tessellation_beauty(bm, looptris, &tottri);
+
+ BMIter iter;
+ int i;
+ 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). */
+
+ const short ob_src_totcol = mesh_a->totcol;
+ short *material_remap = BLI_array_alloca(material_remap, ob_src_totcol ? ob_src_totcol : 1);
+
+ BMFace *bm_face;
+ i = 0;
+ 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);
+
+ /* Remap material. */
+ if (bm_face->mat_nr < ob_src_totcol) {
+ bm_face->mat_nr = material_remap[bm_face->mat_nr];
+ }
+
+ 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;
+
+ return result;
+}
+
+// Mesh *mesh_boolean_calc(Mesh *mesh_a, Mesh *UNUSED(mesh_b), int UNUSED(boolean_mode))
+// {
+// return mesh_a;
+// }
+
+namespace blender::nodes {
+static void geo_boolean_exec(bNode *UNUSED(node), GValueByName &inputs, GValueByName &outputs)
+{
+ GeometryPtr geometry_in_a = inputs.extract<GeometryPtr>("Geometry A");
+ GeometryPtr geometry_in_b = inputs.extract<GeometryPtr>("Geometry B");
+ GeometryPtr geometry_out;
+
+ if (!geometry_in_a.has_value() || !geometry_in_b.has_value()) {
+ outputs.move_in("Geometry", std::move(geometry_out));
+ return;
+ }
+
+ Mesh *mesh_in_a = geometry_in_a->mesh_get_for_read();
+ Mesh *mesh_in_b = geometry_in_b->mesh_get_for_read();
+ if (mesh_in_a == nullptr || mesh_in_b == nullptr) {
+ outputs.move_in("Geometry", std::move(geometry_out));
+ return;
+ }
+
+ geometry_out = GeometryPtr{new Geometry()};
+
+ Mesh *mesh_out = BM_mesh_boolean_calc(mesh_in_a, mesh_in_b, eBooleanModifierOp_Difference);
+
+ geometry_out->mesh_set_and_transfer_ownership(mesh_out);
+
+ outputs.move_in("Geometry", std::move(geometry_out));
+}
+} // namespace blender::nodes
+
+void register_node_type_geo_boolean()
+{
+ static bNodeType ntype;
+
+ geo_node_type_base(&ntype, GEO_NODE_BOOLEAN, "Boolean", 0, 0);
+ node_type_socket_templates(&ntype, geo_node_boolean_in, geo_node_boolean_out);
+ ntype.geometry_node_execute = blender::nodes::geo_boolean_exec;
+ nodeRegisterType(&ntype);
+}