diff options
Diffstat (limited to 'source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc')
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc | 476 |
1 files changed, 152 insertions, 324 deletions
diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index 99edc4d298c..b74b4e45199 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -8,10 +8,11 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "BKE_attribute_math.hh" +#include "BKE_curves.hh" #include "BKE_customdata.h" #include "BKE_mesh.h" #include "BKE_pointcloud.h" -#include "BKE_spline.hh" #include "node_geometry_util.hh" @@ -38,30 +39,17 @@ static void copy_data_based_on_map(Span<T> src, MutableSpan<T> dst, Span<int> in } } -/** Utility function for making an IndexMask from a boolean selection. The indices vector should - * live at least as long as the returned IndexMask. - */ -static IndexMask index_mask_indices(Span<bool> mask, const bool invert, Vector<int64_t> &indices) -{ - for (const int i : mask.index_range()) { - if (mask[i] != invert) { - indices.append(i); - } - } - return IndexMask(indices); -} - /** * Copies the attributes with a domain in `domains` to `result_component`. */ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes, - const GeometryComponent &in_component, - GeometryComponent &result_component, - const Span<AttributeDomain> domains) + const bke::AttributeAccessor src_attributes, + bke::MutableAttributeAccessor dst_attributes, + const Span<eAttrDomain> domains) { for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id); + GAttributeReader attribute = src_attributes.lookup(attribute_id); if (!attribute) { continue; } @@ -70,9 +58,9 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes if (!domains.contains(attribute.domain)) { continue; } - const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); + const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); - OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only( + GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span( attribute_id, attribute.domain, data_type); if (!result_attribute) { @@ -81,11 +69,11 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); - VArray_Span<T> span{attribute.varray.typed<T>()}; - MutableSpan<T> out_span = result_attribute.as_span<T>(); + VArraySpan<T> span{attribute.varray.typed<T>()}; + MutableSpan<T> out_span = result_attribute.span.typed<T>(); out_span.copy_from(span); }); - result_attribute.save(); + result_attribute.finish(); } } @@ -94,14 +82,14 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes * the mask to `result_component`. */ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKind> &attributes, - const GeometryComponent &in_component, - GeometryComponent &result_component, - const AttributeDomain domain, + const bke::AttributeAccessor src_attributes, + bke::MutableAttributeAccessor dst_attributes, + const eAttrDomain domain, const IndexMask mask) { for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id); + GAttributeReader attribute = src_attributes.lookup(attribute_id); if (!attribute) { continue; } @@ -110,9 +98,9 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin if (domain != attribute.domain) { continue; } - const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); + const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); - OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only( + GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span( attribute_id, attribute.domain, data_type); if (!result_attribute) { @@ -121,23 +109,23 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); - VArray_Span<T> span{attribute.varray.typed<T>()}; - MutableSpan<T> out_span = result_attribute.as_span<T>(); + VArraySpan<T> span{attribute.varray.typed<T>()}; + MutableSpan<T> out_span = result_attribute.span.typed<T>(); copy_data_based_on_mask(span, out_span, mask); }); - result_attribute.save(); + result_attribute.finish(); } } static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind> &attributes, - const GeometryComponent &in_component, - GeometryComponent &result_component, - const AttributeDomain domain, + const bke::AttributeAccessor src_attributes, + bke::MutableAttributeAccessor dst_attributes, + const eAttrDomain domain, const Span<int> index_map) { for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; - ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id); + GAttributeReader attribute = src_attributes.lookup(attribute_id); if (!attribute) { continue; } @@ -146,9 +134,9 @@ static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind if (domain != attribute.domain) { continue; } - const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); + const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); - OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only( + GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span( attribute_id, attribute.domain, data_type); if (!result_attribute) { @@ -157,17 +145,17 @@ static void copy_attributes_based_on_map(const Map<AttributeIDRef, AttributeKind attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); - VArray_Span<T> span{attribute.varray.typed<T>()}; - MutableSpan<T> out_span = result_attribute.as_span<T>(); + VArraySpan<T> span{attribute.varray.typed<T>()}; + MutableSpan<T> out_span = result_attribute.span.typed<T>(); copy_data_based_on_map(span, out_span, index_map); }); - result_attribute.save(); + result_attribute.finish(); } } static void copy_face_corner_attributes(const Map<AttributeIDRef, AttributeKind> &attributes, - const GeometryComponent &in_component, - GeometryComponent &out_component, + const bke::AttributeAccessor src_attributes, + bke::MutableAttributeAccessor dst_attributes, const int selected_loops_num, const Span<int> selected_poly_indices, const Mesh &mesh_in) @@ -183,7 +171,7 @@ static void copy_face_corner_attributes(const Map<AttributeIDRef, AttributeKind> } } copy_attributes_based_on_mask( - attributes, in_component, out_component, ATTR_DOMAIN_CORNER, IndexMask(indices)); + attributes, src_attributes, dst_attributes, ATTR_DOMAIN_CORNER, IndexMask(indices)); } static void copy_masked_vertices_to_new_mesh(const Mesh &src_mesh, @@ -324,227 +312,87 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, } } -static void spline_copy_builtin_attributes(const Spline &spline, - Spline &r_spline, - const IndexMask mask) -{ - copy_data_based_on_mask(spline.positions(), r_spline.positions(), mask); - copy_data_based_on_mask(spline.radii(), r_spline.radii(), mask); - copy_data_based_on_mask(spline.tilts(), r_spline.tilts(), mask); - switch (spline.type()) { - case CURVE_TYPE_POLY: - break; - case CURVE_TYPE_BEZIER: { - const BezierSpline &src = static_cast<const BezierSpline &>(spline); - BezierSpline &dst = static_cast<BezierSpline &>(r_spline); - copy_data_based_on_mask(src.handle_positions_left(), dst.handle_positions_left(), mask); - copy_data_based_on_mask(src.handle_positions_right(), dst.handle_positions_right(), mask); - copy_data_based_on_mask(src.handle_types_left(), dst.handle_types_left(), mask); - copy_data_based_on_mask(src.handle_types_right(), dst.handle_types_right(), mask); - break; - } - case CURVE_TYPE_NURBS: { - const NURBSpline &src = static_cast<const NURBSpline &>(spline); - NURBSpline &dst = static_cast<NURBSpline &>(r_spline); - copy_data_based_on_mask(src.weights(), dst.weights(), mask); - break; - } - case CURVE_TYPE_CATMULL_ROM: { - BLI_assert_unreachable(); - break; - } - } -} - -static void copy_dynamic_attributes(const CustomDataAttributes &src, - CustomDataAttributes &dst, - const IndexMask mask) -{ - src.foreach_attribute( - [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { - std::optional<GSpan> src_attribute = src.get_for_read(attribute_id); - BLI_assert(src_attribute); - - if (!dst.create(attribute_id, meta_data.data_type)) { - /* Since the source spline of the same type had the attribute, adding it should work. - */ - BLI_assert_unreachable(); - } - - std::optional<GMutableSpan> new_attribute = dst.get_for_write(attribute_id); - BLI_assert(new_attribute); - - attribute_math::convert_to_static_type(new_attribute->type(), [&](auto dummy) { - using T = decltype(dummy); - copy_data_based_on_mask(src_attribute->typed<T>(), new_attribute->typed<T>(), mask); - }); - return true; - }, - ATTR_DOMAIN_POINT); -} - -/** - * Deletes points in the spline. Those not in the mask are deleted. The spline is not split into - * multiple newer splines. - */ -static SplinePtr spline_delete(const Spline &spline, const IndexMask mask) -{ - SplinePtr new_spline = spline.copy_only_settings(); - new_spline->resize(mask.size()); - - spline_copy_builtin_attributes(spline, *new_spline, mask); - copy_dynamic_attributes(spline.attributes, new_spline->attributes, mask); - - return new_spline; -} - -static std::unique_ptr<CurveEval> curve_separate(const CurveEval &input_curve, - const Span<bool> selection, - const AttributeDomain selection_domain, - const bool invert) +static void delete_curves_selection(GeometrySet &geometry_set, + const Field<bool> &selection_field, + const eAttrDomain selection_domain) { - Span<SplinePtr> input_splines = input_curve.splines(); - std::unique_ptr<CurveEval> output_curve = std::make_unique<CurveEval>(); - - /* Keep track of which splines were copied to the result to copy spline domain attributes. */ - Vector<int64_t> copied_splines; - - if (selection_domain == ATTR_DOMAIN_CURVE) { - /* Operates on each of the splines as a whole, i.e. not on the points in the splines - * themselves. */ - for (const int i : selection.index_range()) { - if (selection[i] != invert) { - output_curve->add_spline(input_splines[i]->copy()); - copied_splines.append(i); - } - } - } - else { - /* Operates on the points in the splines themselves. */ - - /* Reuse index vector for each spline. */ - Vector<int64_t> indices_to_copy; - - int selection_index = 0; - for (const int i : input_splines.index_range()) { - const Spline &spline = *input_splines[i]; - - indices_to_copy.clear(); - for (const int i_point : IndexRange(spline.size())) { - if (selection[selection_index] != invert) { - /* Append i_point instead of selection_index because we need indices local to the spline - * for copying. */ - indices_to_copy.append(i_point); - } - selection_index++; - } - - /* Avoid creating an empty spline. */ - if (indices_to_copy.is_empty()) { - continue; - } + const CurveComponent &src_component = *geometry_set.get_component_for_read<CurveComponent>(); + GeometryComponentFieldContext field_context{src_component, selection_domain}; - SplinePtr new_spline = spline_delete(spline, IndexMask(indices_to_copy)); - output_curve->add_spline(std::move(new_spline)); - copied_splines.append(i); - } + const int domain_num = src_component.attribute_domain_size(selection_domain); + fn::FieldEvaluator evaluator{field_context, domain_num}; + evaluator.set_selection(selection_field); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + if (selection.is_empty()) { + return; } - - if (copied_splines.is_empty()) { - return {}; + if (selection.size() == domain_num) { + geometry_set.remove<CurveComponent>(); + return; } - output_curve->attributes.reallocate(output_curve->splines().size()); - copy_dynamic_attributes( - input_curve.attributes, output_curve->attributes, IndexMask(copied_splines)); + CurveComponent &component = geometry_set.get_component_for_write<CurveComponent>(); + Curves &curves_id = *component.get_for_write(); + bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); - return output_curve; -} - -static void separate_curve_selection(GeometrySet &geometry_set, - const Field<bool> &selection_field, - const AttributeDomain selection_domain, - const bool invert) -{ - const CurveComponent &src_component = *geometry_set.get_component_for_read<CurveComponent>(); - GeometryComponentFieldContext field_context{src_component, selection_domain}; - - fn::FieldEvaluator selection_evaluator{field_context, - src_component.attribute_domain_num(selection_domain)}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const VArray_Span<bool> &selection = selection_evaluator.get_evaluated<bool>(0); - std::unique_ptr<CurveEval> r_curve = curve_separate( - *curves_to_curve_eval(*src_component.get_for_read()), selection, selection_domain, invert); - if (r_curve) { - geometry_set.replace_curves(curve_eval_to_curves(*r_curve)); + if (selection_domain == ATTR_DOMAIN_POINT) { + curves.remove_points(selection); } - else { - geometry_set.replace_curves(nullptr); + else if (selection_domain == ATTR_DOMAIN_CURVE) { + curves.remove_curves(selection); } } static void separate_point_cloud_selection(GeometrySet &geometry_set, - const Field<bool> &selection_field, - const bool invert) + const Field<bool> &selection_field) { const PointCloudComponent &src_points = *geometry_set.get_component_for_read<PointCloudComponent>(); GeometryComponentFieldContext field_context{src_points, ATTR_DOMAIN_POINT}; - fn::FieldEvaluator selection_evaluator{field_context, - src_points.attribute_domain_num(ATTR_DOMAIN_POINT)}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const VArray_Span<bool> &selection = selection_evaluator.get_evaluated<bool>(0); - - Vector<int64_t> indices; - const IndexMask mask = index_mask_indices(selection, invert, indices); - const int total = mask.size(); - PointCloud *pointcloud = BKE_pointcloud_new_nomain(total); - - if (total == 0) { - geometry_set.replace_pointcloud(pointcloud); + fn::FieldEvaluator evaluator{field_context, src_points.attribute_domain_size(ATTR_DOMAIN_POINT)}; + evaluator.set_selection(selection_field); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + if (selection.is_empty()) { + geometry_set.replace_pointcloud(nullptr); return; } - PointCloudComponent dst_points; - dst_points.replace(pointcloud, GeometryOwnershipType::Editable); + PointCloud *pointcloud = BKE_pointcloud_new_nomain(selection.size()); Map<AttributeIDRef, AttributeKind> attributes; geometry_set.gather_attributes_for_propagation( {GEO_COMPONENT_TYPE_POINT_CLOUD}, GEO_COMPONENT_TYPE_POINT_CLOUD, false, attributes); - copy_attributes_based_on_mask(attributes, src_points, dst_points, ATTR_DOMAIN_POINT, mask); + copy_attributes_based_on_mask(attributes, + bke::pointcloud_attributes(*src_points.get_for_read()), + bke::pointcloud_attributes_for_write(*pointcloud), + ATTR_DOMAIN_POINT, + selection); geometry_set.replace_pointcloud(pointcloud); } -static void separate_instance_selection(GeometrySet &geometry_set, - const Field<bool> &selection_field, - const bool invert) +static void delete_selected_instances(GeometrySet &geometry_set, + const Field<bool> &selection_field) { InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>(); GeometryComponentFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE}; - const int domain_num = instances.attribute_domain_num(ATTR_DOMAIN_INSTANCE); - fn::FieldEvaluator evaluator{field_context, domain_num}; - evaluator.add(selection_field); + fn::FieldEvaluator evaluator{field_context, instances.instances_num()}; + evaluator.set_selection(selection_field); evaluator.evaluate(); - const VArray_Span<bool> &selection = evaluator.get_evaluated<bool>(0); - - Vector<int64_t> indices; - const IndexMask mask = index_mask_indices(selection, invert, indices); - - if (mask.is_empty()) { + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + if (selection.is_empty()) { geometry_set.remove<InstancesComponent>(); return; } - instances.remove_instances(mask); + instances.remove_instances(selection); } static void compute_selected_vertices_from_vertex_selection(const Span<bool> vertex_selection, - const bool invert, MutableSpan<int> r_vertex_map, int *r_selected_vertices_num) { @@ -552,7 +400,7 @@ static void compute_selected_vertices_from_vertex_selection(const Span<bool> ver int selected_verts_num = 0; for (const int i : r_vertex_map.index_range()) { - if (vertex_selection[i] != invert) { + if (vertex_selection[i]) { r_vertex_map[i] = selected_verts_num; selected_verts_num++; } @@ -566,7 +414,6 @@ static void compute_selected_vertices_from_vertex_selection(const Span<bool> ver static void compute_selected_edges_from_vertex_selection(const Mesh &mesh, const Span<bool> vertex_selection, - const bool invert, MutableSpan<int> r_edge_map, int *r_selected_edges_num) { @@ -577,7 +424,7 @@ static void compute_selected_edges_from_vertex_selection(const Mesh &mesh, const MEdge &edge = mesh.medge[i]; /* Only add the edge if both vertices will be in the new mesh. */ - if (vertex_selection[edge.v1] != invert && vertex_selection[edge.v2] != invert) { + if (vertex_selection[edge.v1] && vertex_selection[edge.v2]) { r_edge_map[i] = selected_edges_num; selected_edges_num++; } @@ -591,7 +438,6 @@ static void compute_selected_edges_from_vertex_selection(const Mesh &mesh, static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh, const Span<bool> vertex_selection, - const bool invert, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, int *r_selected_polys_num, @@ -609,7 +455,7 @@ static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh, bool all_verts_in_selection = true; Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop); for (const MLoop &loop : loops_src) { - if (vertex_selection[loop.v] == invert) { + if (!vertex_selection[loop.v]) { all_verts_in_selection = false; break; } @@ -633,7 +479,6 @@ static void compute_selected_polygons_from_vertex_selection(const Mesh &mesh, static void compute_selected_vertices_and_edges_from_edge_selection( const Mesh &mesh, const Span<bool> edge_selection, - const bool invert, MutableSpan<int> r_vertex_map, MutableSpan<int> r_edge_map, int *r_selected_vertices_num, @@ -645,7 +490,7 @@ static void compute_selected_vertices_and_edges_from_edge_selection( int selected_verts_num = 0; for (const int i : IndexRange(mesh.totedge)) { const MEdge &edge = mesh.medge[i]; - if (edge_selection[i] != invert) { + if (edge_selection[i]) { r_edge_map[i] = selected_edges_num; selected_edges_num++; if (r_vertex_map[edge.v1] == -1) { @@ -671,7 +516,6 @@ static void compute_selected_vertices_and_edges_from_edge_selection( */ static void compute_selected_edges_from_edge_selection(const Mesh &mesh, const Span<bool> edge_selection, - const bool invert, MutableSpan<int> r_edge_map, int *r_selected_edges_num) { @@ -679,7 +523,7 @@ static void compute_selected_edges_from_edge_selection(const Mesh &mesh, int selected_edges_num = 0; for (const int i : IndexRange(mesh.totedge)) { - if (edge_selection[i] != invert) { + if (edge_selection[i]) { r_edge_map[i] = selected_edges_num; selected_edges_num++; } @@ -697,7 +541,6 @@ static void compute_selected_edges_from_edge_selection(const Mesh &mesh, */ static void compute_selected_polygons_from_edge_selection(const Mesh &mesh, const Span<bool> edge_selection, - const bool invert, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, int *r_selected_polys_num, @@ -713,7 +556,7 @@ static void compute_selected_polygons_from_edge_selection(const Mesh &mesh, bool all_edges_in_selection = true; Span<MLoop> loops_src(&mesh.mloop[poly_src.loopstart], poly_src.totloop); for (const MLoop &loop : loops_src) { - if (edge_selection[loop.e] == invert) { + if (!edge_selection[loop.e]) { all_edges_in_selection = false; break; } @@ -736,7 +579,6 @@ static void compute_selected_polygons_from_edge_selection(const Mesh &mesh, static void compute_selected_mesh_data_from_vertex_selection_edge_face( const Mesh &mesh, const Span<bool> vertex_selection, - const bool invert, MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, @@ -746,11 +588,10 @@ static void compute_selected_mesh_data_from_vertex_selection_edge_face( { compute_selected_edges_from_vertex_selection( - mesh, vertex_selection, invert, r_edge_map, r_selected_edges_num); + mesh, vertex_selection, r_edge_map, r_selected_edges_num); compute_selected_polygons_from_vertex_selection(mesh, vertex_selection, - invert, r_selected_poly_indices, r_loop_starts, r_selected_polys_num, @@ -763,7 +604,6 @@ static void compute_selected_mesh_data_from_vertex_selection_edge_face( */ static void compute_selected_mesh_data_from_vertex_selection(const Mesh &mesh, const Span<bool> vertex_selection, - const bool invert, MutableSpan<int> r_vertex_map, MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, @@ -774,14 +614,13 @@ static void compute_selected_mesh_data_from_vertex_selection(const Mesh &mesh, int *r_selected_loops_num) { compute_selected_vertices_from_vertex_selection( - vertex_selection, invert, r_vertex_map, r_selected_vertices_num); + vertex_selection, r_vertex_map, r_selected_vertices_num); compute_selected_edges_from_vertex_selection( - mesh, vertex_selection, invert, r_edge_map, r_selected_edges_num); + mesh, vertex_selection, r_edge_map, r_selected_edges_num); compute_selected_polygons_from_vertex_selection(mesh, vertex_selection, - invert, r_selected_poly_indices, r_loop_starts, r_selected_polys_num, @@ -795,7 +634,6 @@ static void compute_selected_mesh_data_from_vertex_selection(const Mesh &mesh, static void compute_selected_mesh_data_from_edge_selection_edge_face( const Mesh &mesh, const Span<bool> edge_selection, - const bool invert, MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, @@ -804,10 +642,9 @@ static void compute_selected_mesh_data_from_edge_selection_edge_face( int *r_selected_loops_num) { compute_selected_edges_from_edge_selection( - mesh, edge_selection, invert, r_edge_map, r_selected_edges_num); + mesh, edge_selection, r_edge_map, r_selected_edges_num); compute_selected_polygons_from_edge_selection(mesh, edge_selection, - invert, r_selected_poly_indices, r_loop_starts, r_selected_polys_num, @@ -820,7 +657,6 @@ static void compute_selected_mesh_data_from_edge_selection_edge_face( */ static void compute_selected_mesh_data_from_edge_selection(const Mesh &mesh, const Span<bool> edge_selection, - const bool invert, MutableSpan<int> r_vertex_map, MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, @@ -833,14 +669,12 @@ static void compute_selected_mesh_data_from_edge_selection(const Mesh &mesh, r_vertex_map.fill(-1); compute_selected_vertices_and_edges_from_edge_selection(mesh, edge_selection, - invert, r_vertex_map, r_edge_map, r_selected_vertices_num, r_selected_edges_num); compute_selected_polygons_from_edge_selection(mesh, edge_selection, - invert, r_selected_poly_indices, r_loop_starts, r_selected_polys_num, @@ -852,7 +686,6 @@ static void compute_selected_mesh_data_from_edge_selection(const Mesh &mesh, */ static void compute_selected_polygons_from_poly_selection(const Mesh &mesh, const Span<bool> poly_selection, - const bool invert, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, int *r_selected_polys_num, @@ -867,7 +700,7 @@ static void compute_selected_polygons_from_poly_selection(const Mesh &mesh, for (const int i : IndexRange(mesh.totpoly)) { const MPoly &poly_src = mesh.mpoly[i]; /* We keep this one. */ - if (poly_selection[i] != invert) { + if (poly_selection[i]) { r_selected_poly_indices.append_unchecked(i); r_loop_starts.append_unchecked(selected_loops_num); selected_loops_num += poly_src.totloop; @@ -883,7 +716,6 @@ static void compute_selected_polygons_from_poly_selection(const Mesh &mesh, static void compute_selected_mesh_data_from_poly_selection_edge_face( const Mesh &mesh, const Span<bool> poly_selection, - const bool invert, MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, Vector<int> &r_loop_starts, @@ -903,7 +735,7 @@ static void compute_selected_mesh_data_from_poly_selection_edge_face( for (const int i : IndexRange(mesh.totpoly)) { const MPoly &poly_src = mesh.mpoly[i]; /* We keep this one. */ - if (poly_selection[i] != invert) { + if (poly_selection[i]) { r_selected_poly_indices.append_unchecked(i); r_loop_starts.append_unchecked(selected_loops_num); selected_loops_num += poly_src.totloop; @@ -930,7 +762,6 @@ static void compute_selected_mesh_data_from_poly_selection_edge_face( */ static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, const Span<bool> poly_selection, - const bool invert, MutableSpan<int> r_vertex_map, MutableSpan<int> r_edge_map, Vector<int> &r_selected_poly_indices, @@ -954,7 +785,7 @@ static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, for (const int i : IndexRange(mesh.totpoly)) { const MPoly &poly_src = mesh.mpoly[i]; /* We keep this one. */ - if (poly_selection[i] != invert) { + if (poly_selection[i]) { r_selected_poly_indices.append_unchecked(i); r_loop_starts.append_unchecked(selected_loops_num); selected_loops_num += poly_src.totloop; @@ -984,10 +815,9 @@ static void compute_selected_mesh_data_from_poly_selection(const Mesh &mesh, * Keep the parts of the mesh that are in the selection. */ static void do_mesh_separation(GeometrySet &geometry_set, - const MeshComponent &in_component, - const VArray_Span<bool> &selection, - const bool invert, - const AttributeDomain domain, + const Mesh &mesh_in, + const Span<bool> selection, + const eAttrDomain domain, const GeometryNodeDeleteGeometryMode mode) { /* Needed in all cases. */ @@ -996,9 +826,7 @@ static void do_mesh_separation(GeometrySet &geometry_set, int selected_polys_num = 0; int selected_loops_num = 0; - const Mesh &mesh_in = *in_component.get_for_read(); Mesh *mesh_out; - MeshComponent out_component; Map<AttributeIDRef, AttributeKind> attributes; geometry_set.gather_attributes_for_propagation( @@ -1017,7 +845,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, case ATTR_DOMAIN_POINT: compute_selected_mesh_data_from_vertex_selection(mesh_in, selection, - invert, vertex_map, edge_map, selected_poly_indices, @@ -1030,7 +857,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, case ATTR_DOMAIN_EDGE: compute_selected_mesh_data_from_edge_selection(mesh_in, selection, - invert, vertex_map, edge_map, selected_poly_indices, @@ -1043,7 +869,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, case ATTR_DOMAIN_FACE: compute_selected_mesh_data_from_poly_selection(mesh_in, selection, - invert, vertex_map, edge_map, selected_poly_indices, @@ -1063,7 +888,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, 0, selected_loops_num, selected_polys_num); - out_component.replace(mesh_out, GeometryOwnershipType::Editable); /* Copy the selected parts of the mesh over to the new mesh. */ copy_masked_vertices_to_new_mesh(mesh_in, *mesh_out, vertex_map); @@ -1072,18 +896,24 @@ static void do_mesh_separation(GeometrySet &geometry_set, mesh_in, *mesh_out, vertex_map, edge_map, selected_poly_indices, new_loop_starts); /* Copy attributes. */ - copy_attributes_based_on_map( - attributes, in_component, out_component, ATTR_DOMAIN_POINT, vertex_map); - copy_attributes_based_on_map( - attributes, in_component, out_component, ATTR_DOMAIN_EDGE, edge_map); + copy_attributes_based_on_map(attributes, + bke::mesh_attributes(mesh_in), + bke::mesh_attributes_for_write(*mesh_out), + ATTR_DOMAIN_POINT, + vertex_map); + copy_attributes_based_on_map(attributes, + bke::mesh_attributes(mesh_in), + bke::mesh_attributes_for_write(*mesh_out), + ATTR_DOMAIN_EDGE, + edge_map); copy_attributes_based_on_mask(attributes, - in_component, - out_component, + bke::mesh_attributes(mesh_in), + bke::mesh_attributes_for_write(*mesh_out), ATTR_DOMAIN_FACE, IndexMask(Vector<int64_t>(selected_poly_indices.as_span()))); copy_face_corner_attributes(attributes, - in_component, - out_component, + bke::mesh_attributes(mesh_in), + bke::mesh_attributes_for_write(*mesh_out), selected_loops_num, selected_poly_indices, mesh_in); @@ -1098,7 +928,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, case ATTR_DOMAIN_POINT: compute_selected_mesh_data_from_vertex_selection_edge_face(mesh_in, selection, - invert, edge_map, selected_poly_indices, new_loop_starts, @@ -1109,7 +938,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, case ATTR_DOMAIN_EDGE: compute_selected_mesh_data_from_edge_selection_edge_face(mesh_in, selection, - invert, edge_map, selected_poly_indices, new_loop_starts, @@ -1120,7 +948,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, case ATTR_DOMAIN_FACE: compute_selected_mesh_data_from_poly_selection_edge_face(mesh_in, selection, - invert, edge_map, selected_poly_indices, new_loop_starts, @@ -1138,7 +965,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, 0, selected_loops_num, selected_polys_num); - out_component.replace(mesh_out, GeometryOwnershipType::Editable); /* Copy the selected parts of the mesh over to the new mesh. */ memcpy(mesh_out->mvert, mesh_in.mvert, mesh_in.totvert * sizeof(MVert)); @@ -1147,17 +973,23 @@ static void do_mesh_separation(GeometrySet &geometry_set, mesh_in, *mesh_out, edge_map, selected_poly_indices, new_loop_starts); /* Copy attributes. */ - copy_attributes(attributes, in_component, out_component, {ATTR_DOMAIN_POINT}); - copy_attributes_based_on_map( - attributes, in_component, out_component, ATTR_DOMAIN_EDGE, edge_map); + copy_attributes(attributes, + bke::mesh_attributes(mesh_in), + bke::mesh_attributes_for_write(*mesh_out), + {ATTR_DOMAIN_POINT}); + copy_attributes_based_on_map(attributes, + bke::mesh_attributes(mesh_in), + bke::mesh_attributes_for_write(*mesh_out), + ATTR_DOMAIN_EDGE, + edge_map); copy_attributes_based_on_mask(attributes, - in_component, - out_component, + bke::mesh_attributes(mesh_in), + bke::mesh_attributes_for_write(*mesh_out), ATTR_DOMAIN_FACE, IndexMask(Vector<int64_t>(selected_poly_indices.as_span()))); copy_face_corner_attributes(attributes, - in_component, - out_component, + bke::mesh_attributes(mesh_in), + bke::mesh_attributes_for_write(*mesh_out), selected_loops_num, selected_poly_indices, mesh_in); @@ -1169,7 +1001,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, case ATTR_DOMAIN_POINT: compute_selected_polygons_from_vertex_selection(mesh_in, selection, - invert, selected_poly_indices, new_loop_starts, &selected_polys_num, @@ -1178,7 +1009,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, case ATTR_DOMAIN_EDGE: compute_selected_polygons_from_edge_selection(mesh_in, selection, - invert, selected_poly_indices, new_loop_starts, &selected_polys_num, @@ -1187,7 +1017,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, case ATTR_DOMAIN_FACE: compute_selected_polygons_from_poly_selection(mesh_in, selection, - invert, selected_poly_indices, new_loop_starts, &selected_polys_num, @@ -1199,7 +1028,6 @@ static void do_mesh_separation(GeometrySet &geometry_set, } mesh_out = BKE_mesh_new_nomain_from_template( &mesh_in, mesh_in.totvert, mesh_in.totedge, 0, selected_loops_num, selected_polys_num); - out_component.replace(mesh_out, GeometryOwnershipType::Editable); /* Copy the selected parts of the mesh over to the new mesh. */ memcpy(mesh_out->mvert, mesh_in.mvert, mesh_in.totvert * sizeof(MVert)); @@ -1207,16 +1035,18 @@ static void do_mesh_separation(GeometrySet &geometry_set, copy_masked_polys_to_new_mesh(mesh_in, *mesh_out, selected_poly_indices, new_loop_starts); /* Copy attributes. */ - copy_attributes( - attributes, in_component, out_component, {ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE}); + copy_attributes(attributes, + bke::mesh_attributes(mesh_in), + bke::mesh_attributes_for_write(*mesh_out), + {ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE}); copy_attributes_based_on_mask(attributes, - in_component, - out_component, + bke::mesh_attributes(mesh_in), + bke::mesh_attributes_for_write(*mesh_out), ATTR_DOMAIN_FACE, IndexMask(Vector<int64_t>(selected_poly_indices.as_span()))); copy_face_corner_attributes(attributes, - in_component, - out_component, + bke::mesh_attributes(mesh_in), + bke::mesh_attributes_for_write(*mesh_out), selected_loops_num, selected_poly_indices, mesh_in); @@ -1230,32 +1060,26 @@ static void do_mesh_separation(GeometrySet &geometry_set, static void separate_mesh_selection(GeometrySet &geometry_set, const Field<bool> &selection_field, - const AttributeDomain selection_domain, - const GeometryNodeDeleteGeometryMode mode, - const bool invert) + const eAttrDomain selection_domain, + const GeometryNodeDeleteGeometryMode mode) { const MeshComponent &src_component = *geometry_set.get_component_for_read<MeshComponent>(); GeometryComponentFieldContext field_context{src_component, selection_domain}; - fn::FieldEvaluator selection_evaluator{field_context, - src_component.attribute_domain_num(selection_domain)}; - selection_evaluator.add(selection_field); - selection_evaluator.evaluate(); - const VArray_Span<bool> &selection = selection_evaluator.get_evaluated<bool>(0); - + fn::FieldEvaluator evaluator{field_context, + src_component.attribute_domain_size(selection_domain)}; + evaluator.add(selection_field); + evaluator.evaluate(); + const VArray<bool> selection = evaluator.get_evaluated<bool>(0); /* Check if there is anything to delete. */ - bool delete_nothing = true; - for (const int i : selection.index_range()) { - if (selection[i] == invert) { - delete_nothing = false; - break; - } - } - if (delete_nothing) { + if (selection.is_empty() || (selection.is_single() && selection.get_internal_single())) { return; } - do_mesh_separation(geometry_set, src_component, selection, invert, selection_domain, mode); + const VArraySpan<bool> selection_span{selection}; + + do_mesh_separation( + geometry_set, *src_component.get_for_read(), selection_span, selection_domain, mode); } } // namespace blender::nodes::node_geo_delete_geometry_cc @@ -1263,10 +1087,9 @@ static void separate_mesh_selection(GeometrySet &geometry_set, namespace blender::nodes { void separate_geometry(GeometrySet &geometry_set, - const AttributeDomain domain, + const eAttrDomain domain, const GeometryNodeDeleteGeometryMode mode, const Field<bool> &selection_field, - const bool invert, bool &r_is_error) { namespace file_ns = blender::nodes::node_geo_delete_geometry_cc; @@ -1274,25 +1097,26 @@ void separate_geometry(GeometrySet &geometry_set, bool some_valid_domain = false; if (geometry_set.has_pointcloud()) { if (domain == ATTR_DOMAIN_POINT) { - file_ns::separate_point_cloud_selection(geometry_set, selection_field, invert); + file_ns::separate_point_cloud_selection(geometry_set, selection_field); some_valid_domain = true; } } if (geometry_set.has_mesh()) { if (ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER)) { - file_ns::separate_mesh_selection(geometry_set, selection_field, domain, mode, invert); + file_ns::separate_mesh_selection(geometry_set, selection_field, domain, mode); some_valid_domain = true; } } if (geometry_set.has_curves()) { if (ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE)) { - file_ns::separate_curve_selection(geometry_set, selection_field, domain, invert); + file_ns::delete_curves_selection( + geometry_set, fn::invert_boolean_field(selection_field), domain); some_valid_domain = true; } } if (geometry_set.has_instances()) { if (domain == ATTR_DOMAIN_INSTANCE) { - file_ns::separate_instance_selection(geometry_set, selection_field, invert); + file_ns::delete_selected_instances(geometry_set, selection_field); some_valid_domain = true; } } @@ -1320,7 +1144,7 @@ static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { const bNode *node = static_cast<bNode *>(ptr->data); const NodeGeometryDeleteGeometry &storage = node_storage(*node); - const AttributeDomain domain = static_cast<AttributeDomain>(storage.domain); + const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain); uiItemR(layout, ptr, "domain", 0, "", ICON_NONE); /* Only show the mode when it is relevant. */ @@ -1342,21 +1166,25 @@ static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); - const Field<bool> selection_field = params.extract_input<Field<bool>>("Selection"); + /* The node's input is a selection of elements that should be deleted, but the code is + * implemented as a separation operation that copies the selected elements to a new geometry. + * Invert the selection to avoid the need to keep track of both cases in the code. */ + const Field<bool> selection = fn::invert_boolean_field( + params.extract_input<Field<bool>>("Selection")); const NodeGeometryDeleteGeometry &storage = node_storage(params.node()); - const AttributeDomain domain = static_cast<AttributeDomain>(storage.domain); + const eAttrDomain domain = static_cast<eAttrDomain>(storage.domain); const GeometryNodeDeleteGeometryMode mode = (GeometryNodeDeleteGeometryMode)storage.mode; if (domain == ATTR_DOMAIN_INSTANCE) { bool is_error; - separate_geometry(geometry_set, domain, mode, selection_field, true, is_error); + separate_geometry(geometry_set, domain, mode, selection, is_error); } else { geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) { bool is_error; /* Invert here because we want to keep the things not in the selection. */ - separate_geometry(geometry_set, domain, mode, selection_field, true, is_error); + separate_geometry(geometry_set, domain, mode, selection, is_error); }); } |