diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh.c | 75 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh.h | 8 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_node_types.h | 12 | ||||
-rw-r--r-- | source/blender/nodes/geometry/CMakeLists.txt | 3 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_collapse.cc | 103 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_dissolve.cc | 88 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_unsubdivide.cc | 67 |
7 files changed, 165 insertions, 191 deletions
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 61c5fdb75e4..b8d4210dba2 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -1364,79 +1364,4 @@ void BM_mesh_vert_coords_apply_with_mat4(BMesh *bm, mul_v3_m4v3(v->co, mat, vert_coords[i]); } } - -/** - * Use to select bmesh vertex data based on an array of bool. - */ -void BM_select_vertices(BMesh *bm, const bool *mask) -{ - BMIter iter; - BMVert *v; - int i; - BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { - BM_elem_flag_set(v, BM_ELEM_SELECT, mask[i]); - } -} - -/** - * Use to select bmesh edge data based on an array of bool. - */ -void BM_select_edges(BMesh *bm, const bool *mask) -{ - BMIter iter; - BMEdge *e; - int i; - BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { - BM_elem_flag_set(e, BM_ELEM_SELECT, mask[i]); - } -} - -/** - * Use to select bmesh face data based on an array of bool. - */ -void BM_select_faces(BMesh *bm, const bool *mask) -{ - BMIter iter; - BMFace *f; - int i; - BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { - BM_elem_flag_set(f, BM_ELEM_SELECT, mask[i]); - } -} - -void BM_tag_vertices(BMesh *bm, const bool *mask) -{ - BMIter iter; - BMVert *v; - int i; - BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { - BM_elem_flag_set(v, BM_ELEM_TAG, mask[i]); - } -} - -/** - * Use to temporary tag bmesh edge data based on an array of bool. - */ -void BM_tag_edges(BMesh *bm, const bool *mask) -{ - BMIter iter; - BMEdge *e; - int i; - BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { - BM_elem_flag_set(e, BM_ELEM_TAG, mask[i]); - } -} - -/** - * Use to temporary tag bmesh face data based on an array of bool. - */ -void BM_tag_faces(BMesh *bm, const bool *mask) -{ - BMIter iter; - BMFace *f; - int i; - BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { - BM_elem_flag_set(f, BM_ELEM_TAG, mask[i]); - } -} /** \} */ diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 3c0eb700d37..51a60aae5c9 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -217,10 +217,4 @@ float (*BM_mesh_vert_coords_alloc(BMesh *bm, int *r_vert_len))[3]; void BM_mesh_vert_coords_apply(BMesh *bm, const float (*vert_coords)[3]); void BM_mesh_vert_coords_apply_with_mat4(BMesh *bm, const float (*vert_coords)[3], - const float mat[4][4]); -void BM_select_vertices(BMesh *bm, const bool *mask); -void BM_select_edges(BMesh *bm, const bool *mask); -void BM_select_faces(BMesh *bm, const bool *mask); -void BM_tag_vertices(BMesh *bm, const bool *mask); -void BM_tag_edges(BMesh *bm, const bool *mask); -void BM_tag_faces(BMesh *bm, const bool *mask);
\ No newline at end of file + const float mat[4][4]);
\ No newline at end of file diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 127fb901270..8e6f6808d88 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -2380,6 +2380,18 @@ typedef enum GeometryNodeScaleElementsMode { GEO_NODE_SCALE_ELEMENTS_SINGLE_AXIS = 1, } GeometryNodeScaleElementsMode; +typedef enum GeometryNodeCollapseSymmetryAxis { + GEO_NODE_COLLAPSE_SYMMETRY_AXIS_NONE = -1, + GEO_NODE_COLLAPSE_SYMMETRY_AXIS_X = 0, + GEO_NODE_COLLAPSE_SYMMETRY_AXIS_Y = 1, + GEO_NODE_COLLAPSE_SYMMETRY_AXIS_Z = 2, +} GeometryNodeCollapseSymmetryAxis; + +typedef enum GeometryNodeDissolveDelimiter { + GEO_NODE_DISSOLVE_DELIMITTER_UNSELECTED = 0, + GEO_NODE_DISSOLVE_DELIMITTER_LIMIT = 1, + GEO_NODE_DISSOLVE_DELIMITTER_SELECTION_BORDER = 2, +} GeometryNodeDissolveDelimiter; #ifdef __cplusplus } #endif diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index b4add633b0c..6d33d402e4a 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -87,6 +87,7 @@ set(SRC nodes/node_geo_attribute_statistic.cc nodes/node_geo_boolean.cc nodes/node_geo_bounding_box.cc + nodes/node_geo_collapse.cc nodes/node_geo_collection_info.cc nodes/node_geo_common.cc nodes/node_geo_convex_hull.cc @@ -114,6 +115,7 @@ set(SRC nodes/node_geo_curve_to_points.cc nodes/node_geo_curve_trim.cc nodes/node_geo_delete_geometry.cc + nodes/node_geo_dissolve.cc nodes/node_geo_distribute_points_on_faces.cc nodes/node_geo_dual_mesh.cc nodes/node_geo_edge_split.cc @@ -192,6 +194,7 @@ set(SRC nodes/node_geo_transform.cc nodes/node_geo_translate_instances.cc nodes/node_geo_triangulate.cc + nodes/node_geo_unsubdivide.cc nodes/node_geo_viewer.cc nodes/node_geo_volume_to_mesh.cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_collapse.cc b/source/blender/nodes/geometry/nodes/node_geo_collapse.cc index c13ab362f17..899afcc68d3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_collapse.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_collapse.cc @@ -27,19 +27,20 @@ #include "node_geometry_util.hh" -static bNodeSocketTemplate geo_node_collapse_in[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {SOCK_FLOAT, N_("Factor"), 1.0f, 0.0f, 0.0f, 0.0f, 0, 1.0f, PROP_FACTOR}, - {SOCK_STRING, N_("Selection")}, - {-1, ""}, -}; - -static bNodeSocketTemplate geo_node_collapse_out[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {-1, ""}, -}; - -static void geo_node_collapse_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +namespace blender::nodes::node_geo_collapse { +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH); + b.add_input<decl::Float>(N_("Factor")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); + b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value(); + b.add_output<decl::Geometry>(N_("Mesh")); +} + +static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayoutSetPropSep(layout, true); uiLayoutSetPropDecorate(layout, false); @@ -55,10 +56,8 @@ static void geo_node_collapse_init(bNodeTree *UNUSED(tree), bNode *node) node_storage->symmetry_axis = GEO_NODE_COLLAPSE_SYMMETRY_AXIS_NONE; } -namespace blender::nodes { - static Mesh *collapse_mesh(const float factor, - const VArray<float> &selection, + const IndexMask selection, const bool triangulate, const int symmetry_axis, const Mesh *mesh) @@ -69,11 +68,17 @@ static Mesh *collapse_mesh(const float factor, BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmesh_create_params, &bmesh_from_mesh_params); const float symmetry_eps = 0.00002f; - Array<float> mask(selection.size()); - selection.materialize(mask); + + /* Selection (bool) is converted to float array because BM_mesh_decimate_collapse takes it this + * way. While from the description one could think that BM_mesh_decimate_collapse uses the actual + * weight, it just uses it as mask. */ + Array<float> weights(mesh->totvert); + for (int i_vert : selection) { + weights[i_vert] = 1.0f; + } BM_mesh_decimate_collapse( - bm, factor, mask.data(), 1.0f, triangulate, symmetry_axis, symmetry_eps); + bm, factor, weights.begin(), 1.0f, triangulate, symmetry_axis, symmetry_eps); Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); BM_mesh_free(bm); @@ -81,42 +86,52 @@ static Mesh *collapse_mesh(const float factor, return result; } -static void geo_node_collapse_exec(GeoNodeExecParams params) +static void node_geo_exec(GeoNodeExecParams params) { - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh"); const float factor = params.extract_input<float>("Factor"); - if (factor < 1.0f && geometry_set.has_mesh()) { - MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); - - const float default_factor = 1.0f; - GVArray_Typed<float> selection_attribute = params.get_input_attribute<float>( - "Selection", mesh_component, ATTR_DOMAIN_POINT, default_factor); - // VArray<float> selection(selection_attribute.to); - const Mesh *input_mesh = mesh_component.get_for_read(); - - const bNode &node = params.node(); - const NodeGeometryCollapse &node_storage = *(NodeGeometryCollapse *)node.storage; - Mesh *result = collapse_mesh( - factor, selection_attribute, false, node_storage.symmetry_axis, input_mesh); - geometry_set.replace_mesh(result); - } - - params.set_output("Geometry", std::move(geometry_set)); + MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); + + Field<bool> selection_field = params.extract_input<Field<bool>>("Selection"); + const int domain_size = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT); + GeometryComponentFieldContext context{mesh_component, ATTR_DOMAIN_POINT}; + FieldEvaluator evaluator{context, domain_size}; + evaluator.add(selection_field); + evaluator.evaluate(); + + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + if (geometry_set.has_mesh()) { + const Mesh *input_mesh = mesh_component.get_for_read(); + + const bNode &node = params.node(); + const NodeGeometryCollapse &node_storage = *(NodeGeometryCollapse *)node.storage; + Mesh *result = collapse_mesh(factor, + evaluator.get_evaluated_as_mask(0), + false, + node_storage.symmetry_axis, + input_mesh); + geometry_set.replace_mesh(result); + } + }); + + params.set_output("Mesh", std::move(geometry_set)); } -} // namespace blender::nodes +} // namespace blender::nodes::node_geo_collapse void register_node_type_geo_collapse() { + namespace file_ns = blender::nodes::node_geo_collapse; + static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_COLLAPSE, "Collapse", NODE_CLASS_GEOMETRY, 0); - node_type_socket_templates(&ntype, geo_node_collapse_in, geo_node_collapse_out); + geo_node_type_base(&ntype, GEO_NODE_COLLAPSE, "Collapse", NODE_CLASS_GEOMETRY); + ntype.declare = file_ns::node_declare; node_type_storage( &ntype, "NodeGeometryCollapse", node_free_standard_storage, node_copy_standard_storage); - node_type_init(&ntype, geo_node_collapse_init); - ntype.geometry_node_execute = blender::nodes::geo_node_collapse_exec; - ntype.draw_buttons = geo_node_collapse_layout; + node_type_init(&ntype, file_ns::geo_node_collapse_init); + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.draw_buttons = file_ns::node_layout; ntype.width = 180; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_dissolve.cc b/source/blender/nodes/geometry/nodes/node_geo_dissolve.cc index 3d41fa80e75..5c5384124a4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dissolve.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dissolve.cc @@ -27,20 +27,22 @@ #include "math.h" #include "node_geometry_util.hh" -static bNodeSocketTemplate geo_node_dissolve_in[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {SOCK_FLOAT, N_("Angle"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, M_PI, PROP_ANGLE}, - {SOCK_BOOLEAN, N_("All Boundaries"), false}, - {SOCK_STRING, N_("Selection")}, - {-1, ""}, -}; - -static bNodeSocketTemplate geo_node_dissolve_out[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {-1, ""}, -}; - -static void geo_node_dissolve_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +namespace blender::nodes::node_geo_dissolve { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH); + b.add_input<decl::Float>(N_("Angle")) + .default_value(0.0f) + .min(0.0f) + .max(M_PI) + .subtype(PROP_ANGLE); + b.add_input<decl::Bool>(N_("All Boundaries")).default_value(false); + b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value(); + b.add_output<decl::Geometry>(N_("Mesh")); +} + +static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayoutSetPropSep(layout, true); uiLayoutSetPropDecorate(layout, false); @@ -56,11 +58,10 @@ static void geo_node_dissolve_init(bNodeTree *UNUSED(tree), bNode *node) node_storage->selection_type = GEO_NODE_DISSOLVE_DELIMITTER_UNSELECTED; } -namespace blender::nodes { static Mesh *dissolve_mesh(const float angle, const bool all_boundaries, const int delimiter, - const Span<bool> selection, + const IndexMask selection, const Mesh *mesh) { const BMeshCreateParams bmesh_create_params = {0}; @@ -68,10 +69,18 @@ static Mesh *dissolve_mesh(const float angle, true, 0, 0, 0, {CD_MASK_ORIGINDEX, CD_MASK_ORIGINDEX, CD_MASK_ORIGINDEX}}; BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmesh_create_params, &bmesh_from_mesh_params); if (delimiter & BMO_DELIM_FACE_SELECTION) { - BM_tag_faces(bm, selection.data()); + // BM_tag_faces(bm, selection.data()); + 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); + } } else { - BM_select_edges(bm, selection.data()); + // BM_select_edges(bm, selection.data()); + for (int i_edge : selection) { + BM_mesh_elem_table_ensure(bm, BM_EDGE); + BM_elem_flag_set(BM_edge_at_index(bm, i_edge), BM_ELEM_SELECT, true); + } } BM_mesh_decimate_dissolve(bm, angle, all_boundaries, (BMO_Delimit)delimiter); @@ -82,9 +91,9 @@ static Mesh *dissolve_mesh(const float angle, return result; } -static void geo_node_dissolve_exec(GeoNodeExecParams params) +static void node_geo_exec(GeoNodeExecParams params) { - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh"); const float angle = params.extract_input<float>("Angle"); if (angle > 0.0f && geometry_set.has_mesh()) { @@ -95,7 +104,7 @@ static void geo_node_dissolve_exec(GeoNodeExecParams params) const bNode &node = params.node(); const NodeGeometryDissolve &node_storage = *(NodeGeometryDissolve *)node.storage; - bool default_selection = false; + // bool default_selection = false; AttributeDomain selection_domain = ATTR_DOMAIN_FACE; BMO_Delimit delimiter = BMO_DELIM_FACE_SELECTION; @@ -106,32 +115,41 @@ static void geo_node_dissolve_exec(GeoNodeExecParams params) else if (node_storage.selection_type == GEO_NODE_DISSOLVE_DELIMITTER_LIMIT) { selection_domain = ATTR_DOMAIN_EDGE; delimiter = BMO_DELIM_EDGE_SELECTION; - default_selection = true; + // default_selection = true; }; - GVArray_Typed<bool> selection_attribute = params.get_input_attribute<bool>( - "Selection", mesh_component, selection_domain, default_selection); - VArray_Span<bool> selection{selection_attribute}; - - Mesh *result = dissolve_mesh(angle, all_boundaries, delimiter, selection, input_mesh); - geometry_set.replace_mesh(result); + Field<bool> selection_field = params.extract_input<Field<bool>>("Selection"); + const int domain_size = mesh_component.attribute_domain_size(selection_domain); + GeometryComponentFieldContext context{mesh_component, selection_domain}; + FieldEvaluator evaluator{context, domain_size}; + evaluator.add(selection_field); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_as_mask(0); + + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + Mesh *result = dissolve_mesh(angle, all_boundaries, delimiter, selection, input_mesh); + geometry_set.replace_mesh(result); + }); } - params.set_output("Geometry", std::move(geometry_set)); + params.set_output("Mesh", std::move(geometry_set)); } -} // namespace blender::nodes +} // namespace blender::nodes::node_geo_dissolve void register_node_type_geo_dissolve() { + namespace file_ns = blender::nodes::node_geo_dissolve; + static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_DISSOLVE, "Dissolve", NODE_CLASS_GEOMETRY, 0); - node_type_socket_templates(&ntype, geo_node_dissolve_in, geo_node_dissolve_out); + geo_node_type_base(&ntype, GEO_NODE_DISSOLVE, "Dissolve", NODE_CLASS_GEOMETRY); + ntype.declare = file_ns::node_declare; + node_type_storage( &ntype, "NodeGeometryDissolve", node_free_standard_storage, node_copy_standard_storage); - node_type_init(&ntype, geo_node_dissolve_init); - ntype.geometry_node_execute = blender::nodes::geo_node_dissolve_exec; - ntype.draw_buttons = geo_node_dissolve_layout; + node_type_init(&ntype, file_ns::geo_node_dissolve_init); + ntype.geometry_node_execute = file_ns::node_geo_exec; + ntype.draw_buttons = file_ns::node_layout; ntype.width = 165; nodeRegisterType(&ntype); }
\ No newline at end of file diff --git a/source/blender/nodes/geometry/nodes/node_geo_unsubdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_unsubdivide.cc index 7f0fc66ff28..fd9b6dbaff5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_unsubdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_unsubdivide.cc @@ -23,27 +23,28 @@ #include "bmesh_tools.h" #include "node_geometry_util.hh" -static bNodeSocketTemplate geo_node_unsubdivide_in[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {SOCK_INT, N_("Iterations"), 1, 0, 0, 0, 0, 10}, - {SOCK_STRING, N_("Selection")}, - {-1, ""}, -}; +namespace blender::nodes::node_geo_unsubdivide { -static bNodeSocketTemplate geo_node_unsubdivide_out[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {-1, ""}, -}; - -namespace blender::nodes { +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH); + b.add_input<decl::Int>(N_("Iterations")).default_value(1).min(0).max(10); + b.add_input<decl::Bool>(N_("Selection")).default_value(true).supports_field().hide_value(); + b.add_output<decl::Geometry>(N_("Mesh")); +} -static Mesh *unsubdivide_mesh(const int iterations, const Array<bool> &selection, const Mesh *mesh) +static Mesh *unsubdivide_mesh(const int iterations, const IndexMask selection, const Mesh *mesh) { const BMeshCreateParams bmesh_create_params = {0}; const BMeshFromMeshParams bmesh_from_mesh_params = { true, 0, 0, 0, {CD_MASK_ORIGINDEX, CD_MASK_ORIGINDEX, CD_MASK_ORIGINDEX}}; BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmesh_create_params, &bmesh_from_mesh_params); - BM_tag_vertices(bm, selection.data()); + + BM_mesh_elem_table_ensure(bm, BM_VERT); + for (int i_point : selection) { + BM_elem_flag_set(BM_vert_at_index(bm, i_point), BM_ELEM_TAG, true); + } + BM_mesh_decimate_unsubdivide_ex(bm, iterations, true); Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); @@ -53,35 +54,41 @@ static Mesh *unsubdivide_mesh(const int iterations, const Array<bool> &selection return result; } -static void geo_node_unsubdivide_exec(GeoNodeExecParams params) +static void node_geo_exec(GeoNodeExecParams params) { - GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh"); const int iterations = params.extract_input<int>("Iterations"); if (iterations > 0 && geometry_set.has_mesh()) { const MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); const Mesh *input_mesh = mesh_component.get_for_read(); - const bool default_selection = true; - GVArray_Typed<bool> selection_attribute = params.get_input_attribute<bool>( - "Selection", mesh_component, ATTR_DOMAIN_POINT, default_selection); - VArray_Span<bool> selection{selection_attribute}; + Field<bool> selection_field = params.extract_input<Field<bool>>("Selection"); + const int domain_size = mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT); + GeometryComponentFieldContext context{mesh_component, ATTR_DOMAIN_POINT}; + FieldEvaluator evaluator{context, domain_size}; + evaluator.add(selection_field); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_as_mask(0); - Mesh *result = unsubdivide_mesh(iterations, selection, input_mesh); - if (result != input_mesh) { - geometry_set.replace_mesh(result); - } + geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { + Mesh *result = unsubdivide_mesh(iterations, selection, input_mesh); + if (result != input_mesh) { + geometry_set.replace_mesh(result); + } + }); } - params.set_output("Geometry", std::move(geometry_set)); + params.set_output("Mesh", std::move(geometry_set)); } -} // namespace blender::nodes +} // namespace blender::nodes::node_geo_unsubdivide void register_node_type_geo_unsubdivide() { + namespace file_ns = blender::nodes::node_geo_unsubdivide; + static bNodeType ntype; - geo_node_type_base(&ntype, GEO_NODE_UNSUBDIVIDE, "Unsubdivide", NODE_CLASS_GEOMETRY, 0); - node_type_socket_templates(&ntype, geo_node_unsubdivide_in, geo_node_unsubdivide_out); - ntype.geometry_node_execute = blender::nodes::geo_node_unsubdivide_exec; - ntype.width = 165; + geo_node_type_base(&ntype, GEO_NODE_UNSUBDIVIDE, "Unsubdivide", NODE_CLASS_GEOMETRY); + ntype.declare = file_ns::node_declare; + ntype.geometry_node_execute = file_ns::node_geo_exec; nodeRegisterType(&ntype); } |