diff --git a/source/blender/blenkernel/BKE_deform.hh b/source/blender/blenkernel/BKE_deform.hh index 95ea5ae7c1e..c44882d1e37 100644 --- a/source/blender/blenkernel/BKE_deform.hh +++ b/source/blender/blenkernel/BKE_deform.hh @@ -298,4 +298,9 @@ VMutableArray varray_for_mutable_deform_verts(MutableSpan dv int defgroup_index); void remove_defgroup_index(MutableSpan dverts, int defgroup_index); +void gather_deform_verts(Span src, Span indices, MutableSpan dst); +void gather_deform_verts(Span src, + const IndexMask &indices, + MutableSpan dst); + } // namespace blender::bke diff --git a/source/blender/blenkernel/intern/deform.cc b/source/blender/blenkernel/intern/deform.cc index 476941190db..69be1b39d18 100644 --- a/source/blender/blenkernel/intern/deform.cc +++ b/source/blender/blenkernel/intern/deform.cc @@ -1768,6 +1768,30 @@ void remove_defgroup_index(MutableSpan dverts, const int defgroup_i }); } +void gather_deform_verts(const Span src, + const Span indices, + MutableSpan dst) +{ + threading::parallel_for(indices.index_range(), 512, [&](const IndexRange range) { + for (const int dst_i : range) { + const int src_i = indices[dst_i]; + dst[dst_i].dw = static_cast(MEM_dupallocN(src[src_i].dw)); + dst[dst_i].totweight = src[src_i].totweight; + dst[dst_i].flag = src[src_i].flag; + } + }); +} +void gather_deform_verts(const Span src, + const IndexMask &indices, + MutableSpan dst) +{ + indices.foreach_index(GrainSize(512), [&](const int64_t src_i, const int64_t dst_i) { + dst[dst_i].dw = static_cast(MEM_dupallocN(src[src_i].dw)); + dst[dst_i].totweight = src[src_i].totweight; + dst[dst_i].flag = src[src_i].flag; + }); +} + } // namespace blender::bke /** \} */ diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc index d84b3636232..afaae85fa12 100644 --- a/source/blender/blenkernel/intern/geometry_component_curves.cc +++ b/source/blender/blenkernel/intern/geometry_component_curves.cc @@ -368,8 +368,7 @@ class CurvesVertexGroupsAttributeProvider final : public DynamicAttributesProvid } const Span dverts = curves->deform_verts(); if (dverts.is_empty()) { - static const float default_value = 0.0f; - return {VArray::ForSingle(default_value, curves->points_num()), AttrDomain::Point}; + return {VArray::ForSingle(0.0f, curves->points_num()), AttrDomain::Point}; } return {varray_for_deform_verts(dverts, vertex_group_index), AttrDomain::Point}; } diff --git a/source/blender/geometry/intern/mesh_copy_selection.cc b/source/blender/geometry/intern/mesh_copy_selection.cc index bfaea06c7e4..c35f898a562 100644 --- a/source/blender/geometry/intern/mesh_copy_selection.cc +++ b/source/blender/geometry/intern/mesh_copy_selection.cc @@ -2,7 +2,6 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "BLI_enumerable_thread_specific.hh" @@ -11,6 +10,7 @@ #include "BKE_attribute.hh" #include "BKE_customdata.hh" +#include "BKE_deform.hh" #include "BKE_geometry_fields.hh" #include "BKE_mesh.hh" @@ -124,26 +124,17 @@ static void gather_vert_attributes(const Mesh &mesh_src, } const Span src = mesh_src.deform_verts(); - MutableSpan dst = mesh_dst.deform_verts_for_write(); - threading::parallel_invoke( - src.size() > 1024, - [&]() { - if (!src.is_empty() && !dst.is_empty()) { - vert_mask.foreach_index(GrainSize(512), [&](const int64_t src_i, const int64_t dst_i) { - dst[dst_i].dw = static_cast(MEM_dupallocN(src[src_i].dw)); - dst[dst_i].totweight = src[src_i].totweight; - dst[dst_i].flag = src[src_i].flag; - }); - } - }, - [&]() { - bke::gather_attributes(mesh_src.attributes(), - bke::AttrDomain::Point, - propagation_info, - vertex_group_names, - vert_mask, - mesh_dst.attributes_for_write()); - }); + if (!vertex_group_names.is_empty() && !src.is_empty()) { + MutableSpan dst = mesh_dst.deform_verts_for_write(); + bke::gather_deform_verts(src, vert_mask, dst); + } + + bke::gather_attributes(mesh_src.attributes(), + bke::AttrDomain::Point, + propagation_info, + vertex_group_names, + vert_mask, + mesh_dst.attributes_for_write()); } std::optional mesh_copy_selection( diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 31e0fa02651..9bf4c850484 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -3,14 +3,15 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ #include "BLI_array_utils.hh" -#include "BLI_disjoint_set.hh" #include "BLI_task.hh" #include "BLI_vector_set.hh" #include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "BKE_attribute_math.hh" #include "BKE_customdata.hh" +#include "BKE_deform.hh" #include "BKE_mesh.hh" #include "BKE_mesh_mapping.hh" #include "BKE_mesh_runtime.hh" @@ -269,7 +270,7 @@ using IDsByDomain = std::array, ATTR_DOMAIN_NUM>; static IDsByDomain attribute_ids_by_domain(const AttributeAccessor attributes, const Set &skip) { - IDsByDomain map; + IDsByDomain ids_by_domain; attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) { if (meta_data.data_type == CD_PROP_STRING) { return true; @@ -277,10 +278,10 @@ static IDsByDomain attribute_ids_by_domain(const AttributeAccessor attributes, if (skip.contains(id.name())) { return true; } - map[int(meta_data.domain)].append(id); + ids_by_domain[int(meta_data.domain)].append(id); return true; }); - return map; + return ids_by_domain; } static void gather_attributes(MutableAttributeAccessor attributes, @@ -307,6 +308,56 @@ static void gather_attributes(MutableAttributeAccessor attributes, } } +static void gather_vert_attributes(Mesh &mesh, + const Span ids, + const Span indices, + const IndexRange new_range) +{ + Set vertex_group_names; + LISTBASE_FOREACH (bDeformGroup *, group, &mesh.vertex_group_names) { + vertex_group_names.add(group->name); + } + + if (!vertex_group_names.is_empty() && !mesh.deform_verts().is_empty()) { + MutableSpan dverts = mesh.deform_verts_for_write(); + bke::gather_deform_verts(dverts, indices, dverts.slice(new_range)); + } + + MutableAttributeAccessor attributes = mesh.attributes_for_write(); + for (const AttributeIDRef &id : ids) { + if (!vertex_group_names.contains(id.name())) { + GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id); + bke::attribute_math::gather(attribute.span, indices, attribute.span.slice(new_range)); + attribute.finish(); + } + } +} + +static void gather_vert_attributes(Mesh &mesh, + const Span ids, + const IndexMask &indices, + const IndexRange new_range) +{ + Set vertex_group_names; + LISTBASE_FOREACH (bDeformGroup *, group, &mesh.vertex_group_names) { + vertex_group_names.add(group->name); + } + + if (!vertex_group_names.is_empty() && !mesh.deform_verts().is_empty()) { + MutableSpan dverts = mesh.deform_verts_for_write(); + bke::gather_deform_verts(dverts, indices, dverts.slice(new_range)); + } + + MutableAttributeAccessor attributes = mesh.attributes_for_write(); + for (const AttributeIDRef &id : ids) { + if (!vertex_group_names.contains(id.name())) { + GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id); + array_utils::gather(attribute.span, indices, attribute.span.slice(new_range)); + attribute.finish(); + } + } +} + static void extrude_mesh_vertices(Mesh &mesh, const Field &selection_field, const Field &offset_field, @@ -357,7 +408,7 @@ static void extrude_mesh_vertices(Mesh &mesh, }); /* New vertices copy the attribute values from their source vertex. */ - gather_attributes(attributes, ids_by_domain[int(AttrDomain::Point)], selection, new_vert_range); + gather_vert_attributes(mesh, ids_by_domain[int(AttrDomain::Point)], selection, new_vert_range); /* New edge values are mixed from of all the edges connected to the source vertex. */ for (const AttributeIDRef &id : ids_by_domain[int(AttrDomain::Edge)]) { @@ -631,7 +682,7 @@ static void extrude_mesh_edges(Mesh &mesh, }); /* New vertices copy the attribute values from their source vertex. */ - gather_attributes(attributes, ids_by_domain[int(AttrDomain::Point)], new_verts, new_vert_range); + gather_vert_attributes(mesh, ids_by_domain[int(AttrDomain::Point)], new_verts, new_vert_range); /* Edges parallel to original edges copy the edge attributes from the original edges. */ gather_attributes( @@ -1006,8 +1057,8 @@ static void extrude_mesh_face_regions(Mesh &mesh, } /* New vertices copy the attributes from their original vertices. */ - gather_attributes( - attributes, ids_by_domain[int(AttrDomain::Point)], new_vert_indices, new_vert_range); + gather_vert_attributes( + mesh, ids_by_domain[int(AttrDomain::Point)], new_vert_indices, new_vert_range); /* New faces on the side of extrusions get the values from the corresponding selected face. */ gather_attributes(attributes, @@ -1276,8 +1327,8 @@ static void extrude_individual_mesh_faces( }); /* New vertices copy the attributes from their original vertices. */ - gather_attributes( - attributes, ids_by_domain[int(AttrDomain::Point)], new_vert_indices, new_vert_range); + gather_vert_attributes( + mesh, ids_by_domain[int(AttrDomain::Point)], new_vert_indices, new_vert_range); /* The data for the duplicate edge is simply a copy of the original edge's data. */ gather_attributes(attributes,