42 const bool keep_existing_edges,
45 const int totedge_guess = std::max(keep_existing_edges ?
mesh.edges_num : 0,
mesh.faces_num * 2);
47 edge_maps, [&](
EdgeMap &edge_map) { edge_map.
reserve(totedge_guess / edge_maps.
size()); });
51 const uint32_t parallel_mask,
57 const int task_index = &edge_map - edge_maps.
data();
58 for (
const int2 edge : edges) {
61 if (task_index == (parallel_mask &
edge_hash_2(ordered_edge))) {
62 edge_map.
add(ordered_edge);
69 const uint32_t parallel_mask,
75 const int task_index = &edge_map - edge_maps.
data();
76 for (
const int face_i :
faces.index_range()) {
78 for (
const int corner : face) {
79 const int vert = corner_verts[corner];
82 if (
LIKELY(vert_prev != vert)) {
85 if (task_index == (parallel_mask &
edge_hash_2(ordered_edge))) {
86 edge_map.
add(ordered_edge);
99 const int task_index = &edge_map - edge_maps.
data();
100 if (edge_offsets[task_index].is_empty()) {
112 const uint32_t parallel_mask,
117 for (const int face_index : range) {
118 const IndexRange face = faces[face_index];
119 for (const int corner : face) {
120 const int vert = corner_verts[corner];
121 const int vert_prev = corner_verts[bke::mesh::face_corner_next(face, corner)];
122 if (UNLIKELY(vert == vert_prev)) {
126 corner_edges[corner] = 0;
130 const OrderedEdge ordered_edge(vert_prev, vert);
131 const int task_index = parallel_mask & edge_hash_2(ordered_edge);
132 const EdgeMap &edge_map = edge_maps[task_index];
133 const int edge_i = edge_map.index_of(ordered_edge);
134 const int edge_index = edge_offsets[task_index][edge_i];
135 corner_edges[corner] = edge_index;
144 if (
mesh.faces_num < 1000) {
160 const uint32_t parallel_mask,
165 for (const int2 original_edge : known_edges.slice(range)) {
166 const OrderedEdge ordered_edge(original_edge);
167 const int task_index = parallel_mask & edge_hash_2(ordered_edge);
168 const EdgeMap &edge_map = edge_maps[task_index];
169 const int edge_i = edge_map.index_of(ordered_edge);
170 const int edge_index = edge_offsets[task_index][edge_i];
171 selection[edge_index] = false;
184 const uint32_t parallel_mask = uint32_t(parallel_maps) - 1;
189 if (keep_existing_edges) {
196 edge_sizes[
i] = edge_maps[
i].
size();
211 mesh.corner_edges_for_write());
214 if (keep_existing_edges && select_new_edges) {
225 if (select_new_edges) {
230 select_edge.
span.fill(
true);
233 edge_offsets, edge_maps, parallel_mask, original_edges, select_edge.
span);
239 if (!keep_existing_edges) {
241 mesh.tag_loose_edges_none();
CustomData interface, see also DNA_customdata_types.h.
void CustomData_reset(CustomData *data)
void CustomData_free(CustomData *data)
MINLINE int power_of_2_min_i(int n)
MINLINE int is_power_of_2_i(int n)
int BLI_system_thread_count(void)
unsigned long long int uint64_t
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 * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
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)
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)
VectorSet< OrderedEdge, 16, DefaultProbingStrategy, DefaultHash< OrderedEdge >, DefaultEquality< OrderedEdge >, SimpleVectorSetSlot< OrderedEdge, int >, GuardedAllocator > EdgeMap
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
MutableVArraySpan< T > span