From abf30007abdac2a5bf3a12c90649a42294aad660 Mon Sep 17 00:00:00 2001 From: Johnny Matthews Date: Sun, 23 Jan 2022 13:27:53 -0600 Subject: Geometry Nodes: Triangulate Node - Add Selection Input This adds a selection field input to the node, faces that are selected and meet the minimum vertex count threshold will be triangulated. Differential Revision: https://developer.blender.org/D13804 --- source/blender/modifiers/intern/MOD_triangulate.c | 16 ++---- .../nodes/geometry/nodes/node_geo_triangulate.cc | 63 +++++++++++++++++----- 2 files changed, 55 insertions(+), 24 deletions(-) (limited to 'source') diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index 52d5f3e97ef..b713df05b80 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -48,17 +48,11 @@ #include "MOD_modifiertypes.h" #include "MOD_ui_common.h" -Mesh *triangulate_mesh(Mesh *mesh, - const int quad_method, - const int ngon_method, - const int min_vertices, - const int flag); - -Mesh *triangulate_mesh(Mesh *mesh, - const int quad_method, - const int ngon_method, - const int min_vertices, - const int flag) +static Mesh *triangulate_mesh(Mesh *mesh, + const int quad_method, + const int ngon_method, + const int min_vertices, + const int flag) { Mesh *result; BMesh *bm; diff --git a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc index 998e4d58bf3..e78c4d7bc35 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc @@ -14,24 +14,25 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "BKE_customdata.h" +#include "BKE_mesh.h" + +#include "bmesh.h" +#include "bmesh_tools.h" + +#include "DNA_mesh_types.h" + #include "UI_interface.h" #include "UI_resources.h" #include "node_geometry_util.hh" -extern "C" { -Mesh *triangulate_mesh(Mesh *mesh, - const int quad_method, - const int ngon_method, - const int min_vertices, - const int flag); -} - namespace blender::nodes::node_geo_triangulate_cc { static void node_declare(NodeDeclarationBuilder &b) { b.add_input(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH); + b.add_input(N_("Selection")).default_value(true).supports_field().hide_value(); b.add_input(N_("Minimum Vertices")).default_value(4).min(4).max(10000); b.add_output(N_("Mesh")); } @@ -48,9 +49,35 @@ static void geo_triangulate_init(bNodeTree *UNUSED(ntree), bNode *node) node->custom2 = GEO_NODE_TRIANGULATE_NGON_BEAUTY; } +static Mesh *triangulate_mesh_selection(const Mesh &mesh, + const int quad_method, + const int ngon_method, + const IndexMask selection, + const int min_vertices) +{ + CustomData_MeshMasks cd_mask_extra = { + CD_MASK_ORIGINDEX, CD_MASK_ORIGINDEX, 0, CD_MASK_ORIGINDEX}; + BMeshCreateParams create_params{0}; + BMeshFromMeshParams from_mesh_params{true, 1, 1, 1, cd_mask_extra}; + BMesh *bm = BKE_mesh_to_bmesh_ex(&mesh, &create_params, &from_mesh_params); + + /* Tag faces to be triangulated from the selection mask. */ + BM_mesh_elem_table_ensure(bm, BM_FACE); + for (int i_face : selection) { + BM_elem_flag_set(BM_face_at_index(bm, i_face), BM_ELEM_TAG, true); + } + + BM_mesh_triangulate(bm, quad_method, ngon_method, min_vertices, true, NULL, NULL, NULL); + Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, &cd_mask_extra, &mesh); + BM_mesh_free(bm); + BKE_mesh_normals_tag_dirty(result); + return result; +} + static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Mesh"); + Field selection_field = params.extract_input>("Selection"); const int min_vertices = std::max(params.extract_input("Minimum Vertices"), 4); GeometryNodeTriangulateQuads quad_method = static_cast( @@ -59,12 +86,22 @@ static void node_geo_exec(GeoNodeExecParams params) params.node().custom2); geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { - /* #triangulate_mesh might modify the input mesh currently. */ - Mesh *mesh_in = geometry_set.get_mesh_for_write(); - if (mesh_in != nullptr) { - Mesh *mesh_out = triangulate_mesh(mesh_in, quad_method, ngon_method, min_vertices, 0); - geometry_set.replace_mesh(mesh_out); + if (!geometry_set.has_mesh()) { + return; } + GeometryComponent &component = geometry_set.get_component_for_write(); + const Mesh &mesh_in = *geometry_set.get_mesh_for_read(); + + const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_FACE); + GeometryComponentFieldContext context{component, ATTR_DOMAIN_FACE}; + FieldEvaluator evaluator{context, domain_size}; + evaluator.add(selection_field); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_as_mask(0); + + Mesh *mesh_out = triangulate_mesh_selection( + mesh_in, quad_method, ngon_method, selection, min_vertices); + geometry_set.replace_mesh(mesh_out); }); params.set_output("Mesh", std::move(geometry_set)); -- cgit v1.2.3