30 for (
const int i :
indices.index_range()) {
60 if (src_mesh.
runtime->face_normals_cache.is_cached()) {
61 return src_mesh.face_normals();
63 if (selection_size > src_mesh.
faces_num / 4) {
64 return src_mesh.face_normals();
71 const auto &src_cache = src.
runtime->loose_verts_cache;
72 if (src_cache.is_cached() && src_cache.data().count == 0) {
73 dst.tag_loose_verts_none();
103 if (
UNLIKELY(flip_flag & (1 << 0))) {
106 if (
UNLIKELY(flip_flag & (1 << 1))) {
166 switch (directions[
i]) {
174 const int src_face_start = face_offsets[
i];
175 for (
int &
i : quad_map) {
196 data.directions.reinitialize(quads.
size());
216 dst_offsets[
i] = offset;
217 offset += src_offsets[selection[
i]].
size();
219 dst_offsets.
last() = offset;
251 Heap *heap =
nullptr;
270 data.offset_data.reinitialize(ngons.
size() + 1);
272 src_faces, ngons,
data.offset_data);
275 data.projections.reinitialize(ngons.
size());
292 data.projected_positions.reinitialize(local_corner_offsets.
total_size());
322 reinterpret_cast<uint(*)[3]
>(map.
data()));
326 reinterpret_cast<uint(*)[3]
>(map.
data()),
337 const int src_face_start = src_faces[ngons[
i]].start();
339 for (
int &vert : map) {
340 vert += src_face_start;
358 BLI_assert(std::is_sorted(&tri_verts[0], &tri_verts[0] + 3));
370 BLI_assert(std::is_sorted(&value[0], &value[0] + 3));
385 return b.tri_lower_vert == a[0] &&
tris[
b.tri_index] == a;
392 res[0] = std::min({tri[0], tri[1], tri[2]});
393 res[2] = std::max({tri[0], tri[1], tri[2]});
394 res[1] = (tri[0] - res[0]) + (tri[2] - res[2]) + tri[1];
401 for (int3 &tri : tris.slice(range)) {
402 tri = tri_to_ordered(tri);
425 return universe_segment.
offset();
429 for (
const int16_t
i : universe_segment.
base_span()) {
430 const int face = int(universe_segment.
offset() +
i);
431 if (src_faces[face].
size() == 3) {
435 return universe_segment.
offset();
452 const int3 corner_tri(&corner_verts[
faces[face_i].start()]);
461 for (const int face_i : range) {
462 indices[face_i] = faces[face_i].tri_index;
493 const Span<float3> positions = src_mesh.vert_positions();
495 const Span<int> src_corner_verts = src_mesh.corner_verts();
508 selection,
GrainSize(4096), memory, [&](
const int i) {
return src_faces[
i].
size() == 4; });
510 selection,
GrainSize(4096), memory, [&](
const int i) {
return src_faces[
i].
size() > 4; });
511 if (quads.
is_empty() && ngons.is_empty()) {
518 Array<int> tris_by_ngon_data(ngons.size() + 1);
520 const int ngon_tris_num = tris_by_ngon.
total_size();
521 const int quad_tris_num = quads.
size() * 2;
522 const IndexRange tris_range(ngon_tris_num + quad_tris_num);
526 Array<int3> corner_tris(ngon_tris_num + quad_tris_num);
528 if (!ngons.is_empty()) {
551 Array<int3> vert_tris(ngon_tris_num + quad_tris_num);
553 corner_tris.
as_span().cast<
int>(),
571 for (
const int face_i : ordered_vert_tris.
index_range()) {
572 const TriKey face_key(face_i, ordered_vert_tris);
573 unique_tris.add(face_key);
575 const int unique_tri_num = unique_tris.size();
581 src_tris, src_faces, src_corner_verts, unique_tris, memory);
588 const IndexRange unique_faces_range(unique_tri_num + unique_src_faces.
size());
603 const int total_new_tri_corners = unique_tri_range.
size() * 3;
607 total_new_tri_corners,
622 const bool has_duplicate_faces = unique_tri_num != (ngon_tris_num + quad_tris_num);
624 Array<int> dst_tri_to_src_face(unique_tri_num);
628 if (has_duplicate_faces) {
636 Array<int> src_to_unique_map(ngon_tris_num + quad_tris_num);
639 ngons, tris_by_ngon, src_to_unique_map.
as_mutable_span().slice(ngon_tris_range));
646 const Span<int3> unique_corner_tris = has_duplicate_faces ? unique_corner_tris_data.
as_span() :
653 attribute.src, dst_tri_to_src_face.
as_span(), attribute.dst.span.slice(unique_tri_range));
655 attribute.src, unique_src_faces, attribute.dst.span.
slice(unique_src_faces_range));
656 attribute.dst.finish();
674 faces.slice(unique_src_faces_range),
679 unique_corner_tris.
cast<
int>(),
680 corner_verts.take_front(total_new_tri_corners));
687 {
".corner_vert",
".corner_edge"})))
696 unique_corner_tris.
cast<
int>(),
697 attribute.dst.span.slice(0, unique_tri_num * 3));
698 attribute.dst.finish();
706 if (src_mesh.no_overlapping_topology()) {
707 mesh->tag_overlapping_none();
@ ATTR_DOMAIN_MASK_CORNER
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
bool CustomData_merge(const CustomData *source, CustomData *dest, eCustomDataMask mask, int totelem)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
const CustomData_MeshMasks CD_MASK_MESH
void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
bool BKE_mesh_is_valid(Mesh *mesh)
A min-heap / priority queue ADT.
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) ATTR_NONNULL(1)
Heap * BLI_heap_new_ex(unsigned int reserve_num) ATTR_WARN_UNUSED_RESULT
int is_quad_flip_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
void BLI_memarena_free(MemArena *ma) ATTR_NONNULL(1)
void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
#define BLI_POLYFILL_ARENA_SIZE
void BLI_polyfill_calc(const float(*coords)[2], unsigned int coords_num, int coords_sign, unsigned int(*r_tris)[3])
#define BLI_POLYFILL_ALLOC_NGON_RESERVE
void BLI_polyfill_beautify(const float(*coords)[2], unsigned int coords_num, unsigned int(*tris)[3], struct MemArena *arena, struct Heap *eheap)
float BLI_polyfill_edge_calc_rotate_beauty__area(const float v1[3], const float v2[3], const float v3[3], const float v4[3], bool lock_degenerate)
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
static IndexMask from_batch_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, FunctionRef< int64_t(const IndexMaskSegment &universe_segment, IndexRangesBuilder< int16_t > &builder)> batch_predicate)
static IndexMask from_difference(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
void reinitialize(const int64_t new_size)
constexpr int64_t one_after_last() const
constexpr IndexRange shift(int64_t n) const
constexpr int64_t size() const
constexpr int64_t start() const
constexpr IndexRange take_back(int64_t n) const
constexpr IndexRange take_front(int64_t n) const
bool add_range(const T start, const T end)
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr MutableSpan< NewT > cast() const
constexpr MutableSpan take_back(const int64_t n) const
constexpr T * data() const
constexpr void fill(const T &value) const
constexpr IndexRange index_range() const
constexpr void copy_from(Span< T > values) const
constexpr MutableSpan take_front(const int64_t n) const
constexpr T & last(const int64_t n=0) const
IndexRange index_range() const
Span< BaseT > base_span() const
constexpr Span drop_front(int64_t n) const
Span< NewT > constexpr cast() const
constexpr Span slice(int64_t start, int64_t size) const
constexpr const T * data() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
void reinitialize(const int64_t new_size)
Span< T > as_span() const
bool add(const StringRef attribute_id, const AttrDomain domain, const AttrType data_type, const AttributeInit &initializer)
const DifferenceExpr & subtract(const Term &main_term, const Span< Term > subtract_terms)
void foreach_index_optimized(Fn &&fn) const
IndexMask slice(IndexRange range) const
IndexRange index_range() const
void foreach_index(Fn &&fn) const
void foreach_segment(Fn &&fn) const
IndexRange index_range() const
OffsetIndices slice(const IndexRange range) const
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static void copy_loose_vert_hint(const Mesh &src, Mesh &dst)
void gather_group_to_group(const OffsetIndices< int > src_offsets, const OffsetIndices< int > dst_offsets, const IndexMask &selection, const Span< T > src, MutableSpan< T > dst)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void gather(GSpan src, Span< int > map, GMutableSpan dst)
void gather_group_to_group(OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, GSpan src, GMutableSpan dst)
float3 face_normal_calc(Span< float3 > vert_positions, Span< int > face_verts)
int face_triangles_num(const int face_size)
Vector< AttributeTransferData > retrieve_attributes_for_transfer(const AttributeAccessor src_attributes, MutableAttributeAccessor dst_attributes, AttrDomainMask domain_mask, const AttributeFilter &attribute_filter={})
auto attribute_filter_with_skip_ref(AttributeFilter filter, const Span< StringRef > skip)
Mesh * mesh_new_no_attributes(int verts_num, int edges_num, int faces_num, int corners_num)
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
static void calc_corner_tris(const Span< float3 > positions, const OffsetIndices< int > src_faces, const Span< int > src_corner_verts, const Span< float3 > face_normals, const IndexMask &ngons, const OffsetIndices< int > tris_by_ngon, const TriangulateNGonMode ngon_mode, MutableSpan< int3 > corner_tris)
static OffsetIndices< int > calc_tris_by_ngon(const OffsetIndices< int > src_faces, const IndexMask &ngons, MutableSpan< int > face_offset_data)
static void calc_corner_tris(const Span< int > face_offsets, const Span< QuadDirection > directions, MutableSpan< int3 > corner_tris)
static void calc_quad_directions(const Span< float3 > positions, const Span< int > face_offsets, const Span< int > corner_verts, const TriangulateQuadMode quad_mode, MutableSpan< QuadDirection > directions)
static QuadDirection calc_quad_direction_beauty(const float3 &v0, const float3 &v1, const float3 &v2, const float3 &v3)
std::optional< Mesh * > mesh_triangulate(const Mesh &src_mesh, const IndexMask &selection, TriangulateNGonMode ngon_mode, TriangulateQuadMode quad_mode, const bke::AttributeFilter &attribute_filter)
static void ngon_indices_of_tris(const IndexMask &ngons, const OffsetIndices< int > tris_by_ngon, MutableSpan< int > indices)
static void gather(const Span< int > src, const Span< int16_t > indices, MutableSpan< int > dst)
static Span< int3 > tri_to_ordered_tri(MutableSpan< int3 > tris)
static void quad_indices_of_tris(const IndexMask &quads, MutableSpan< int > indices)
static int3 tri_to_ordered(const int3 tri)
static void face_keys_to_face_indices(const Span< TriKey > faces, MutableSpan< int > indices)
static OffsetIndices< int > gather_selected_offsets(const OffsetIndices< int > src_offsets, const IndexMaskSegment selection, MutableSpan< int > dst_offsets)
static Span< float3 > face_normals_if_worthwhile(const Mesh &src_mesh, const int selection_size)
static Span< int > gather_or_reference(const Span< int > src, const Span< int16_t > indices, Vector< int > &dst)
static IndexMask face_tris_mask(const OffsetIndices< int > src_faces, const IndexMask &mask, IndexMaskMemory &memory)
static void copy_loose_vert_hint(const Mesh &src, Mesh &dst)
static IndexMask tris_in_set(const IndexMask &tri_mask, const OffsetIndices< int > faces, const Span< int > corner_verts, const VectorSet< TriKey, 4, DefaultProbingStrategy, FaceHash, FacesEquality, SimpleVectorSetSlot< TriKey, int > > &unique_tris, IndexMaskMemory &memory)
IndexMask evaluate_expression(const Expr &expression, IndexMaskMemory &memory)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
void fill_constant_group_size(int size, int start_offset, MutableSpan< int > offsets)
OffsetIndices< int > gather_selected_offsets(OffsetIndices< int > src_offsets, const IndexMask &selection, int start_offset, MutableSpan< int > dst_offsets)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
bool non_empty_is_range(const Span< T > indices)
IndexRange non_empty_as_range(const Span< T > indices)
VecBase< int32_t, 3 > int3
MatBase< float, 3, 3 > float3x3
PythonProbingStrategy<> DefaultProbingStrategy
VecBase< float, 3 > float3
MeshRuntimeHandle * runtime
const c_style_mat & ptr() const
uint64_t operator()(const TriKey value) const
uint64_t operator()(const int3 value) const
bool operator()(const TriKey a, const TriKey b) const
bool operator()(const int3 a, const TriKey b) const
TriKey(const int tri_index, Span< int3 > tris)