22 const int src_verts_num,
34 vert_mask.
size() > 1024,
36 face_mask.foreach_index(GrainSize(512), [&](const int64_t src_i, const int64_t dst_i) {
37 const IndexRange src_face = src_faces[src_i];
38 const IndexRange dst_face = dst_faces[dst_i];
39 for (const int i : src_face.index_range()) {
40 dst_corner_verts[dst_face[i]] = map[src_corner_verts[src_face[i]]];
46 dst_edges[dst_i][0] = map[src_edges[src_i][0]];
47 dst_edges[dst_i][1] = map[src_edges[src_i][1]];
54 const int src_edges_num,
66 dst_corner_edges[dst_face[
i]] = map[src_corner_edges[src_face[
i]]];
73 const auto &src_cache = src.
runtime->loose_verts_cache;
74 if (src_cache.is_cached() && src_cache.data().count == 0) {
75 dst.tag_loose_verts_none();
81 const auto &src_cache = src.
runtime->loose_edges_cache;
82 if (src_cache.is_cached() && src_cache.data().count == 0) {
83 dst.tag_loose_edges_none();
89 if (src.no_overlapping_topology()) {
90 dst.tag_overlapping_none();
102 vertex_group_names.
add(group->name);
116 mesh_dst.attributes_for_write());
124 const Span<int2> src_edges = src_mesh.edges();
126 const Span<int> src_corner_verts = src_mesh.corner_verts();
127 const Span<int> src_corner_edges = src_mesh.corner_edges();
133 if (
const std::optional<bool> single = selection.
get_if_single()) {
134 return *single ? std::nullopt : std::make_optional<Mesh *>(
nullptr);
141 switch (selection_domain) {
146 [&]() { vert_mask = IndexMask::from_bools(span, memory.local()); },
147 [&]() { edge_mask = edge_selection_from_vert(src_edges, span, memory.local()); },
149 face_mask = face_selection_from_vert(
150 src_faces, src_corner_verts, span, memory.local());
157 src_edges.
size() > 1024,
159 edge_mask = IndexMask::from_bools(span, memory.local());
160 vert_mask = vert_selection_from_edge(
161 src_edges, edge_mask, src_mesh.verts_num, memory.local());
164 face_mask = face_selection_from_edge(
165 src_faces, src_corner_edges, span, memory.local());
173 face_mask.
size() > 1024,
175 vert_mask = vert_selection_from_face(
176 src_faces, face_mask, src_corner_verts, src_mesh.verts_num, memory.local());
179 edge_mask = edge_selection_from_face(
180 src_faces, face_mask, src_corner_edges, src_mesh.edges_num, memory.local());
192 const bool same_verts = vert_mask.
size() == src_mesh.
verts_num;
193 const bool same_edges = edge_mask.
size() == src_mesh.
edges_num;
194 const bool same_faces = face_mask.
size() == src_mesh.
faces_num;
195 if (same_verts && same_edges && same_faces) {
200 vert_mask.
size(), edge_mask.
size(), face_mask.
size(), 0);
207 src_faces, face_mask, dst_mesh->face_offsets_for_write());
215 vert_mask.
size() > 1024,
217 remap_verts(src_faces,
229 remap_edges(src_faces,
238 gather_vert_attributes(src_mesh, attribute_filter, vert_mask, *dst_mesh);
239 bke::gather_attributes(
241 bke::AttrDomain::Edge,
242 bke::AttrDomain::Edge,
243 bke::attribute_filter_with_skip_ref(attribute_filter, {
".edge_verts"}),
257 {
".corner_edge",
".corner_vert"}),
267 else if (selection_domain == bke::AttrDomain::Face) {
281 const Span<int2> src_edges = src_mesh.edges();
283 const Span<int> src_corner_verts = src_mesh.corner_verts();
284 const Span<int> src_corner_edges = src_mesh.corner_edges();
294 switch (selection_domain) {
298 src_edges.
size() > 1024,
299 [&]() { edge_mask = edge_selection_from_vert(src_edges, span, memory.local()); },
301 face_mask = face_selection_from_vert(
302 src_faces, src_corner_verts, span, memory.local());
309 src_edges.
size() > 1024,
310 [&]() { edge_mask = IndexMask::from_bools(span, memory.local()); },
312 face_mask = face_selection_from_edge(
313 src_faces, src_corner_edges, span, memory.local());
321 src_faces, face_mask, src_corner_edges, src_edges.
size(), memory.
local());
329 const bool same_edges = edge_mask.
size() == src_mesh.
edges_num;
330 const bool same_faces = face_mask.
size() == src_mesh.
faces_num;
331 if (same_edges && same_faces) {
341 src_faces, face_mask, dst_mesh->face_offsets_for_write());
409 switch (selection_domain) {
412 src_faces, src_mesh.corner_verts(),
VArraySpan(selection), memory);
416 src_faces, src_mesh.corner_edges(),
VArraySpan(selection), memory);
426 const bool same_faces = face_mask.
size() == src_mesh.
faces_num;
437 src_faces, face_mask, dst_mesh->face_offsets_for_write());
void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH(type, var, list)
Object is a sort of wrapper for general info.
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
constexpr IndexRange index_range() const
constexpr int64_t size() const
constexpr bool is_empty() const
std::optional< T > get_if_single() const
bool add(const StringRef attribute_id, const AttrDomain domain, const AttrType data_type, const AttributeInit &initializer)
void foreach_index(Fn &&fn) const
static void copy_loose_edge_hint(const Mesh &src, Mesh &dst)
static void copy_overlapping_hint(const Mesh &src, Mesh &dst)
static void copy_loose_vert_hint(const Mesh &src, Mesh &dst)
void copy_attributes(const AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, MutableAttributeAccessor dst_attributes)
void gather_attributes(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
auto attribute_filter_with_skip_ref(AttributeFilter filter, const Span< StringRef > skip)
Mesh * mesh_new_no_attributes(int verts_num, int edges_num, int faces_num, int corners_num)
void gather_deform_verts(Span< MDeformVert > src, Span< int > indices, MutableSpan< MDeformVert > dst)
void gather_attributes_group_to_group(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
static void gather_vert_attributes(const Mesh &mesh_src, const bke::AttributeFilter &attribute_filter, const IndexMask &vert_mask, Mesh &mesh_dst)
IndexMask edge_selection_from_face(OffsetIndices< int > faces, const IndexMask &face_mask, Span< int > corner_edges, int edges_num, IndexMaskMemory &memory)
std::optional< Mesh * > mesh_copy_selection_keep_edges(const Mesh &mesh, const VArray< bool > &selection, bke::AttrDomain selection_domain, const bke::AttributeFilter &attribute_filter={})
static void remap_verts(const OffsetIndices< int > src_faces, const OffsetIndices< int > dst_faces, const int src_verts_num, const IndexMask &vert_mask, const IndexMask &edge_mask, const IndexMask &face_mask, const Span< int2 > src_edges, const Span< int > src_corner_verts, MutableSpan< int2 > dst_edges, MutableSpan< int > dst_corner_verts)
static void remap_edges(const OffsetIndices< int > src_faces, const OffsetIndices< int > dst_faces, const int src_edges_num, const IndexMask &edge_mask, const IndexMask &face_mask, const Span< int > src_corner_edges, MutableSpan< int > dst_corner_edges)
std::optional< Mesh * > mesh_copy_selection_keep_verts(const Mesh &src_mesh, const VArray< bool > &selection, bke::AttrDomain selection_domain, const bke::AttributeFilter &attribute_filter={})
IndexMask face_selection_from_edge(OffsetIndices< int > faces, Span< int > corner_edges, Span< bool > edge_mask, IndexMaskMemory &memory)
IndexMask face_selection_from_vert(OffsetIndices< int > faces, Span< int > corner_verts, Span< bool > vert_selection, IndexMaskMemory &memory)
std::optional< Mesh * > mesh_copy_selection(const Mesh &src_mesh, const VArray< bool > &selection, bke::AttrDomain selection_domain, const bke::AttributeFilter &attribute_filter={})
void build_reverse_map(const IndexMask &mask, MutableSpan< T > r_map)
template void build_reverse_map< int >(const IndexMask &mask, MutableSpan< int > r_map)
OffsetIndices< int > gather_selected_offsets(OffsetIndices< int > src_offsets, const IndexMask &selection, int start_offset, MutableSpan< int > dst_offsets)
void parallel_invoke(Functions &&...functions)
VecBase< int32_t, 2 > int2
MeshRuntimeHandle * runtime
ListBase vertex_group_names