diff options
Diffstat (limited to 'source/blender/nodes/geometry/nodes/node_geo_triangulate.cc')
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_triangulate.cc | 95 |
1 files changed, 67 insertions, 28 deletions
diff --git a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc index 7ef0913622c..e78c4d7bc35 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc @@ -14,29 +14,30 @@ * 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 { -namespace blender::nodes { - -static void geo_node_triangulate_declare(NodeDeclarationBuilder &b) +static void node_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Geometry>("Geometry"); - b.add_input<decl::Int>("Minimum Vertices").default_value(4).min(4).max(10000); - b.add_output<decl::Geometry>("Geometry"); + b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH); + b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value(); + b.add_input<decl::Int>(N_("Minimum Vertices")).default_value(4).min(4).max(10000); + b.add_output<decl::Geometry>(N_("Mesh")); } -static void geo_node_triangulate_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "quad_method", 0, "", ICON_NONE); uiItemR(layout, ptr, "ngon_method", 0, "", ICON_NONE); @@ -48,9 +49,35 @@ static void geo_triangulate_init(bNodeTree *UNUSED(ntree), bNode *node) node->custom2 = GEO_NODE_TRIANGULATE_NGON_BEAUTY; } -static void geo_node_triangulate_exec(GeoNodeExecParams params) +static Mesh *triangulate_mesh_selection(const Mesh &mesh, + const int quad_method, + const int ngon_method, + const IndexMask selection, + const int min_vertices) { - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + 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<GeometrySet>("Mesh"); + Field<bool> selection_field = params.extract_input<Field<bool>>("Selection"); const int min_vertices = std::max(params.extract_input<int>("Minimum Vertices"), 4); GeometryNodeTriangulateQuads quad_method = static_cast<GeometryNodeTriangulateQuads>( @@ -59,26 +86,38 @@ static void geo_node_triangulate_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<MeshComponent>(); + 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("Geometry", std::move(geometry_set)); + params.set_output("Mesh", std::move(geometry_set)); } -} // namespace blender::nodes +} // namespace blender::nodes::node_geo_triangulate_cc void register_node_type_geo_triangulate() { + namespace file_ns = blender::nodes::node_geo_triangulate_cc; + static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_TRIANGULATE, "Triangulate", NODE_CLASS_GEOMETRY, 0); - ntype.declare = blender::nodes::geo_node_triangulate_declare; - node_type_init(&ntype, blender::nodes::geo_triangulate_init); - ntype.geometry_node_execute = blender::nodes::geo_node_triangulate_exec; - ntype.draw_buttons = blender::nodes::geo_node_triangulate_layout; + geo_node_type_base(&ntype, GEO_NODE_TRIANGULATE, "Triangulate", NODE_CLASS_GEOMETRY); + ntype.declare = file_ns::node_declare; + node_type_init(&ntype, file_ns::geo_triangulate_init); + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.draw_buttons = file_ns::node_layout; nodeRegisterType(&ntype); } |