37 const bool *hide_poly,
38 const bool *select_poly,
39 const int *corner_verts,
40 const float (*mloopuv)[2],
44 const bool use_winding)
57 for (
const int64_t a : faces.index_range()) {
58 if (!selected || (!(hide_poly && hide_poly[a]) && (select_poly && select_poly[a]))) {
71 if (!vmap->
vert || !vmap->
buf) {
76 bool *winding =
nullptr;
78 winding =
static_cast<bool *
>(
82 for (
const int64_t a : faces.index_range()) {
84 if (!selected || (!(hide_poly && hide_poly[a]) && (select_poly && select_poly[a]))) {
85 float(*tf_uv)[2] =
nullptr;
92 nverts =
int(face.size());
94 for (i = 0; i < nverts; i++) {
98 buf->
next = vmap->
vert[corner_verts[face[i]]];
99 vmap->
vert[corner_verts[face[i]]] = buf;
115 for (
uint a = 0; a < totvert; a++) {
118 const float *uv, *uv2;
127 uv = mloopuv[faces[
v->face_index].start() +
v->loop_of_face_index];
137 if (
fabsf(uv[0] - uv2[0]) < limit[0] &&
fabsf(uv[1] - uv2[1]) < limit[1] &&
138 (!use_winding || winding[iterv->
face_index] == winding[
v->face_index]))
146 iterv->
next = newvlist;
159 vmap->
vert[a] = newvlist;
173 return vmap->
vert[
v];
194 const int *corner_verts,
197 MeshElemMap *map = MEM_cnew_array<MeshElemMap>(
size_t(totvert), __func__);
198 int *indices =
static_cast<int *
>(
MEM_mallocN(
sizeof(
int) *
size_t(tris_num) * 3, __func__));
203 for (i = 0; i < tris_num; i++) {
204 for (
int j = 3; j--;) {
205 map[corner_verts[corner_tris[i][j]]].count++;
211 for (i = 0; i < totvert; i++) {
212 map[i].indices = index_step;
213 index_step += map[i].count;
220 for (i = 0; i < tris_num; i++) {
221 for (
int j = 3; j--;) {
222 MeshElemMap *map_ele = &map[corner_verts[corner_tris[i][j]]];
234 const int *final_origindex,
237 MeshElemMap *map = MEM_cnew_array<MeshElemMap>(
size_t(totsource), __func__);
238 int *indices =
static_cast<int *
>(
MEM_mallocN(
sizeof(
int) *
size_t(totfinal), __func__));
243 for (i = 0; i < totfinal; i++) {
246 map[final_origindex[i]].count++;
252 for (i = 0; i < totsource; i++) {
253 map[i].indices = index_step;
254 index_step += map[i].count;
261 for (i = 0; i < totfinal; i++) {
275 const int *corner_tri_faces,
276 const int corner_tris_num)
278 MeshElemMap *map = MEM_cnew_array<MeshElemMap>(
size_t(faces.size()), __func__);
279 int *indices =
static_cast<int *
>(
MEM_mallocN(
sizeof(
int) *
size_t(corner_tris_num), __func__));
284 for (
const int64_t i : faces.index_range()) {
285 map[i].indices = index_step;
290 for (
int i = 0; i < corner_tris_num; i++) {
309 const int grain_size,
313 for (const int64_t index : range) {
314 MutableSpan<int> group = indices.slice(groups[index]);
315 std::sort(group.begin(), group.end());
333 int *counts = MEM_cnew_array<int>(
size_t(offsets.
size()), __func__);
337 for (const int64_t i : range) {
338 const int group_index = group_indices[i];
339 const int index_in_group = atomic_fetch_and_add_int32(&counts[group_index], 1);
340 results[offsets[group_index][index_in_group]] = int(i);
343 sort_small_groups(offsets, 1024, results);
353 int *counts = MEM_cnew_array<int>(
size_t(offsets.
size()), __func__);
355 threading::parallel_for(groups.index_range(), 1024, [&](
const IndexRange range) {
357 for (
const int elem : group_to_elem.
slice(groups[face])) {
359 results[offsets[elem][index_in_group]] =
int(face);
367 const int groups_num,
379 offset_indices::build_reverse_map(faces, map);
393 int *counts = MEM_cnew_array<int>(
size_t(offsets.
size()), __func__);
395 threading::parallel_for(edges.index_range(), 1024, [&](
const IndexRange range) {
397 for (
const int vert : {edges[edge][0], edges[edge][1]}) {
399 r_indices[offsets[vert][index_in_group]] =
int(edge);
404 return {offsets, r_indices};
438 return gather_groups(corner_verts, verts_num, r_offsets, r_indices);
446 return gather_groups(corner_edges, edges_num, r_offsets, r_indices);
484 const bool use_bitflags,
489 int *r_totedgeborder)
495 int num_edgeborders = 0;
498 const int temp_face_group_id = 3;
501 const int face_group_id_overflowed = 5;
504 bool group_id_overflow =
false;
506 if (faces.is_empty()) {
508 *r_face_groups =
nullptr;
509 if (r_edge_borders) {
510 *r_edge_borders =
nullptr;
511 *r_totedgeborder = 0;
516 if (r_edge_borders) {
518 *r_totedgeborder = 0;
525 faces, corner_edges, totedge, edge_to_face_src_offsets, edge_to_face_src_indices);
528 face_groups =
static_cast<int *
>(
MEM_callocN(
sizeof(
int) *
size_t(faces.size()), __func__));
529 face_stack =
static_cast<int *
>(
MEM_mallocN(
sizeof(
int) *
size_t(faces.size()), __func__));
533 int bit_face_group_mask = 0;
535 int ps_curr_idx = 0, ps_end_idx = 0;
537 for (face = face_prev; face <
int(faces.size()); face++) {
538 if (face_groups[face] == 0) {
543 if (face ==
int(faces.size())) {
548 face_group_id = use_bitflags ? temp_face_group_id : ++tot_group;
551 face_prev = face + 1;
553 face_groups[face] = face_group_id;
554 face_stack[ps_end_idx++] = face;
556 while (ps_curr_idx != ps_end_idx) {
557 face = face_stack[ps_curr_idx++];
558 BLI_assert(face_groups[face] == face_group_id);
560 for (
const int64_t loop : faces[face]) {
561 const int edge = corner_edges[loop];
564 const int *p = map_ele.
data();
566 if (!edge_boundary_check(face,
int(loop), edge, i, map_ele)) {
571 if (face_groups[*p] == 0) {
572 face_groups[*p] = face_group_id;
573 face_stack[ps_end_idx++] = *p;
586 int bit = face_groups[*p];
587 if (!
ELEM(bit, 0, face_group_id, face_group_id_overflowed) &&
588 !(bit_face_group_mask & bit))
590 bit_face_group_mask |= bit;
602 int i, *p, gid_bit = 0;
606 for (; (face_group_id & bit_face_group_mask) && (gid_bit < 32); gid_bit++) {
616 "Warning, could not find an available id for current smooth group, faces will me "
618 "as out of any smooth group...\n");
621 face_group_id = face_group_id_overflowed;
623 group_id_overflow =
true;
625 if (gid_bit > tot_group) {
629 for (i = ps_end_idx, p = face_stack; i--; p++) {
630 face_groups[*p] = face_group_id;
641 int i =
int(faces.size()), *gid = face_groups;
643 if (*gid == face_group_id_overflowed) {
653 *r_totgroup = tot_group;
654 *r_face_groups = face_groups;
655 if (r_edge_borders) {
656 *r_edge_borders = edge_borders;
657 *r_totedgeborder = num_edgeborders;
669 int *face_groups =
nullptr;
671 auto face_is_smooth = [&](
const int i) {
return sharp_faces.
is_empty() || !sharp_faces[i]; };
673 auto face_is_island_boundary_smooth = [&](
const int face_index,
675 const int edge_index,
676 const int edge_user_count,
680 if (face_is_smooth(face_index) && !(!sharp_edges.
is_empty() && sharp_edges[edge_index]) &&
681 (edge_user_count == 2))
684 const int other_face_index = (face_index == edge_face_map_elem[0]) ? edge_face_map_elem[1] :
685 edge_face_map_elem[0];
686 return !face_is_smooth(other_face_index);
696 face_is_island_boundary_smooth,
705#define MISLAND_DEFAULT_BUFSIZE 64
708 const short item_type,
710 const short island_type,
711 const short innercut_type)
715 if (mem ==
nullptr) {
717 island_store->
mem = mem;
749 island_store->
islands =
nullptr;
754 if (island_store->
mem) {
763 if (island_store->
mem) {
765 island_store->
mem =
nullptr;
771 const int *items_indices,
772 const int num_island_items,
773 int *island_item_indices,
774 const int num_innercut_items,
775 int *innercut_item_indices)
780 const int curr_island_idx = island_store->
islands_num++;
781 const size_t curr_num_islands = size_t(island_store->
islands_num);
794 memcpy(islds, island_store->
islands,
sizeof(*islds) * (curr_num_islands - 1));
799 memcpy(innrcuts, island_store->
innercuts,
sizeof(*innrcuts) * (curr_num_islands - 1));
805 isld->
count = num_island_items;
806 isld->
indices =
static_cast<int *
>(
808 memcpy(isld->
indices, island_item_indices,
sizeof(*isld->
indices) *
size_t(num_island_items));
812 innrcut->
count = num_innercut_items;
813 innrcut->
indices =
static_cast<int *
>(
816 innercut_item_indices,
817 sizeof(*innrcut->
indices) *
size_t(num_innercut_items));
821 const bool *uv_seams,
823 const int *corner_verts,
824 const int *corner_edges,
825 const int corners_num,
826 const float (*luvs)[2],
830 int *face_groups =
nullptr;
835 int num_pidx, num_lidx;
841 int num_edge_borders = 0;
842 char *edge_border_count =
nullptr;
843 int *edge_innercut_indices =
nullptr;
844 int num_einnercuts = 0;
854 const GroupedSpan<int> edge_to_face_map = bke::mesh::build_edge_to_face_map(
855 faces, {corner_edges, corners_num}, totedge, edge_to_face_offsets, edge_to_face_indices);
861 edge_to_loop_map = bke::mesh::build_edge_to_corner_map(
862 {corner_edges, corners_num}, totedge, edge_to_loop_offsets, edge_to_loop_indices);
871 auto mesh_check_island_boundary_uv = [&](
const int ,
872 const int loop_index,
873 const int edge_index,
877 const Span<int> edge_to_loops = edge_to_loop_map[corner_edges[loop_index]];
881 const int v1 = corner_verts[edge_to_loops[0]];
882 const int v2 = corner_verts[edge_to_loops[1]];
883 const float *uvco_v1 = luvs[edge_to_loops[0]];
884 const float *uvco_v2 = luvs[edge_to_loops[1]];
885 for (
int i = 2; i < edge_to_loops.
size(); i += 2) {
886 if (corner_verts[edge_to_loops[i]] == v1) {
887 if (!
equals_v2v2(uvco_v1, luvs[edge_to_loops[i]]) ||
896 if (!
equals_v2v2(uvco_v2, luvs[edge_to_loops[i]]) ||
907 return uv_seams && uv_seams[edge_index];
912 {corner_edges, corners_num},
915 mesh_check_island_boundary_uv,
921 if (!num_face_groups) {
928 if (num_edge_borders) {
929 edge_border_count =
static_cast<char *
>(
930 MEM_mallocN(
sizeof(*edge_border_count) *
size_t(totedge), __func__));
931 edge_innercut_indices =
static_cast<int *
>(
932 MEM_mallocN(
sizeof(*edge_innercut_indices) *
size_t(num_edge_borders), __func__));
935 face_indices =
static_cast<int *
>(
936 MEM_mallocN(
sizeof(*face_indices) *
size_t(faces.size()), __func__));
937 loop_indices =
static_cast<int *
>(
938 MEM_mallocN(
sizeof(*loop_indices) *
size_t(corners_num), __func__));
941 for (grp_idx = 1; grp_idx <= num_face_groups; grp_idx++) {
942 num_pidx = num_lidx = 0;
943 if (num_edge_borders) {
945 memset(edge_border_count, 0,
sizeof(*edge_border_count) *
size_t(totedge));
948 for (
const int64_t p_idx : faces.index_range()) {
949 if (face_groups[p_idx] != grp_idx) {
952 face_indices[num_pidx++] =
int(p_idx);
953 for (
const int64_t corner : faces[p_idx]) {
954 const int edge_i = corner_edges[corner];
955 loop_indices[num_lidx++] =
int(corner);
957 (edge_border_count[edge_i] < 2))
959 edge_border_count[edge_i]++;
960 if (edge_border_count[edge_i] == 2) {
961 edge_innercut_indices[num_einnercuts++] = edge_i;
973 edge_innercut_indices);
984 if (num_edge_borders) {
995 const bool *uv_seams,
997 const int *corner_verts,
998 const int *corner_edges,
999 const int corners_num,
1004 totedge, uv_seams, faces, corner_verts, corner_edges, corners_num,
nullptr, r_island_store);
1011 const bool *uv_seams,
1013 const int *corner_verts,
1014 const int *corner_edges,
1015 const int corners_num,
1016 const float (*luvs)[2],
1022 totedge, uv_seams, faces, corner_verts, corner_edges, corners_num, luvs, 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)
#define BLI_buffer_reinit_data(buffer_, type_, new_count_)
#define BLI_buffer_declare_static(type_, name_, flag_, static_count_)
#define BLI_buffer_free(name_)
float cross_poly_v2(const float verts[][2], unsigned int nr)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
#define BLI_MEMARENA_STD_BUFSIZE
void void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
#define BLI_SCOPED_DEFER(function_to_defer)
#define UNUSED_VARS_NDEBUG(...)
Read Guarded memory(de)allocation.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE int32_t atomic_fetch_and_add_int32(int32_t *p, int32_t x)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Span< T > as_span() const
const T & last(const int64_t n=0) const
void reinitialize(const int64_t new_size)
constexpr Span slice(int64_t start, int64_t size) 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
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void *(* MEM_mallocN)(size_t len, const char *str)
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
static void face_edge_loop_islands_calc(const int totedge, const blender::OffsetIndices< int > faces, const blender::Span< int > corner_edges, blender::GroupedSpan< int > edge_face_map, const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check, int **r_face_groups, int *r_totgroup, BLI_bitmap **r_edge_borders, int *r_totedgeborder)
UvMapVert * BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, uint v)
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)
bool BKE_mesh_calc_islands_loop_face_edgeseam(const float(*vert_positions)[3], const int totvert, const blender::int2 *edges, const int totedge, const bool *uv_seams, const blender::OffsetIndices< int > faces, const int *corner_verts, const int *corner_edges, const int corners_num, MeshIslandStore *r_island_store)
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)
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)
bool BKE_mesh_calc_islands_loop_face_uvmap(float(*vert_positions)[3], const int totvert, blender::int2 *edges, const int totedge, const bool *uv_seams, const blender::OffsetIndices< int > faces, const int *corner_verts, const int *corner_edges, const int corners_num, const float(*luvs)[2], MeshIslandStore *r_island_store)
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)
UvVertMap * BKE_mesh_uv_vert_map_create(const blender::OffsetIndices< int > faces, const bool *hide_poly, const bool *select_poly, const int *corner_verts, const float(*mloopuv)[2], uint totvert, const float limit[2], const bool selected, const bool use_winding)
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 use_bitflags)
void BKE_mesh_loop_islands_free(MeshIslandStore *island_store)
static bool mesh_calc_islands_loop_face_uv(const int totedge, const bool *uv_seams, const blender::OffsetIndices< int > faces, const int *corner_verts, const int *corner_edges, const int corners_num, const float(*luvs)[2], MeshIslandStore *r_island_store)
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_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))
unsigned short loop_of_face_index