56 if (
int *orig_indices =
static_cast<int *
>(
80 if (
id ==
".edge_verts") {
93 if (
int *orig_indices =
static_cast<int *
>(
115 if (corner_verts[corner] == vert) {
145 for (
const int start_corner : connected_corners) {
148 while (!corner_stack.is_empty()) {
149 const int corner = corner_stack.pop_last();
151 if (used_corners[
i]) {
154 used_corners[
i].set();
156 const int face = corner_to_face_map[corner];
159 for (
const int edge : {corner_edges[corner], corner_edges[prev_corner]}) {
163 for (
const int other_corner : edge_to_corner_map[edge]) {
164 const int other_face = corner_to_face_map[other_corner];
165 if (other_face == face) {
170 corner_verts, other_corner,
faces[other_face], vert);
171 corner_stack.append(neighbor_corner);
176 groups.
append(std::move(group));
199 new (&corner_groups[
mask])
206 vert_to_corner_map[vert],
209 return corner_groups;
225 for (
const int edge : vert_to_edge_map[vert]) {
226 if (loose_edges[edge]) {
261 new_verts_nums.slice(range).fill(-1);
262 for (const int i : range) {
263 new_verts_nums[i] += corner_groups[i].size();
266 if (!loose_edges.is_empty()) {
267 affected_verts.foreach_index(
GrainSize(512), [&](
const int vert,
const int mask) {
270 new_verts_nums[
mask] += info.selected.size();
271 if (corner_groups[
mask].is_empty()) {
273 new_verts_nums[
mask] += info.unselected.size() > 0;
291 for (const int new_vert : range) {
292 const Span<CornerGroup> groups = corner_groups[new_vert];
293 const IndexRange new_verts = new_verts_by_affected_vert[new_vert];
294 for (const int group : groups.index_range().drop_back(1)) {
295 const int new_vert = orig_verts_num + new_verts[group];
296 new_corner_verts.fill_indices(groups[group].as_span(), new_vert);
307 const int face = corner_to_face_map[corner];
309 return OrderedEdge(corner_verts[corner], corner_verts[corner_next]);
331 r_new_edge_offsets[
mask] = std::max<int>(edge_to_corner_map[edge].
size() - 1, 0);
339 std::atomic<bool> found_duplicate =
false;
349 if (edge_to_corner_map[edge].is_empty()) {
351 num_edges_per_edge_merged[
mask] = 0;
355 const int new_edges_start = offsets[
mask].start();
357 for (
const int corner : edge_to_corner_map[edge]) {
361 found_duplicate.store(
true, std::memory_order_relaxed);
368 is_reused[corner] =
true;
371 corner_edges[corner] = edges.
size() + new_edges_start + index - 1;
375 const int new_edges_num = deduplication.
size() - 1;
377 edges[edge] =
int2(deduplication.
first().v_low, deduplication.
first().v_high);
379 .slice(new_edges_start, new_edges_num)
380 .copy_from(deduplication.
as_span().drop_front(1).cast<
int2>());
382 num_edges_per_edge_merged[
mask] = new_edges_num;
385 if (!found_duplicate) {
392 num_edges_per_edge_merged);
394 const int difference = offsets[
mask].start() - offsets_merged[
mask].start();
395 for (
const int corner : edge_to_corner_map[edge]) {
396 if (!is_reused[corner]) {
397 corner_edges[corner] -= difference;
405 for (const int i : range) {
406 new_edges_merged.as_mutable_span()
407 .slice(offsets_merged[i])
408 .copy_from(new_edges.as_span().slice(offsets[i].start(), offsets_merged[i].size()));
412 r_new_edge_offsets.copy_from(num_edges_per_edge_merged);
413 return new_edges_merged;
424 const Span<int> edge_corners = edge_to_corner_map[edge];
428 const int corner = edge_corners.
first();
436 if (edge[0] == old_vert) {
439 else if (edge[1] == old_vert) {
464 int new_vert_i = std::max<int>(corner_groups[
mask].
size() - 1, 0);
465 if (new_vert_i == new_verts.
size()) {
470 for (
const int edge : vert_info.
selected) {
471 const int new_vert = orig_verts_num + new_verts[new_vert_i];
474 if (new_vert_i == new_verts.size()) {
478 const int new_vert = orig_verts_num + new_verts[new_vert_i];
479 for (
const int orig_edge : vert_info.
unselected) {
502 const int orig_verts_num = mesh.
verts_num;
508 orig_edges, selected_edges, orig_verts_num, memory);
510 selected_edges.
to_bits(selection_bits);
518 mesh.corner_edges(), orig_edges.
size(), edge_to_corner_offsets, edge_to_corner_indices);
523 if (loose_edges.
count > 0) {
525 orig_edges, orig_verts_num, vert_to_edge_offsets, vert_to_edge_indices);
528 const Array<int> corner_to_face_map = mesh.corner_to_face_map();
546 vert_new_vert_offset_data);
549 update_corner_verts(orig_verts_num, corner_groups, new_verts_by_affected_vert, corner_verts);
557 mesh.edges_for_write(),
558 mesh.corner_edges_for_write(),
566 mesh.edges_for_write());
568 if (loose_edges.
count > 0) {
575 new_verts_by_affected_vert,
576 mesh.edges_for_write());
581 mesh.edges_for_write().take_back(new_edges.
size()).copy_from(new_edges);
586 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
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
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