56 if (
int *orig_indices =
static_cast<int *
>(
81 if (
id ==
".edge_verts") {
94 if (
int *orig_indices =
static_cast<int *
>(
116 if (corner_verts[corner] == vert) {
146 for (
const int start_corner : connected_corners) {
149 while (!corner_stack.is_empty()) {
150 const int corner = corner_stack.pop_last();
152 if (used_corners[
i]) {
155 used_corners[
i].set();
157 const int face = corner_to_face_map[corner];
160 for (
const int edge : {corner_edges[corner], corner_edges[prev_corner]}) {
164 for (
const int other_corner : edge_to_corner_map[edge]) {
165 const int other_face = corner_to_face_map[other_corner];
166 if (other_face == face) {
171 corner_verts, other_corner,
faces[other_face], vert);
172 corner_stack.append(neighbor_corner);
177 groups.
append(std::move(group));
200 new (&corner_groups[
mask])
207 vert_to_corner_map[vert],
210 return corner_groups;
226 for (
const int edge : vert_to_edge_map[vert]) {
227 if (loose_edges[edge]) {
262 new_verts_nums.slice(range).fill(-1);
263 for (const int i : range) {
264 new_verts_nums[i] += corner_groups[i].size();
267 if (!loose_edges.is_empty()) {
268 affected_verts.foreach_index(
GrainSize(512), [&](
const int vert,
const int mask) {
271 new_verts_nums[
mask] += info.selected.size();
272 if (corner_groups[
mask].is_empty()) {
274 new_verts_nums[
mask] += info.unselected.size() > 0;
292 for (const int new_vert : range) {
293 const Span<CornerGroup> groups = corner_groups[new_vert];
294 const IndexRange new_verts = new_verts_by_affected_vert[new_vert];
295 for (const int group : groups.index_range().drop_back(1)) {
296 const int new_vert = orig_verts_num + new_verts[group];
297 new_corner_verts.fill_indices(groups[group].as_span(), new_vert);
308 const int face = corner_to_face_map[corner];
310 return OrderedEdge(corner_verts[corner], corner_verts[corner_next]);
332 r_new_edge_offsets[
mask] = std::max<int>(edge_to_corner_map[edge].
size() - 1, 0);
340 std::atomic<bool> found_duplicate =
false;
350 if (edge_to_corner_map[edge].is_empty()) {
352 num_edges_per_edge_merged[
mask] = 0;
356 const int new_edges_start = offsets[
mask].start();
358 for (
const int corner : edge_to_corner_map[edge]) {
362 found_duplicate.store(
true, std::memory_order_relaxed);
369 is_reused[corner] =
true;
372 corner_edges[corner] = edges.
size() + new_edges_start + index - 1;
380 .slice(new_edges_start, new_edges_num)
383 num_edges_per_edge_merged[
mask] = new_edges_num;
386 if (!found_duplicate) {
393 num_edges_per_edge_merged);
395 const int difference = offsets[
mask].start() - offsets_merged[
mask].start();
396 for (
const int corner : edge_to_corner_map[edge]) {
397 if (!is_reused[corner]) {
398 corner_edges[corner] -= difference;
406 for (const int i : range) {
407 new_edges_merged.as_mutable_span()
408 .slice(offsets_merged[i])
409 .copy_from(new_edges.as_span().slice(offsets[i].start(), offsets_merged[i].size()));
413 r_new_edge_offsets.copy_from(num_edges_per_edge_merged);
414 return new_edges_merged;
425 const Span<int> edge_corners = edge_to_corner_map[edge];
429 const int corner = edge_corners.
first();
437 if (edge[0] == old_vert) {
440 else if (edge[1] == old_vert) {
465 int new_vert_i = std::max<int>(corner_groups[
mask].
size() - 1, 0);
466 if (new_vert_i == new_verts.
size()) {
471 for (
const int edge : vert_info.
selected) {
472 const int new_vert = orig_verts_num + new_verts[new_vert_i];
475 if (new_vert_i == new_verts.size()) {
479 const int new_vert = orig_verts_num + new_verts[new_vert_i];
480 for (
const int orig_edge : vert_info.
unselected) {
503 const int orig_verts_num = mesh.
verts_num;
509 orig_edges, selected_edges, orig_verts_num, memory);
511 selected_edges.
to_bits(selection_bits);
519 mesh.corner_edges(), orig_edges.
size(), edge_to_corner_offsets, edge_to_corner_indices);
524 if (loose_edges.
count > 0) {
526 orig_edges, orig_verts_num, vert_to_edge_offsets, vert_to_edge_indices);
529 const Array<int> corner_to_face_map = mesh.corner_to_face_map();
547 vert_new_vert_offset_data);
550 update_corner_verts(orig_verts_num, corner_groups, new_verts_by_affected_vert, corner_verts);
558 mesh.edges_for_write(),
559 mesh.corner_edges_for_write(),
567 mesh.edges_for_write());
569 if (loose_edges.
count > 0) {
576 new_verts_by_affected_vert,
577 mesh.edges_for_write());
582 mesh.edges_for_write().take_back(new_edges.
size()).copy_from(new_edges);
587 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)
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)
GMutableSpan take_back(const int64_t n) const
constexpr int64_t size() const
constexpr int64_t size() const
constexpr MutableSpan take_back(const 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
void append(const T &value)
Set< StringRefNull > all_ids() const
std::optional< AttributeMetaData > lookup_meta_data(StringRef attribute_id) const
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
void foreach_index_optimized(Fn &&fn) const
IndexRange index_range() const
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
void to_bits(MutableBitSpan r_bits, int64_t offset=0) const
void foreach_index(Fn &&fn) const
IndexRange index_range() const
ccl_device_inline float2 mask(const MaskType mask, const float2 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)
GroupedSpan< int > build_edge_to_corner_map(Span< int > corner_edges, int edges_num, Array< int > &r_offsets, Array< int > &r_indices)
int face_corner_prev(const IndexRange face, const int corner)
int face_corner_next(const IndexRange face, const int corner)
GroupedSpan< int > build_vert_to_edge_map(Span< int2 > edges, int verts_num, Array< int > &r_offsets, Array< int > &r_indices)
void debug_randomize_edge_order(Mesh *mesh)
static Array< int > offsets_to_map(const IndexMask &mask, const OffsetIndices< int > offsets)
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)
Vector< int > CornerGroup
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)
void split_edges(Mesh &mesh, const IndexMask &selected_edges, const bke::AttributeFilter &attribute_filter={})
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))
VecBase< int32_t, 2 > int2
VecBase< float, 3 > float3
blender::BitVector is_loose_bits