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);
71 const Span<int> corner_verts = mesh.corner_verts();
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;
180 const int parallel_maps = calc_edges::get_parallel_maps_count(mesh);
184 calc_edges::reserve_hash_maps(mesh, keep_existing_edges, edge_maps);
187 if (keep_existing_edges) {
188 calc_edges::add_existing_edges_to_hash_maps(mesh, parallel_mask, edge_maps);
190 calc_edges::add_face_edges_to_hash_maps(mesh, parallel_mask, edge_maps);
194 edge_sizes[i] = edge_maps[i].
size();
196 const OffsetIndices<int> edge_offsets = offset_indices::accumulate_counts_to_offsets(edge_sizes);
203 calc_edges::serialize_and_initialize_deduplicated_edges(edge_maps, edge_offsets, new_edges);
204 calc_edges::update_edge_indices_in_face_loops(mesh.faces(),
209 mesh.corner_edges_for_write());
212 if (keep_existing_edges && select_new_edges) {
223 if (select_new_edges) {
226 ".select_edge", AttrDomain::Edge);
228 select_edge.
span.fill(
true);
230 calc_edges::deselect_known_edges(
231 edge_offsets, edge_maps, parallel_mask, original_edges, select_edge.
span);
237 if (!keep_existing_edges) {
239 mesh.tag_loose_edges_none();
243 calc_edges::clear_hash_tables(edge_maps);
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
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
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)
int face_corner_prev(const IndexRange face, const int corner)
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
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))
PythonProbingStrategy<> DefaultProbingStrategy
unsigned __int64 uint64_t
MutableVArraySpan< T > span