40 const bool keep_existing_edges,
43 const int totedge_guess = std::max(keep_existing_edges ?
mesh.edges_num : 0,
mesh.faces_num * 2);
45 edge_maps, [&](
EdgeMap &edge_map) { edge_map.
reserve(totedge_guess / edge_maps.
size()); });
55 const int task_index = &edge_map - edge_maps.
data();
56 for (
const int2 edge : edges) {
59 if (task_index == (parallel_mask &
edge_hash_2(ordered_edge))) {
60 edge_map.
add(ordered_edge);
73 const int task_index = &edge_map - edge_maps.
data();
74 for (
const int face_i :
faces.index_range()) {
76 for (
const int corner : face) {
77 const int vert = corner_verts[corner];
80 if (
LIKELY(vert_prev != vert)) {
83 if (task_index == (parallel_mask &
edge_hash_2(ordered_edge))) {
84 edge_map.
add(ordered_edge);
97 const int task_index = &edge_map - edge_maps.
data();
98 if (edge_offsets[task_index].is_empty()) {
115 for (const int face_index : range) {
116 const IndexRange face = faces[face_index];
117 for (const int corner : face) {
118 const int vert = corner_verts[corner];
119 const int vert_prev = corner_verts[bke::mesh::face_corner_next(face, corner)];
120 if (UNLIKELY(vert == vert_prev)) {
124 corner_edges[corner] = 0;
128 const OrderedEdge ordered_edge(vert_prev, vert);
129 const int task_index = parallel_mask & edge_hash_2(ordered_edge);
130 const EdgeMap &edge_map = edge_maps[task_index];
131 const int edge_i = edge_map.index_of(ordered_edge);
132 const int edge_index = edge_offsets[task_index][edge_i];
133 corner_edges[corner] = edge_index;
142 if (
mesh.faces_num < 1000) {
163 for (const int2 original_edge : known_edges.slice(range)) {
164 const OrderedEdge ordered_edge(original_edge);
165 const int task_index = parallel_mask & edge_hash_2(ordered_edge);
166 const EdgeMap &edge_map = edge_maps[task_index];
167 const int edge_i = edge_map.index_of(ordered_edge);
168 const int edge_index = edge_offsets[task_index][edge_i];
169 selection[edge_index] = false;
187 if (keep_existing_edges) {
194 edge_sizes[i] = edge_maps[i].
size();
209 mesh.corner_edges_for_write());
212 if (keep_existing_edges && select_new_edges) {
223 if (select_new_edges) {
228 select_edge.
span.fill(
true);
231 edge_offsets, edge_maps, parallel_mask, original_edges, select_edge.
span);
237 if (!keep_existing_edges) {
239 mesh.tag_loose_edges_none();
CustomData interface, see also DNA_customdata_types.h.
void CustomData_reset(CustomData *data)
void CustomData_free(CustomData *data, int totelem)
MINLINE int power_of_2_min_i(int n)
MINLINE int is_power_of_2_i(int n)
int BLI_system_thread_count(void)
MutableSpan< T > as_mutable_span()
IndexRange index_range() const
void reinitialize(const int64_t new_size)
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr T * data() const
constexpr void copy_from(Span< T > values) const
constexpr IndexRange index_range() const
void reserve(const int64_t n)
Span< Key > as_span() const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
static void add_existing_edges_to_hash_maps(const Mesh &mesh, const uint32_t parallel_mask, MutableSpan< EdgeMap > edge_maps)
static uint64_t edge_hash_2(const OrderedEdge &edge)
static void update_edge_indices_in_face_loops(const OffsetIndices< int > faces, const Span< int > corner_verts, const Span< EdgeMap > edge_maps, const uint32_t parallel_mask, const OffsetIndices< int > edge_offsets, MutableSpan< int > corner_edges)
static void serialize_and_initialize_deduplicated_edges(MutableSpan< EdgeMap > edge_maps, const OffsetIndices< int > edge_offsets, MutableSpan< int2 > new_edges)
static int get_parallel_maps_count(const Mesh &mesh)
static void deselect_known_edges(const OffsetIndices< int > edge_offsets, const Span< EdgeMap > edge_maps, const uint32_t parallel_mask, const Span< int2 > known_edges, MutableSpan< bool > selection)
VectorSet< OrderedEdge, DefaultProbingStrategy, DefaultHash< OrderedEdge >, DefaultEquality< OrderedEdge >, SimpleVectorSetSlot< OrderedEdge, int >, GuardedAllocator > EdgeMap
static void clear_hash_tables(MutableSpan< EdgeMap > edge_maps)
static void reserve_hash_maps(const Mesh &mesh, const bool keep_existing_edges, MutableSpan< EdgeMap > edge_maps)
static void add_face_edges_to_hash_maps(const Mesh &mesh, const uint32_t parallel_mask, MutableSpan< EdgeMap > edge_maps)
int face_corner_prev(const IndexRange face, const int corner)
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
void parallel_for_each(Range &&range, const Function &function)
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
PythonProbingStrategy<> DefaultProbingStrategy
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[]
unsigned __int64 uint64_t
MutableVArraySpan< T > span