27 &mesh.vert_data, mesh.verts_num, mesh.verts_num + new_to_old_verts_map.
size());
28 mesh.verts_num += new_to_old_verts_map.
size();
31 for (
const StringRef id : attributes.all_ids()) {
53 if (
int *orig_indices =
static_cast<int *
>(
57 Span(orig_indices, mesh.verts_num),
67 mesh.edges_num += new_to_old_edge_map.
size();
70 for (
const StringRef id : attributes.all_ids()) {
74 if (
id ==
".edge_verts") {
83 attribute.span, new_to_old_edge_map, attribute.span.
take_back(new_to_old_edge_map.
size()));
87 if (
int *orig_indices =
static_cast<int *
>(
91 Span(orig_indices, mesh.edges_num),
105 array[edges[i][0]] =
true;
106 array[edges[i][1]] =
true;
114 selection.to_bits(bits);
130 if (corner_verts[corner] == vert) {
160 for (
const int start_corner : connected_corners) {
163 while (!corner_stack.is_empty()) {
164 const int corner = corner_stack.
pop_last();
165 const int i = connected_corners.
first_index(corner);
166 if (used_corners[i]) {
169 used_corners[i].set();
171 const int face = corner_to_face_map[corner];
174 for (
const int edge : {corner_edges[corner], corner_edges[prev_corner]}) {
178 for (
const int other_corner : edge_to_corner_map[edge]) {
179 const int other_face = corner_to_face_map[other_corner];
180 if (other_face == face) {
185 corner_verts, other_corner, faces[other_face], vert);
186 corner_stack.append(neighbor_corner);
190 if (!group.is_empty()) {
191 groups.append(std::move(group));
214 new (&corner_groups[
mask])
221 vert_to_corner_map[vert],
224 return corner_groups;
240 for (
const int edge : vert_to_edge_map[vert]) {
241 if (loose_edges[edge]) {
276 new_verts_nums.slice(range).fill(-1);
277 for (const int i : range) {
278 new_verts_nums[i] += corner_groups[i].size();
281 if (!loose_edges.is_empty()) {
282 affected_verts.foreach_index(
GrainSize(512), [&](
const int vert,
const int mask) {
285 new_verts_nums[
mask] += info.selected.size();
286 if (corner_groups[mask].is_empty()) {
288 new_verts_nums[
mask] += info.unselected.size() > 0;
305 threading::parallel_for(corner_groups.index_range(), 512, [&](
const IndexRange range) {
306 for (const int new_vert : range) {
307 const Span<CornerGroup> groups = corner_groups[new_vert];
308 const IndexRange new_verts = new_verts_by_affected_vert[new_vert];
309 for (const int group : groups.index_range().drop_back(1)) {
310 const int new_vert = orig_verts_num + new_verts[group];
311 new_corner_verts.fill_indices(groups[group].as_span(), new_vert);
322 const int face = corner_to_face_map[corner];
323 const int corner_next = bke::mesh::face_corner_next(faces[face], corner);
324 return OrderedEdge(corner_verts[corner], corner_verts[corner_next]);
346 r_new_edge_offsets[
mask] = std::max<int>(edge_to_corner_map[edge].
size() - 1, 0);
348 const OffsetIndices offsets = offset_indices::accumulate_counts_to_offsets(r_new_edge_offsets);
354 std::atomic<bool> found_duplicate =
false;
364 if (edge_to_corner_map[edge].is_empty()) {
366 num_edges_per_edge_merged[
mask] = 0;
370 const int new_edges_start = offsets[
mask].start();
372 for (
const int corner : edge_to_corner_map[edge]) {
376 found_duplicate.store(
true, std::memory_order_relaxed);
383 is_reused[corner] =
true;
386 corner_edges[corner] = edges.
size() + new_edges_start + index - 1;
390 const int new_edges_num = deduplication.
size() - 1;
392 edges[edge] =
int2(deduplication.
first().v_low, deduplication.
first().v_high);
394 .slice(new_edges_start, new_edges_num)
395 .copy_from(deduplication.
as_span().drop_front(1).cast<
int2>());
397 num_edges_per_edge_merged[
mask] = new_edges_num;
400 if (!found_duplicate) {
406 const OffsetIndices offsets_merged = offset_indices::accumulate_counts_to_offsets(
407 num_edges_per_edge_merged);
409 const int difference = offsets[
mask].start() - offsets_merged[mask].start();
410 for (
const int corner : edge_to_corner_map[edge]) {
411 if (!is_reused[corner]) {
412 corner_edges[corner] -= difference;
420 for (const int i : range) {
421 new_edges_merged.as_mutable_span()
422 .slice(offsets_merged[i])
423 .copy_from(new_edges.as_span().slice(offsets[i].start(), offsets_merged[i].size()));
427 r_new_edge_offsets.copy_from(num_edges_per_edge_merged);
428 return new_edges_merged;
439 const Span<int> edge_corners = edge_to_corner_map[edge];
443 const int corner = edge_corners.
first();
451 if (edge[0] == old_vert) {
454 else if (edge[1] == old_vert) {
479 int new_vert_i = std::max<int>(corner_groups[mask].
size() - 1, 0);
480 if (new_vert_i == new_verts.
size()) {
485 for (
const int edge : vert_info.
selected) {
486 const int new_vert = orig_verts_num + new_verts[new_vert_i];
489 if (new_vert_i == new_verts.size()) {
493 const int new_vert = orig_verts_num + new_verts[new_vert_i];
494 for (
const int orig_edge : vert_info.
unselected) {
507 mask.foreach_index(
GrainSize(1024), [&](
const int i,
const int mask) {
508 map.as_mutable_span().slice(offsets[mask]).fill(i);
517 const int orig_verts_num = mesh.verts_num;
523 orig_edges, selected_edges, orig_verts_num, memory);
531 const GroupedSpan<int> edge_to_corner_map = bke::mesh::build_edge_to_corner_map(
532 mesh.corner_edges(), orig_edges.
size(), edge_to_corner_offsets, edge_to_corner_indices);
537 if (loose_edges.
count > 0) {
538 vert_to_edge_map = bke::mesh::build_vert_to_edge_map(
539 orig_edges, orig_verts_num, vert_to_edge_offsets, vert_to_edge_indices);
542 const Array<int> corner_to_face_map = mesh.corner_to_face_map();
560 vert_new_vert_offset_data);
563 update_corner_verts(orig_verts_num, corner_groups, new_verts_by_affected_vert, corner_verts);
571 mesh.edges_for_write(),
572 mesh.corner_edges_for_write(),
580 mesh.edges_for_write());
582 if (loose_edges.
count > 0) {
589 new_verts_by_affected_vert,
590 mesh.edges_for_write());
595 mesh.edges_for_write().take_back(new_edges.
size()).copy_from(new_edges);
600 mesh.tag_edges_split();
CustomData interface, see also DNA_customdata_types.h.
void CustomData_realloc(CustomData *data, int old_size, int new_size, eCDAllocType alloctype=CD_CONSTRUCT)
void CustomData_free_layers(CustomData *data, eCustomDataType type, int totelem)
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
void reinitialize(const int64_t new_size)
constexpr int64_t size() const
constexpr int64_t size() const
constexpr MutableSpan take_back(const int64_t n) const
constexpr Span take_back(int64_t n) const
constexpr const T & first() const
constexpr int64_t first_index(const T &search_value) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
int64_t append_and_get_index(const T &value)
void append(const T &value)
Span< T > as_span() const
int64_t first_index_of_try(const T &value) const
void append(const bool value)
void foreach_index_optimized(Fn &&fn) const
IndexRange index_range() const
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
void foreach_index(Fn &&fn) const
IndexRange index_range() const
ccl_device_inline float4 mask(const int4 mask, const float4 a)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void gather(GSpan src, Span< int > map, GMutableSpan dst)
int face_corner_prev(const IndexRange face, const int corner)
int face_corner_next(const IndexRange face, const int corner)
void debug_randomize_edge_order(Mesh *mesh)
static Array< int > offsets_to_map(const IndexMask &mask, const OffsetIndices< int > offsets)
static BitVector selection_to_bit_vector(const IndexMask &selection, const int total_size)
void split_edges(Mesh &mesh, const IndexMask &mask, const bke::AttributeFilter &attribute_filter={})
static Vector< CornerGroup > calc_corner_groups_for_vertex(const OffsetIndices< int > faces, const Span< int > corner_verts, const Span< int > corner_edges, const GroupedSpan< int > edge_to_corner_map, const Span< int > corner_to_face_map, const BitSpan split_edges, const Span< int > connected_corners, const int vert)
static void reassign_loose_edge_verts(const int orig_verts_num, const IndexMask &affected_verts, const GroupedSpan< int > vert_to_edge_map, const BitSpan loose_edges, const BitSpan split_edges, const Span< Vector< CornerGroup > > corner_groups, const OffsetIndices< int > new_verts_by_affected_vert, MutableSpan< int2 > edges)
static Array< int2 > calc_new_edges(const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > edge_to_corner_map, const Span< int > corner_to_face_map, const IndexMask &selected_edges, MutableSpan< int2 > edges, MutableSpan< int > corner_edges, MutableSpan< int > r_new_edge_offsets)
static void propagate_vert_attributes(Mesh &mesh, const Span< int > new_to_old_verts_map)
static OrderedEdge edge_from_corner(const OffsetIndices< int > faces, const Span< int > corner_verts, const Span< int > corner_to_face_map, const int corner)
static BLI_NOINLINE Array< Vector< CornerGroup > > calc_all_corner_groups(const OffsetIndices< int > faces, const Span< int > corner_verts, const Span< int > corner_edges, const GroupedSpan< int > vert_to_corner_map, const GroupedSpan< int > edge_to_corner_map, const Span< int > corner_to_face_map, const BitSpan split_edges, const IndexMask &affected_verts)
static OffsetIndices< int > calc_vert_ranges_per_old_vert(const IndexMask &affected_verts, const Span< Vector< CornerGroup > > corner_groups, const GroupedSpan< int > vert_to_edge_map, const BitSpan loose_edges, const BitSpan split_edges, Array< int > &offset_data)
void debug_randomize_vert_order(Mesh *mesh)
static VertLooseEdges calc_vert_loose_edges(const GroupedSpan< int > vert_to_edge_map, const BitSpan loose_edges, const BitSpan split_edges, const int vert)
static void swap_edge_vert(int2 &edge, const int old_vert, const int new_vert)
static int corner_on_edge_connected_to_vert(const Span< int > corner_verts, const int corner, const IndexRange face, const int vert)
static void update_unselected_edges(const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > edge_to_corner_map, const Span< int > corner_to_face_map, const IndexMask &unselected_edges, MutableSpan< int2 > edges)
static void propagate_edge_attributes(Mesh &mesh, const Span< int > new_to_old_edge_map)
IndexMask vert_selection_from_edge(Span< int2 > edges, const IndexMask &edge_mask, int verts_num, IndexMaskMemory &memory)
static void update_corner_verts(const int orig_verts_num, const Span< Vector< CornerGroup > > corner_groups, const OffsetIndices< int > new_verts_by_affected_vert, MutableSpan< int > new_corner_verts)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
blender::BitVector is_loose_bits