53 if (
int *orig_indices =
static_cast<int *
>(
74 if (
id ==
".edge_verts") {
87 if (
int *orig_indices =
static_cast<int *
>(
105 array[edges[i][0]] =
true;
106 array[edges[i][1]] =
true;
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);
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;
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];
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);
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) {
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) {
517 const int orig_verts_num = mesh.
verts_num;
523 orig_edges, selected_edges, orig_verts_num, memory);
532 mesh.corner_edges(), orig_edges.
size(), edge_to_corner_offsets, edge_to_corner_indices);
537 if (loose_edges.
count > 0) {
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)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
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)
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
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(const 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 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)
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 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)
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)
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
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]
blender::BitVector is_loose_bits