46 if (
faces.is_empty()) {
49 const int corners_num =
faces.total_size();
55 if (!vmap->
vert || !vmap->
buf) {
64 for (const int64_t face : range) {
65 const Span<float2> face_uvs = uv_map.slice(faces[face]);
66 winding[face] = cross_poly_v2(reinterpret_cast<const float (*)[2]>(face_uvs.data()),
67 uint(faces[face].size())) < 0.0f;
75 buf->loop_of_face_index =
ushort(
i);
76 buf->face_index =
uint(a);
77 buf->separate =
false;
78 buf->next = vmap->vert[corner_verts[face[
i]]];
79 vmap->vert[corner_verts[face[
i]]] = buf;
86 UvMapVert *newvlist =
nullptr, *vlist = vmap->vert[vert];
88 const float *uv, *uv2;
97 uv = uv_map[
faces[
v->face_index].start() +
v->loop_of_face_index];
107 if (
fabsf(uv[0] - uv2[0]) < limit[0] &&
fabsf(uv[1] - uv2[1]) < limit[1] &&
108 (!use_winding || winding[iterv->
face_index] == winding[
v->face_index]))
116 iterv->
next = newvlist;
129 vmap->vert[vert] = newvlist;
137 return vmap->
vert[
v];
158 const int *corner_verts,
167 for (
i = 0;
i < tris_num;
i++) {
168 for (
int j = 3; j--;) {
169 map[corner_verts[corner_tris[
i][j]]].
count++;
175 for (
i = 0;
i < totvert;
i++) {
177 index_step += map[
i].
count;
184 for (
i = 0;
i < tris_num;
i++) {
185 for (
int j = 3; j--;) {
186 MeshElemMap *map_ele = &map[corner_verts[corner_tris[
i][j]]];
198 const int *final_origindex,
207 for (
i = 0;
i < totfinal;
i++) {
210 map[final_origindex[
i]].
count++;
216 for (
i = 0;
i < totsource;
i++) {
218 index_step += map[
i].
count;
225 for (
i = 0;
i < totfinal;
i++) {
239 const int *corner_tri_faces,
240 const int corner_tris_num)
254 for (
int i = 0;
i < corner_tris_num;
i++) {
273 const int grain_size,
277 for (const int64_t index : range) {
278 MutableSpan<int> group = indices.slice(groups[index]);
279 std::sort(group.begin(), group.end());
301 for (const int64_t i : range) {
302 const int group_index = group_indices[i];
303 const int index_in_group = atomic_fetch_and_add_int32(&counts[group_index], 1);
304 results[offsets[group_index][index_in_group]] = int(i);
307 sort_small_groups(offsets, 1024, results);
320 for (const int64_t face : range) {
321 for (const int elem : group_to_elem.slice(groups[face])) {
322 const int index_in_group = atomic_fetch_and_add_int32(&counts[elem], 1);
323 results[offsets[elem][index_in_group]] = int(face);
327 sort_small_groups(offsets, 1024, results);
331 const int groups_num,
360 for (const int64_t edge : range) {
361 for (const int vert : {edges[edge][0], edges[edge][1]}) {
362 const int index_in_group = atomic_fetch_and_add_int32(&counts[vert], 1);
363 r_indices[offsets[vert][index_in_group]] = int(edge);
367 sort_small_groups(offsets, 1024, r_indices);
368 return {offsets, r_indices};
402 return gather_groups(corner_verts, verts_num, r_offsets, r_indices);
410 return gather_groups(corner_edges, edges_num, r_offsets, r_indices);
445 const int *face_groups,
447 const int face_group_id,
448 const int face_group_id_overflowed,
449 int &r_bit_face_group_mask)
454 for (
const int face_idx : faces_from_item) {
455 int bit = face_groups[face_idx];
456 if (!
ELEM(bit, 0, face_group_id, face_group_id_overflowed) && !(r_bit_face_group_mask & bit)) {
457 r_bit_face_group_mask |= bit;
485 const bool use_bitflags,
486 const bool use_boundary_vertices_for_bitflags,
491 int *r_totedgeboundaries)
497 int num_edgeboundaries = 0;
500 constexpr int temp_face_group_id = 3;
504 constexpr int face_group_id_overflowed = 5;
507 bool group_id_overflow =
false;
509 if (
faces.is_empty()) {
511 *r_face_groups =
nullptr;
512 if (r_edge_boundaries) {
513 *r_edge_boundaries =
nullptr;
514 *r_totedgeboundaries = 0;
519 if (r_edge_boundaries) {
521 *r_totedgeboundaries = 0;
528 faces, corner_edges, totedge, edge_to_face_src_offsets, edge_to_face_src_indices);
532 if (use_bitflags && vert_face_map.
is_empty()) {
534 faces, corner_verts, totvert, vert_to_face_src_offsets, vert_to_face_src_indices);
542 int bit_face_group_mask = 0;
544 int ps_curr_idx = 0, ps_end_idx = 0;
546 for (face = face_prev; face < int(
faces.size()); face++) {
547 if (face_groups[face] == 0) {
552 if (face ==
int(
faces.size())) {
557 face_group_id = use_bitflags ? temp_face_group_id : ++tot_group;
560 face_prev = face + 1;
562 face_groups[face] = face_group_id;
563 face_stack[ps_end_idx++] = face;
565 while (ps_curr_idx != ps_end_idx) {
566 face = face_stack[ps_curr_idx++];
567 BLI_assert(face_groups[face] == face_group_id);
570 const int edge = corner_edges[loop];
573 const int *p = map_ele.
data();
574 int i = int(map_ele.
size());
575 if (!edge_boundary_check(face,
int(loop), edge,
i, map_ele)) {
580 if (face_groups[*p] == 0) {
581 face_groups[*p] = face_group_id;
582 face_stack[ps_end_idx++] = *p;
589 num_edgeboundaries++;
596 face_group_id_overflowed,
597 bit_face_group_mask);
598 if (use_boundary_vertices_for_bitflags) {
612 const int vert = corner_verts[loop];
616 face_group_id_overflowed,
617 bit_face_group_mask);
628 int i, *p, gid_bit = 0;
632 for (; (face_group_id & bit_face_group_mask) && (gid_bit < 32); gid_bit++) {
647 "Warning, could not find an available id for current smooth group, faces will me "
649 "as out of any smooth group...\n");
652 face_group_id = face_group_id_overflowed;
654 group_id_overflow =
true;
656 tot_group = std::max(gid_bit, tot_group);
658 for (
i = ps_end_idx, p = face_stack;
i--; p++) {
659 face_groups[*p] = face_group_id;
670 int i = int(
faces.size()), *gid = face_groups;
672 if (*gid == face_group_id_overflowed) {
682 *r_totgroup = tot_group;
683 *r_face_groups = face_groups;
684 if (r_edge_boundaries) {
685 *r_edge_boundaries = edge_boundaries;
686 *r_totedgeboundaries = num_edgeboundaries;
698 const bool use_bitflags,
699 const bool use_boundary_vertices_for_bitflags)
701 int *face_groups =
nullptr;
703 auto face_is_smooth = [&](
const int i) {
return sharp_faces.
is_empty() || !sharp_faces[
i]; };
705 auto face_is_island_boundary_smooth = [&](
const int face_index,
707 const int edge_index,
708 const int edge_user_count,
712 if (face_is_smooth(face_index) && !(!sharp_edges.
is_empty() && sharp_edges[edge_index]) &&
713 (edge_user_count == 2))
716 const int other_face_index = (face_index == edge_face_map_elem[0]) ? edge_face_map_elem[1] :
717 edge_face_map_elem[0];
718 return !face_is_smooth(other_face_index);
731 use_boundary_vertices_for_bitflags,
732 face_is_island_boundary_smooth,
749 edges_num, 0,
faces, corner_edges, {}, sharp_edges, sharp_faces, r_totgroup,
false,
false);
759 const bool use_boundary_vertices_for_bitflags,
771 use_boundary_vertices_for_bitflags);
774#define MISLAND_DEFAULT_BUFSIZE 64
777 const short item_type,
779 const short island_type,
780 const short innercut_type)
784 if (mem ==
nullptr) {
786 island_store->
mem = mem;
818 island_store->
islands =
nullptr;
823 if (island_store->
mem) {
832 if (island_store->
mem) {
834 island_store->
mem =
nullptr;
840 const int *items_indices,
841 const int num_island_items,
842 int *island_item_indices,
843 const int num_innercut_items,
844 int *innercut_item_indices)
849 const int curr_island_idx = island_store->
islands_num++;
850 const size_t curr_num_islands = size_t(island_store->
islands_num);
863 memcpy(islds, island_store->
islands,
sizeof(*islds) * (curr_num_islands - 1));
868 memcpy(innrcuts, island_store->
innercuts,
sizeof(*innrcuts) * (curr_num_islands - 1));
874 isld->
count = num_island_items;
875 isld->
indices =
static_cast<int *
>(
877 memcpy(isld->
indices, island_item_indices,
sizeof(*isld->
indices) *
size_t(num_island_items));
881 innrcut->
count = num_innercut_items;
882 innrcut->
indices =
static_cast<int *
>(
885 innercut_item_indices,
886 sizeof(*innrcut->
indices) *
size_t(num_innercut_items));
896 int *face_groups =
nullptr;
901 int num_pidx, num_lidx;
907 int num_edge_boundaries = 0;
908 char *edge_boundary_count =
nullptr;
909 int *edge_innercut_indices =
nullptr;
910 int num_einnercuts = 0;
917 int(corner_edges.
size()),
924 faces, corner_edges, totedge, edge_to_face_offsets, edge_to_face_indices);
932 auto mesh_check_island_boundary_uv = [&](
const int ,
934 const int edge_index,
938 return !uv_seams.
is_empty() && uv_seams[edge_index];
950 mesh_check_island_boundary_uv,
954 &num_edge_boundaries);
956 if (!num_face_groups) {
957 if (num_edge_boundaries) {
963 if (num_edge_boundaries) {
972 for (grp_idx = 1; grp_idx <= num_face_groups; grp_idx++) {
973 num_pidx = num_lidx = 0;
974 if (num_edge_boundaries) {
976 memset(edge_boundary_count, 0,
sizeof(*edge_boundary_count) *
size_t(totedge));
980 if (face_groups[p_idx] != grp_idx) {
983 face_indices[num_pidx++] = int(p_idx);
985 const int edge_i = corner_edges[corner];
986 loop_indices[num_lidx++] = int(corner);
988 (edge_boundary_count[edge_i] < 2))
990 edge_boundary_count[edge_i]++;
991 if (edge_boundary_count[edge_i] == 2) {
992 edge_innercut_indices[num_einnercuts++] = edge_i;
1004 edge_innercut_indices);
1011 if (num_edge_boundaries) {
1015 if (num_edge_boundaries) {
1032 int(edges.
size()), uv_seams,
faces, corner_edges, r_island_store);
CustomData interface, see also DNA_customdata_types.h.
#define BLI_BITMAP_NEW(_num, _alloc_string)
#define BLI_BITMAP_TEST(_bitmap, _index)
#define BLI_BITMAP_ENABLE(_bitmap, _index)
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
#define BLI_MEMARENA_STD_BUFSIZE
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_alloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
#define BLI_SCOPED_DEFER(function_to_defer)
Read Guarded memory(de)allocation.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
constexpr IndexRange index_range() const
Span< T > as_span() const
const T & last(const int64_t n=0) const
void reinitialize(const int64_t new_size)
Span< NewT > constexpr cast() const
constexpr const T * data() const
constexpr int64_t size() const
constexpr const T * end() const
constexpr IndexRange index_range() const
constexpr const T * begin() const
constexpr bool is_empty() const
IndexRange index_range() const
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
UvMapVert * BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, uint v)
int * BKE_mesh_calc_smoothgroups_bitflags(int edges_num, int verts_num, const blender::OffsetIndices< int > faces, const blender::Span< int > corner_edges, const blender::Span< int > corner_verts, const blender::Span< bool > sharp_edges, const blender::Span< bool > sharp_faces, const bool use_boundary_vertices_for_bitflags, int *r_totgroup)
void BKE_mesh_origindex_map_create_corner_tri(MeshElemMap **r_map, int **r_mem, const blender::OffsetIndices< int > faces, const int *corner_tri_faces, const int corner_tris_num)
void BKE_mesh_origindex_map_create(MeshElemMap **r_map, int **r_mem, const int totsource, const int *final_origindex, const int totfinal)
void BKE_mesh_loop_islands_add(MeshIslandStore *island_store, const int item_num, const int *items_indices, const int num_island_items, int *island_item_indices, const int num_innercut_items, int *innercut_item_indices)
int * BKE_mesh_calc_smoothgroups(int edges_num, const blender::OffsetIndices< int > faces, const blender::Span< int > corner_edges, const blender::Span< bool > sharp_edges, const blender::Span< bool > sharp_faces, int *r_totgroup)
bool BKE_mesh_calc_islands_loop_face_edgeseam(const blender::Span< blender::float3 > vert_positions, const blender::Span< blender::int2 > edges, const blender::Span< bool > uv_seams, const blender::OffsetIndices< int > faces, const blender::Span< int >, const blender::Span< int > corner_edges, MeshIslandStore *r_island_store)
static bool mesh_calc_islands_loop_face_uv(const int totedge, const blender::Span< bool > uv_seams, const blender::OffsetIndices< int > faces, const blender::Span< int > corner_edges, MeshIslandStore *r_island_store)
static void face_edge_loop_islands_calc(const int totedge, const int totvert, const blender::OffsetIndices< int > faces, const blender::Span< int > corner_edges, const blender::Span< int > corner_verts, blender::GroupedSpan< int > edge_face_map, blender::GroupedSpan< int > vert_face_map, const bool use_bitflags, const bool use_boundary_vertices_for_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check, int **r_face_groups, int *r_totgroup, BLI_bitmap **r_edge_boundaries, int *r_totedgeboundaries)
void BKE_mesh_loop_islands_init(MeshIslandStore *island_store, const short item_type, const int items_num, const short island_type, const short innercut_type)
#define MISLAND_DEFAULT_BUFSIZE
void BKE_mesh_loop_islands_clear(MeshIslandStore *island_store)
blender::FunctionRef< bool(int face_index, int corner, int edge_index, int edge_user_count, const blender::Span< int > edge_face_map_elem)> MeshRemap_CheckIslandBoundary
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
void BKE_mesh_vert_corner_tri_map_create(MeshElemMap **r_map, int **r_mem, const int totvert, const blender::int3 *corner_tris, const int tris_num, const int *corner_verts, const int)
static int * mesh_calc_smoothgroups(const int edges_num, const int verts_num, const blender::OffsetIndices< int > faces, const blender::Span< int > corner_edges, const blender::Span< int > corner_verts, const blender::Span< bool > sharp_edges, const blender::Span< bool > sharp_faces, int *r_totgroup, const bool use_bitflags, const bool use_boundary_vertices_for_bitflags)
void BKE_mesh_loop_islands_free(MeshIslandStore *island_store)
static void face_edge_loop_islands_calc_bitflags_exclude_at_boundary(const int *face_groups, const blender::Span< int > faces_from_item, const int face_group_id, const int face_group_id_overflowed, int &r_bit_face_group_mask)
UvVertMap * BKE_mesh_uv_vert_map_create(blender::OffsetIndices< int > faces, blender::Span< int > corner_verts, blender::Span< blender::float2 > uv_map, int verts_num, const blender::float2 &limit, bool use_winding)
void build_vert_to_face_indices(OffsetIndices< int > faces, Span< int > corner_verts, OffsetIndices< int > offsets, MutableSpan< int > face_indices)
GroupedSpan< int > build_vert_to_corner_map(Span< int > corner_verts, int verts_num, Array< int > &r_offsets, Array< int > &r_indices)
static Array< int > reverse_indices_in_groups(const Span< int > group_indices, const OffsetIndices< int > offsets)
GroupedSpan< int > build_edge_to_corner_map(Span< int > corner_edges, int edges_num, Array< int > &r_offsets, Array< int > &r_indices)
static Array< int > create_reverse_offsets(const Span< int > indices, const int items_num)
static GroupedSpan< int > gather_groups(const Span< int > group_indices, const int groups_num, Array< int > &r_offsets, Array< int > &r_indices)
static void sort_small_groups(const OffsetIndices< int > groups, const int grain_size, MutableSpan< int > indices)
int face_triangles_num(const int face_size)
GroupedSpan< int > build_edge_to_face_map(OffsetIndices< int > faces, Span< int > corner_edges, int edges_num, Array< int > &r_offsets, Array< int > &r_indices)
Array< int > build_corner_to_face_map(OffsetIndices< int > faces)
Array< int > build_vert_to_corner_indices(Span< int > corner_verts, OffsetIndices< int > offsets)
GroupedSpan< int > build_vert_to_face_map(OffsetIndices< int > faces, Span< int > corner_verts, int verts_num, Array< int > &r_offsets, Array< int > &r_indices)
static void reverse_group_indices_in_groups(const OffsetIndices< int > groups, const Span< int > group_to_elem, const OffsetIndices< int > offsets, MutableSpan< int > results)
GroupedSpan< int > build_vert_to_edge_map(Span< int2 > edges, int verts_num, Array< int > &r_offsets, Array< int > &r_indices)
void build_reverse_map(OffsetIndices< int > offsets, MutableSpan< int > r_map)
void build_reverse_offsets(Span< int > indices, MutableSpan< int > offsets)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
unsigned short loop_of_face_index