Blender  V3.3
mesh_mapping.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_meshdata_types.h"
13 #include "DNA_vec_types.h"
14 
15 #include "BLI_bitmap.h"
16 #include "BLI_buffer.h"
17 #include "BLI_math.h"
18 #include "BLI_utildefines.h"
19 
20 #include "BKE_customdata.h"
21 #include "BKE_mesh_mapping.h"
22 #include "BLI_memarena.h"
23 
24 #include "BLI_strict_flags.h"
25 
26 /* -------------------------------------------------------------------- */
30 /* ngon version wip, based on BM_uv_vert_map_create */
32  const MLoop *mloop,
33  const MLoopUV *mloopuv,
34  uint totpoly,
35  uint totvert,
36  const float limit[2],
37  const bool selected,
38  const bool use_winding)
39 {
40  UvVertMap *vmap;
41  UvMapVert *buf;
42  const MPoly *mp;
43  uint a;
44  int i, totuv, nverts;
45 
46  bool *winding = NULL;
48 
49  totuv = 0;
50 
51  /* generate UvMapVert array */
52  mp = mpoly;
53  for (a = 0; a < totpoly; a++, mp++) {
54  if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) {
55  totuv += mp->totloop;
56  }
57  }
58 
59  if (totuv == 0) {
60  return NULL;
61  }
62 
63  vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap");
64  buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * (size_t)totuv, "UvMapVert");
65  vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totvert, "UvMapVert*");
66  if (use_winding) {
67  winding = MEM_callocN(sizeof(*winding) * totpoly, "winding");
68  }
69 
70  if (!vmap->vert || !vmap->buf) {
72  return NULL;
73  }
74 
75  mp = mpoly;
76  for (a = 0; a < totpoly; a++, mp++) {
77  if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) {
78  float(*tf_uv)[2] = NULL;
79 
80  if (use_winding) {
81  tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, (size_t)mp->totloop);
82  }
83 
84  nverts = mp->totloop;
85 
86  for (i = 0; i < nverts; i++) {
87  buf->loop_of_poly_index = (unsigned short)i;
88  buf->poly_index = a;
89  buf->separate = 0;
90  buf->next = vmap->vert[mloop[mp->loopstart + i].v];
91  vmap->vert[mloop[mp->loopstart + i].v] = buf;
92 
93  if (use_winding) {
94  copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i].uv);
95  }
96 
97  buf++;
98  }
99 
100  if (use_winding) {
101  winding[a] = cross_poly_v2(tf_uv, (uint)nverts) > 0;
102  }
103  }
104  }
105 
106  /* sort individual uvs for each vert */
107  for (a = 0; a < totvert; a++) {
108  UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
109  UvMapVert *iterv, *v, *lastv, *next;
110  const float *uv, *uv2;
111  float uvdiff[2];
112 
113  while (vlist) {
114  v = vlist;
115  vlist = vlist->next;
116  v->next = newvlist;
117  newvlist = v;
118 
119  uv = mloopuv[mpoly[v->poly_index].loopstart + v->loop_of_poly_index].uv;
120  lastv = NULL;
121  iterv = vlist;
122 
123  while (iterv) {
124  next = iterv->next;
125 
126  uv2 = mloopuv[mpoly[iterv->poly_index].loopstart + iterv->loop_of_poly_index].uv;
127  sub_v2_v2v2(uvdiff, uv2, uv);
128 
129  if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] &&
130  (!use_winding || winding[iterv->poly_index] == winding[v->poly_index])) {
131  if (lastv) {
132  lastv->next = next;
133  }
134  else {
135  vlist = next;
136  }
137  iterv->next = newvlist;
138  newvlist = iterv;
139  }
140  else {
141  lastv = iterv;
142  }
143 
144  iterv = next;
145  }
146 
147  newvlist->separate = 1;
148  }
149 
150  vmap->vert[a] = newvlist;
151  }
152 
153  if (use_winding) {
154  MEM_freeN(winding);
155  }
156 
157  BLI_buffer_free(&tf_uv_buf);
158 
159  return vmap;
160 }
161 
163 {
164  return vmap->vert[v];
165 }
166 
168 {
169  if (vmap) {
170  if (vmap->vert) {
171  MEM_freeN(vmap->vert);
172  }
173  if (vmap->buf) {
174  MEM_freeN(vmap->buf);
175  }
176  MEM_freeN(vmap);
177  }
178 }
179 
188  int **r_mem,
189  const MPoly *mpoly,
190  const MLoop *mloop,
191  int totvert,
192  int totpoly,
193  int totloop,
194  const bool do_loops)
195 {
196  MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, __func__);
197  int *indices, *index_iter;
198  int i, j;
199 
200  indices = index_iter = MEM_mallocN(sizeof(int) * (size_t)totloop, __func__);
201 
202  /* Count number of polys for each vertex */
203  for (i = 0; i < totpoly; i++) {
204  const MPoly *p = &mpoly[i];
205 
206  for (j = 0; j < p->totloop; j++) {
207  map[mloop[p->loopstart + j].v].count++;
208  }
209  }
210 
211  /* Assign indices mem */
212  for (i = 0; i < totvert; i++) {
213  map[i].indices = index_iter;
214  index_iter += map[i].count;
215 
216  /* Reset 'count' for use as index in last loop */
217  map[i].count = 0;
218  }
219 
220  /* Find the users */
221  for (i = 0; i < totpoly; i++) {
222  const MPoly *p = &mpoly[i];
223 
224  for (j = 0; j < p->totloop; j++) {
225  uint v = mloop[p->loopstart + j].v;
226 
227  map[v].indices[map[v].count] = do_loops ? p->loopstart + j : i;
228  map[v].count++;
229  }
230  }
231 
232  *r_map = map;
233  *r_mem = indices;
234 }
235 
237  int **r_mem,
238  const MPoly *mpoly,
239  const MLoop *mloop,
240  int totvert,
241  int totpoly,
242  int totloop)
243 {
244  mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, false);
245 }
246 
248  int **r_mem,
249  const MPoly *mpoly,
250  const MLoop *mloop,
251  int totvert,
252  int totpoly,
253  int totloop)
254 {
255  mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, true);
256 }
257 
259  int **r_mem,
260  const MVert *UNUSED(mvert),
261  const int totvert,
262  const MLoopTri *mlooptri,
263  const int totlooptri,
264  const MLoop *mloop,
265  const int UNUSED(totloop))
266 {
267  MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, __func__);
268  int *indices = MEM_mallocN(sizeof(int) * (size_t)totlooptri * 3, __func__);
269  int *index_step;
270  const MLoopTri *mlt;
271  int i;
272 
273  /* count face users */
274  for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) {
275  for (int j = 3; j--;) {
276  map[mloop[mlt->tri[j]].v].count++;
277  }
278  }
279 
280  /* create offsets */
281  index_step = indices;
282  for (i = 0; i < totvert; i++) {
283  map[i].indices = index_step;
284  index_step += map[i].count;
285 
286  /* re-count, using this as an index below */
287  map[i].count = 0;
288  }
289 
290  /* assign looptri-edge users */
291  for (i = 0, mlt = mlooptri; i < totlooptri; mlt++, i++) {
292  for (int j = 3; j--;) {
293  MeshElemMap *map_ele = &map[mloop[mlt->tri[j]].v];
294  map_ele->indices[map_ele->count++] = i;
295  }
296  }
297 
298  *r_map = map;
299  *r_mem = indices;
300 }
301 
303  MeshElemMap **r_map, int **r_mem, const MEdge *medge, int totvert, int totedge)
304 {
305  MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, "vert-edge map");
306  int *indices = MEM_mallocN(sizeof(int[2]) * (size_t)totedge, "vert-edge map mem");
307  int *i_pt = indices;
308 
309  int i;
310 
311  /* Count number of edges for each vertex */
312  for (i = 0; i < totedge; i++) {
313  map[medge[i].v1].count++;
314  map[medge[i].v2].count++;
315  }
316 
317  /* Assign indices mem */
318  for (i = 0; i < totvert; i++) {
319  map[i].indices = i_pt;
320  i_pt += map[i].count;
321 
322  /* Reset 'count' for use as index in last loop */
323  map[i].count = 0;
324  }
325 
326  /* Find the users */
327  for (i = 0; i < totedge; i++) {
328  const uint v[2] = {medge[i].v1, medge[i].v2};
329 
330  map[v[0]].indices[map[v[0]].count] = i;
331  map[v[1]].indices[map[v[1]].count] = i;
332 
333  map[v[0]].count++;
334  map[v[1]].count++;
335  }
336 
337  *r_map = map;
338  *r_mem = indices;
339 }
340 
342  MeshElemMap **r_map, int **r_mem, const MEdge *medge, int totvert, int totedge)
343 {
344  MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totvert, "vert-edge map");
345  int *indices = MEM_mallocN(sizeof(int[2]) * (size_t)totedge, "vert-edge map mem");
346  int *i_pt = indices;
347 
348  int i;
349 
350  /* Count number of edges for each vertex */
351  for (i = 0; i < totedge; i++) {
352  map[medge[i].v1].count++;
353  map[medge[i].v2].count++;
354  }
355 
356  /* Assign indices mem */
357  for (i = 0; i < totvert; i++) {
358  map[i].indices = i_pt;
359  i_pt += map[i].count;
360 
361  /* Reset 'count' for use as index in last loop */
362  map[i].count = 0;
363  }
364 
365  /* Find the users */
366  for (i = 0; i < totedge; i++) {
367  const uint v[2] = {medge[i].v1, medge[i].v2};
368 
369  map[v[0]].indices[map[v[0]].count] = (int)v[1];
370  map[v[1]].indices[map[v[1]].count] = (int)v[0];
371 
372  map[v[0]].count++;
373  map[v[1]].count++;
374  }
375 
376  *r_map = map;
377  *r_mem = indices;
378 }
379 
381  int **r_mem,
382  const MEdge *UNUSED(medge),
383  const int totedge,
384  const MPoly *mpoly,
385  const int totpoly,
386  const MLoop *mloop,
387  const int totloop)
388 {
389  MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totedge, "edge-poly map");
390  int *indices = MEM_mallocN(sizeof(int) * (size_t)totloop * 2, "edge-poly map mem");
391  int *index_step;
392  const MPoly *mp;
393  int i;
394 
395  /* count face users */
396  for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
397  const MLoop *ml;
398  int j = mp->totloop;
399  for (ml = &mloop[mp->loopstart]; j--; ml++) {
400  map[ml->e].count += 2;
401  }
402  }
403 
404  /* create offsets */
405  index_step = indices;
406  for (i = 0; i < totedge; i++) {
407  map[i].indices = index_step;
408  index_step += map[i].count;
409 
410  /* re-count, using this as an index below */
411  map[i].count = 0;
412  }
413 
414  /* assign loop-edge users */
415  for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
416  const MLoop *ml;
417  MeshElemMap *map_ele;
418  const int max_loop = mp->loopstart + mp->totloop;
419  int j = mp->loopstart;
420  for (ml = &mloop[j]; j < max_loop; j++, ml++) {
421  map_ele = &map[ml->e];
422  map_ele->indices[map_ele->count++] = j;
423  map_ele->indices[map_ele->count++] = j + 1;
424  }
425  /* last edge/loop of poly, must point back to first loop! */
426  map_ele->indices[map_ele->count - 1] = mp->loopstart;
427  }
428 
429  *r_map = map;
430  *r_mem = indices;
431 }
432 
434  int **r_mem,
435  const MEdge *UNUSED(medge),
436  const int totedge,
437  const MPoly *mpoly,
438  const int totpoly,
439  const MLoop *mloop,
440  const int totloop)
441 {
442  MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totedge, "edge-poly map");
443  int *indices = MEM_mallocN(sizeof(int) * (size_t)totloop, "edge-poly map mem");
444  int *index_step;
445  const MPoly *mp;
446  int i;
447 
448  /* count face users */
449  for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
450  const MLoop *ml;
451  int j = mp->totloop;
452  for (ml = &mloop[mp->loopstart]; j--; ml++) {
453  map[ml->e].count++;
454  }
455  }
456 
457  /* create offsets */
458  index_step = indices;
459  for (i = 0; i < totedge; i++) {
460  map[i].indices = index_step;
461  index_step += map[i].count;
462 
463  /* re-count, using this as an index below */
464  map[i].count = 0;
465  }
466 
467  /* assign poly-edge users */
468  for (i = 0, mp = mpoly; i < totpoly; mp++, i++) {
469  const MLoop *ml;
470  int j = mp->totloop;
471  for (ml = &mloop[mp->loopstart]; j--; ml++) {
472  MeshElemMap *map_ele = &map[ml->e];
473  map_ele->indices[map_ele->count++] = i;
474  }
475  }
476 
477  *r_map = map;
478  *r_mem = indices;
479 }
480 
482  int **r_mem,
483  const int totsource,
484  const int *final_origindex,
485  const int totfinal)
486 {
487  MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totsource, "poly-tessface map");
488  int *indices = MEM_mallocN(sizeof(int) * (size_t)totfinal, "poly-tessface map mem");
489  int *index_step;
490  int i;
491 
492  /* count face users */
493  for (i = 0; i < totfinal; i++) {
494  if (final_origindex[i] != ORIGINDEX_NONE) {
495  BLI_assert(final_origindex[i] < totsource);
496  map[final_origindex[i]].count++;
497  }
498  }
499 
500  /* create offsets */
501  index_step = indices;
502  for (i = 0; i < totsource; i++) {
503  map[i].indices = index_step;
504  index_step += map[i].count;
505 
506  /* re-count, using this as an index below */
507  map[i].count = 0;
508  }
509 
510  /* assign poly-tessface users */
511  for (i = 0; i < totfinal; i++) {
512  if (final_origindex[i] != ORIGINDEX_NONE) {
513  MeshElemMap *map_ele = &map[final_origindex[i]];
514  map_ele->indices[map_ele->count++] = i;
515  }
516  }
517 
518  *r_map = map;
519  *r_mem = indices;
520 }
521 
523  int **r_mem,
524  const MPoly *mpoly,
525  const int mpoly_num,
526  const MLoopTri *looptri,
527  const int looptri_num)
528 {
529  MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)mpoly_num, "poly-tessface map");
530  int *indices = MEM_mallocN(sizeof(int) * (size_t)looptri_num, "poly-tessface map mem");
531  int *index_step;
532  int i;
533 
534  /* create offsets */
535  index_step = indices;
536  for (i = 0; i < mpoly_num; i++) {
537  map[i].indices = index_step;
538  index_step += ME_POLY_TRI_TOT(&mpoly[i]);
539  }
540 
541  /* assign poly-tessface users */
542  for (i = 0; i < looptri_num; i++) {
543  MeshElemMap *map_ele = &map[looptri[i].poly];
544  map_ele->indices[map_ele->count++] = i;
545  }
546 
547  *r_map = map;
548  *r_mem = indices;
549 }
550 
553 /* -------------------------------------------------------------------- */
561 typedef bool (*MeshRemap_CheckIslandBoundary)(const struct MPoly *mpoly,
562  const struct MLoop *mloop,
563  const struct MEdge *medge,
564  const int edge_user_count,
565  const struct MPoly *mpoly_array,
566  const struct MeshElemMap *edge_poly_map,
567  void *user_data);
568 
569 static void poly_edge_loop_islands_calc(const MEdge *medge,
570  const int totedge,
571  const MPoly *mpoly,
572  const int totpoly,
573  const MLoop *mloop,
574  const int totloop,
575  MeshElemMap *edge_poly_map,
576  const bool use_bitflags,
577  MeshRemap_CheckIslandBoundary edge_boundary_check,
578  void *edge_boundary_check_data,
579  int **r_poly_groups,
580  int *r_totgroup,
581  BLI_bitmap **r_edge_borders,
582  int *r_totedgeborder)
583 {
584  int *poly_groups;
585  int *poly_stack;
586 
587  BLI_bitmap *edge_borders = NULL;
588  int num_edgeborders = 0;
589 
590  int poly_prev = 0;
591  const int temp_poly_group_id = 3; /* Placeholder value. */
592 
593  /* Group we could not find any available bit, will be reset to 0 at end. */
594  const int poly_group_id_overflowed = 5;
595 
596  int tot_group = 0;
597  bool group_id_overflow = false;
598 
599  /* map vars */
600  int *edge_poly_mem = NULL;
601 
602  if (totpoly == 0) {
603  *r_totgroup = 0;
604  *r_poly_groups = NULL;
605  if (r_edge_borders) {
606  *r_edge_borders = NULL;
607  *r_totedgeborder = 0;
608  }
609  return;
610  }
611 
612  if (r_edge_borders) {
613  edge_borders = BLI_BITMAP_NEW(totedge, __func__);
614  *r_totedgeborder = 0;
615  }
616 
617  if (!edge_poly_map) {
619  &edge_poly_map, &edge_poly_mem, medge, totedge, mpoly, totpoly, mloop, totloop);
620  }
621 
622  poly_groups = MEM_callocN(sizeof(int) * (size_t)totpoly, __func__);
623  poly_stack = MEM_mallocN(sizeof(int) * (size_t)totpoly, __func__);
624 
625  while (true) {
626  int poly;
627  int bit_poly_group_mask = 0;
628  int poly_group_id;
629  int ps_curr_idx = 0, ps_end_idx = 0; /* stack indices */
630 
631  for (poly = poly_prev; poly < totpoly; poly++) {
632  if (poly_groups[poly] == 0) {
633  break;
634  }
635  }
636 
637  if (poly == totpoly) {
638  /* all done */
639  break;
640  }
641 
642  poly_group_id = use_bitflags ? temp_poly_group_id : ++tot_group;
643 
644  /* start searching from here next time */
645  poly_prev = poly + 1;
646 
647  poly_groups[poly] = poly_group_id;
648  poly_stack[ps_end_idx++] = poly;
649 
650  while (ps_curr_idx != ps_end_idx) {
651  const MPoly *mp;
652  const MLoop *ml;
653  int j;
654 
655  poly = poly_stack[ps_curr_idx++];
656  BLI_assert(poly_groups[poly] == poly_group_id);
657 
658  mp = &mpoly[poly];
659  for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) {
660  /* loop over poly users */
661  const int me_idx = (int)ml->e;
662  const MEdge *me = &medge[me_idx];
663  const MeshElemMap *map_ele = &edge_poly_map[me_idx];
664  const int *p = map_ele->indices;
665  int i = map_ele->count;
666  if (!edge_boundary_check(mp, ml, me, i, mpoly, map_ele, edge_boundary_check_data)) {
667  for (; i--; p++) {
668  /* if we meet other non initialized its a bug */
669  BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id));
670 
671  if (poly_groups[*p] == 0) {
672  poly_groups[*p] = poly_group_id;
673  poly_stack[ps_end_idx++] = *p;
674  }
675  }
676  }
677  else {
678  if (edge_borders && !BLI_BITMAP_TEST(edge_borders, me_idx)) {
679  BLI_BITMAP_ENABLE(edge_borders, me_idx);
680  num_edgeborders++;
681  }
682  if (use_bitflags) {
683  /* Find contiguous smooth groups already assigned,
684  * these are the values we can't reuse! */
685  for (; i--; p++) {
686  int bit = poly_groups[*p];
687  if (!ELEM(bit, 0, poly_group_id, poly_group_id_overflowed) &&
688  !(bit_poly_group_mask & bit)) {
689  bit_poly_group_mask |= bit;
690  }
691  }
692  }
693  }
694  }
695  }
696  /* And now, we have all our poly from current group in poly_stack
697  * (from 0 to (ps_end_idx - 1)),
698  * as well as all smoothgroups bits we can't use in bit_poly_group_mask.
699  */
700  if (use_bitflags) {
701  int i, *p, gid_bit = 0;
702  poly_group_id = 1;
703 
704  /* Find first bit available! */
705  for (; (poly_group_id & bit_poly_group_mask) && (gid_bit < 32); gid_bit++) {
706  poly_group_id <<= 1; /* will 'overflow' on last possible iteration. */
707  }
708  if (UNLIKELY(gid_bit > 31)) {
709  /* All bits used in contiguous smooth groups, we can't do much!
710  * NOTE: this is *very* unlikely - theoretically, four groups are enough,
711  * I don't think we can reach this goal with such a simple algorithm,
712  * but I don't think either we'll never need all 32 groups!
713  */
714  printf(
715  "Warning, could not find an available id for current smooth group, faces will me "
716  "marked "
717  "as out of any smooth group...\n");
718 
719  /* Can't use 0, will have to set them to this value later. */
720  poly_group_id = poly_group_id_overflowed;
721 
722  group_id_overflow = true;
723  }
724  if (gid_bit > tot_group) {
725  tot_group = gid_bit;
726  }
727  /* And assign the final smooth group id to that poly group! */
728  for (i = ps_end_idx, p = poly_stack; i--; p++) {
729  poly_groups[*p] = poly_group_id;
730  }
731  }
732  }
733 
734  if (use_bitflags) {
735  /* used bits are zero-based. */
736  tot_group++;
737  }
738 
739  if (UNLIKELY(group_id_overflow)) {
740  int i = totpoly, *gid = poly_groups;
741  for (; i--; gid++) {
742  if (*gid == poly_group_id_overflowed) {
743  *gid = 0;
744  }
745  }
746  /* Using 0 as group id adds one more group! */
747  tot_group++;
748  }
749 
750  if (edge_poly_mem) {
751  MEM_freeN(edge_poly_map);
752  MEM_freeN(edge_poly_mem);
753  }
754  MEM_freeN(poly_stack);
755 
756  *r_totgroup = tot_group;
757  *r_poly_groups = poly_groups;
758  if (r_edge_borders) {
759  *r_edge_borders = edge_borders;
760  *r_totedgeborder = num_edgeborders;
761  }
762 }
763 
765  const MLoop *UNUSED(ml),
766  const MEdge *me,
767  const int edge_user_count,
768  const MPoly *mpoly_array,
769  const MeshElemMap *edge_poly_map,
770  void *UNUSED(user_data))
771 {
772  /* Edge is sharp if one of its polys is flat, or edge itself is sharp,
773  * or edge is not used by exactly two polygons. */
774  if ((mp->flag & ME_SMOOTH) && !(me->flag & ME_SHARP) && (edge_user_count == 2)) {
775  /* In that case, edge appears to be smooth, but we need to check its other poly too. */
776  const MPoly *mp_other = (mp == &mpoly_array[edge_poly_map->indices[0]]) ?
777  &mpoly_array[edge_poly_map->indices[1]] :
778  &mpoly_array[edge_poly_map->indices[0]];
779  return (mp_other->flag & ME_SMOOTH) == 0;
780  }
781  return true;
782 }
783 
785  const int totedge,
786  const MPoly *mpoly,
787  const int totpoly,
788  const MLoop *mloop,
789  const int totloop,
790  int *r_totgroup,
791  const bool use_bitflags)
792 {
793  int *poly_groups = NULL;
794 
796  totedge,
797  mpoly,
798  totpoly,
799  mloop,
800  totloop,
801  NULL,
802  use_bitflags,
804  NULL,
805  &poly_groups,
806  r_totgroup,
807  NULL,
808  NULL);
809 
810  return poly_groups;
811 }
812 
813 #define MISLAND_DEFAULT_BUFSIZE 64
814 
816  const short item_type,
817  const int items_num,
818  const short island_type,
819  const short innercut_type)
820 {
821  MemArena *mem = island_store->mem;
822 
823  if (mem == NULL) {
825  island_store->mem = mem;
826  }
827  /* else memarena should be cleared */
828 
829  BLI_assert(
833 
834  island_store->item_type = item_type;
835  island_store->items_to_islands_num = items_num;
836  island_store->items_to_islands = BLI_memarena_alloc(
837  mem, sizeof(*island_store->items_to_islands) * (size_t)items_num);
838 
839  island_store->island_type = island_type;
841  island_store->islands = BLI_memarena_alloc(
842  mem, sizeof(*island_store->islands) * island_store->islands_num_alloc);
843 
844  island_store->innercut_type = innercut_type;
845  island_store->innercuts = BLI_memarena_alloc(
846  mem, sizeof(*island_store->innercuts) * island_store->islands_num_alloc);
847 }
848 
850 {
851  island_store->item_type = MISLAND_TYPE_NONE;
852  island_store->items_to_islands_num = 0;
853  island_store->items_to_islands = NULL;
854 
855  island_store->island_type = MISLAND_TYPE_NONE;
856  island_store->islands_num = 0;
857  island_store->islands = NULL;
858 
859  island_store->innercut_type = MISLAND_TYPE_NONE;
860  island_store->innercuts = NULL;
861 
862  if (island_store->mem) {
863  BLI_memarena_clear(island_store->mem);
864  }
865 
866  island_store->islands_num_alloc = 0;
867 }
868 
870 {
871  if (island_store->mem) {
872  BLI_memarena_free(island_store->mem);
873  island_store->mem = NULL;
874  }
875 }
876 
878  const int item_num,
879  const int *items_indices,
880  const int num_island_items,
881  int *island_item_indices,
882  const int num_innercut_items,
883  int *innercut_item_indices)
884 {
885  MemArena *mem = island_store->mem;
886 
887  MeshElemMap *isld, *innrcut;
888  const int curr_island_idx = island_store->islands_num++;
889  const size_t curr_num_islands = (size_t)island_store->islands_num;
890  int i = item_num;
891 
892  while (i--) {
893  island_store->items_to_islands[items_indices[i]] = curr_island_idx;
894  }
895 
896  if (UNLIKELY(curr_num_islands > island_store->islands_num_alloc)) {
897  MeshElemMap **islds, **innrcuts;
898 
899  island_store->islands_num_alloc *= 2;
900  islds = BLI_memarena_alloc(mem, sizeof(*islds) * island_store->islands_num_alloc);
901  memcpy(islds, island_store->islands, sizeof(*islds) * (curr_num_islands - 1));
902  island_store->islands = islds;
903 
904  innrcuts = BLI_memarena_alloc(mem, sizeof(*innrcuts) * island_store->islands_num_alloc);
905  memcpy(innrcuts, island_store->innercuts, sizeof(*innrcuts) * (curr_num_islands - 1));
906  island_store->innercuts = innrcuts;
907  }
908 
909  island_store->islands[curr_island_idx] = isld = BLI_memarena_alloc(mem, sizeof(*isld));
910  isld->count = num_island_items;
911  isld->indices = BLI_memarena_alloc(mem, sizeof(*isld->indices) * (size_t)num_island_items);
912  memcpy(isld->indices, island_item_indices, sizeof(*isld->indices) * (size_t)num_island_items);
913 
914  island_store->innercuts[curr_island_idx] = innrcut = BLI_memarena_alloc(mem, sizeof(*innrcut));
915  innrcut->count = num_innercut_items;
916  innrcut->indices = BLI_memarena_alloc(mem,
917  sizeof(*innrcut->indices) * (size_t)num_innercut_items);
918  memcpy(innrcut->indices,
919  innercut_item_indices,
920  sizeof(*innrcut->indices) * (size_t)num_innercut_items);
921 }
922 
923 /* TODO: I'm not sure edge seam flag is enough to define UV islands?
924  * Maybe we should also consider UV-maps values
925  * themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?).
926  * Would make things much more complex though,
927  * and each UVMap would then need its own mesh mapping, not sure we want that at all!
928  */
930  const MLoop *loops;
931  const MLoopUV *luvs;
934 
936  const MLoop *ml,
937  const MEdge *me,
938  const int UNUSED(edge_user_count),
939  const MPoly *UNUSED(mpoly_array),
940  const MeshElemMap *UNUSED(edge_poly_map),
941  void *user_data)
942 {
943  if (user_data) {
945  const MLoop *loops = data->loops;
946  const MLoopUV *luvs = data->luvs;
947  const MeshElemMap *edge_to_loops = &data->edge_loop_map[ml->e];
948 
949  BLI_assert(edge_to_loops->count >= 2 && (edge_to_loops->count % 2) == 0);
950 
951  const uint v1 = loops[edge_to_loops->indices[0]].v;
952  const uint v2 = loops[edge_to_loops->indices[1]].v;
953  const float *uvco_v1 = luvs[edge_to_loops->indices[0]].uv;
954  const float *uvco_v2 = luvs[edge_to_loops->indices[1]].uv;
955  for (int i = 2; i < edge_to_loops->count; i += 2) {
956  if (loops[edge_to_loops->indices[i]].v == v1) {
957  if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]].uv) ||
958  !equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i + 1]].uv)) {
959  return true;
960  }
961  }
962  else {
963  BLI_assert(loops[edge_to_loops->indices[i]].v == v2);
965  if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]].uv) ||
966  !equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i + 1]].uv)) {
967  return true;
968  }
969  }
970  }
971  return false;
972  }
973 
974  /* Edge is UV boundary if tagged as seam. */
975  return (me->flag & ME_SEAM) != 0;
976 }
977 
979  const int UNUSED(totvert),
980  MEdge *edges,
981  const int totedge,
982  MPoly *polys,
983  const int totpoly,
984  MLoop *loops,
985  const int totloop,
986  const MLoopUV *luvs,
987  MeshIslandStore *r_island_store)
988 {
989  int *poly_groups = NULL;
990  int num_poly_groups;
991 
992  /* map vars */
993  MeshElemMap *edge_poly_map;
994  int *edge_poly_mem;
995 
996  MeshElemMap *edge_loop_map;
997  int *edge_loop_mem;
998 
999  MeshCheckIslandBoundaryUv edge_boundary_check_data;
1000 
1001  int *poly_indices;
1002  int *loop_indices;
1003  int num_pidx, num_lidx;
1004 
1005  /* Those are used to detect 'inner cuts', i.e. edges that are borders,
1006  * and yet have two or more polys of a same group using them
1007  * (typical case: seam used to unwrap properly a cylinder). */
1008  BLI_bitmap *edge_borders = NULL;
1009  int num_edge_borders = 0;
1010  char *edge_border_count = NULL;
1011  int *edge_innercut_indices = NULL;
1012  int num_einnercuts = 0;
1013 
1014  int grp_idx, p_idx, pl_idx, l_idx;
1015 
1016  BKE_mesh_loop_islands_clear(r_island_store);
1018  r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE);
1019 
1021  &edge_poly_map, &edge_poly_mem, edges, totedge, polys, totpoly, loops, totloop);
1022 
1023  if (luvs) {
1025  &edge_loop_map, &edge_loop_mem, edges, totedge, polys, totpoly, loops, totloop);
1026  edge_boundary_check_data.loops = loops;
1027  edge_boundary_check_data.luvs = luvs;
1028  edge_boundary_check_data.edge_loop_map = edge_loop_map;
1029  }
1030 
1032  totedge,
1033  polys,
1034  totpoly,
1035  loops,
1036  totloop,
1037  edge_poly_map,
1038  false,
1040  luvs ? &edge_boundary_check_data : NULL,
1041  &poly_groups,
1042  &num_poly_groups,
1043  &edge_borders,
1044  &num_edge_borders);
1045 
1046  if (!num_poly_groups) {
1047  /* Should never happen... */
1048  MEM_freeN(edge_poly_map);
1049  MEM_freeN(edge_poly_mem);
1050 
1051  if (edge_borders) {
1052  MEM_freeN(edge_borders);
1053  }
1054  return false;
1055  }
1056 
1057  if (num_edge_borders) {
1058  edge_border_count = MEM_mallocN(sizeof(*edge_border_count) * (size_t)totedge, __func__);
1059  edge_innercut_indices = MEM_mallocN(sizeof(*edge_innercut_indices) * (size_t)num_edge_borders,
1060  __func__);
1061  }
1062 
1063  poly_indices = MEM_mallocN(sizeof(*poly_indices) * (size_t)totpoly, __func__);
1064  loop_indices = MEM_mallocN(sizeof(*loop_indices) * (size_t)totloop, __func__);
1065 
1066  /* NOTE: here we ignore '0' invalid group - this should *never* happen in this case anyway? */
1067  for (grp_idx = 1; grp_idx <= num_poly_groups; grp_idx++) {
1068  num_pidx = num_lidx = 0;
1069  if (num_edge_borders) {
1070  num_einnercuts = 0;
1071  memset(edge_border_count, 0, sizeof(*edge_border_count) * (size_t)totedge);
1072  }
1073 
1074  for (p_idx = 0; p_idx < totpoly; p_idx++) {
1075  MPoly *mp;
1076 
1077  if (poly_groups[p_idx] != grp_idx) {
1078  continue;
1079  }
1080 
1081  mp = &polys[p_idx];
1082  poly_indices[num_pidx++] = p_idx;
1083  for (l_idx = mp->loopstart, pl_idx = 0; pl_idx < mp->totloop; l_idx++, pl_idx++) {
1084  MLoop *ml = &loops[l_idx];
1085  loop_indices[num_lidx++] = l_idx;
1086  if (num_edge_borders && BLI_BITMAP_TEST(edge_borders, ml->e) &&
1087  (edge_border_count[ml->e] < 2)) {
1088  edge_border_count[ml->e]++;
1089  if (edge_border_count[ml->e] == 2) {
1090  edge_innercut_indices[num_einnercuts++] = (int)ml->e;
1091  }
1092  }
1093  }
1094  }
1095 
1096  BKE_mesh_loop_islands_add(r_island_store,
1097  num_lidx,
1098  loop_indices,
1099  num_pidx,
1100  poly_indices,
1101  num_einnercuts,
1102  edge_innercut_indices);
1103  }
1104 
1105  MEM_freeN(edge_poly_map);
1106  MEM_freeN(edge_poly_mem);
1107 
1108  if (luvs) {
1109  MEM_freeN(edge_loop_map);
1110  MEM_freeN(edge_loop_mem);
1111  }
1112 
1113  MEM_freeN(poly_indices);
1114  MEM_freeN(loop_indices);
1115  MEM_freeN(poly_groups);
1116 
1117  if (edge_borders) {
1118  MEM_freeN(edge_borders);
1119  }
1120 
1121  if (num_edge_borders) {
1122  MEM_freeN(edge_border_count);
1123  MEM_freeN(edge_innercut_indices);
1124  }
1125  return true;
1126 }
1127 
1129  const int totvert,
1130  MEdge *edges,
1131  const int totedge,
1132  MPoly *polys,
1133  const int totpoly,
1134  MLoop *loops,
1135  const int totloop,
1136  MeshIslandStore *r_island_store)
1137 {
1139  verts, totvert, edges, totedge, polys, totpoly, loops, totloop, NULL, r_island_store);
1140 }
1141 
1143  const int totvert,
1144  MEdge *edges,
1145  const int totedge,
1146  MPoly *polys,
1147  const int totpoly,
1148  MLoop *loops,
1149  const int totloop,
1150  const MLoopUV *luvs,
1151  MeshIslandStore *r_island_store)
1152 {
1153  BLI_assert(luvs != NULL);
1155  verts, totvert, edges, totedge, polys, totpoly, loops, totloop, luvs, r_island_store);
1156 }
1157 
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
#define ORIGINDEX_NONE
@ MISLAND_TYPE_POLY
@ MISLAND_TYPE_VERT
@ MISLAND_TYPE_LOOP
@ MISLAND_TYPE_EDGE
@ MISLAND_TYPE_NONE
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition: BLI_bitmap.h:40
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:64
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:81
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:16
#define BLI_buffer_reinit_data(buffer_, type_, new_count_)
Definition: BLI_buffer.h:47
@ BLI_BUFFER_NOP
Definition: BLI_buffer.h:21
#define BLI_buffer_declare_static(type_, name_, flag_, static_count_)
Definition: BLI_buffer.h:25
#define BLI_buffer_free(name_)
Definition: BLI_buffer.h:94
float cross_poly_v2(const float verts[][2], unsigned int nr)
Definition: math_geom.c:141
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_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:94
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:64
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:20
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:116
void void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:208
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
@ ME_HIDE
@ ME_SMOOTH
@ ME_FACE_SEL
#define ME_POLY_TRI_TOT(mp)
@ ME_SEAM
@ ME_SHARP
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
return(oflags[bm->toolflag_index].f &oflag) !=0
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
void * user_data
static float verts[][3]
ccl_gpu_kernel_postfix int ccl_global int * indices
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static ulong * next
struct MeshCheckIslandBoundaryUv MeshCheckIslandBoundaryUv
static bool mesh_calc_islands_loop_poly_uv(MVert *UNUSED(verts), const int UNUSED(totvert), MEdge *edges, const int totedge, MPoly *polys, const int totpoly, MLoop *loops, const int totloop, const MLoopUV *luvs, MeshIslandStore *r_island_store)
Definition: mesh_mapping.c:978
bool BKE_mesh_calc_islands_loop_poly_uvmap(MVert *verts, const int totvert, MEdge *edges, const int totedge, MPoly *polys, const int totpoly, MLoop *loops, const int totloop, const MLoopUV *luvs, MeshIslandStore *r_island_store)
static void poly_edge_loop_islands_calc(const MEdge *medge, const int totedge, const MPoly *mpoly, const int totpoly, const MLoop *mloop, const int totloop, MeshElemMap *edge_poly_map, const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check, void *edge_boundary_check_data, int **r_poly_groups, int *r_totgroup, BLI_bitmap **r_edge_borders, int *r_totedgeborder)
Definition: mesh_mapping.c:569
void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem, const MPoly *mpoly, const MLoop *mloop, int totvert, int totpoly, int totloop)
Definition: mesh_mapping.c:247
void BKE_mesh_origindex_map_create(MeshElemMap **r_map, int **r_mem, const int totsource, const int *final_origindex, const int totfinal)
Definition: mesh_mapping.c:481
void BKE_mesh_vert_edge_vert_map_create(MeshElemMap **r_map, int **r_mem, const MEdge *medge, int totvert, int totedge)
Definition: mesh_mapping.c:341
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)
Definition: mesh_mapping.c:877
bool(* MeshRemap_CheckIslandBoundary)(const struct MPoly *mpoly, const struct MLoop *mloop, const struct MEdge *medge, const int edge_user_count, const struct MPoly *mpoly_array, const struct MeshElemMap *edge_poly_map, void *user_data)
Definition: mesh_mapping.c:561
UvMapVert * BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, uint v)
Definition: mesh_mapping.c:162
static bool poly_is_island_boundary_smooth_cb(const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, const int edge_user_count, const MPoly *mpoly_array, const MeshElemMap *edge_poly_map, void *UNUSED(user_data))
Definition: mesh_mapping.c:764
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)
Definition: mesh_mapping.c:815
#define MISLAND_DEFAULT_BUFSIZE
Definition: mesh_mapping.c:813
int * BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, const MPoly *mpoly, const int totpoly, const MLoop *mloop, const int totloop, int *r_totgroup, const bool use_bitflags)
Definition: mesh_mapping.c:784
void BKE_mesh_loop_islands_clear(MeshIslandStore *island_store)
Definition: mesh_mapping.c:849
UvVertMap * BKE_mesh_uv_vert_map_create(const MPoly *mpoly, const MLoop *mloop, const MLoopUV *mloopuv, uint totpoly, uint totvert, const float limit[2], const bool selected, const bool use_winding)
Definition: mesh_mapping.c:31
void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, int **r_mem, const MVert *UNUSED(mvert), const int totvert, const MLoopTri *mlooptri, const int totlooptri, const MLoop *mloop, const int UNUSED(totloop))
Definition: mesh_mapping.c:258
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
Definition: mesh_mapping.c:167
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem, const MPoly *mpoly, const MLoop *mloop, int totvert, int totpoly, int totloop)
Definition: mesh_mapping.c:236
void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem, const MEdge *medge, int totvert, int totedge)
Definition: mesh_mapping.c:302
static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map, int **r_mem, const MPoly *mpoly, const MLoop *mloop, int totvert, int totpoly, int totloop, const bool do_loops)
Definition: mesh_mapping.c:187
void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, int **r_mem, const MEdge *UNUSED(medge), const int totedge, const MPoly *mpoly, const int totpoly, const MLoop *mloop, const int totloop)
Definition: mesh_mapping.c:380
void BKE_mesh_loop_islands_free(MeshIslandStore *island_store)
Definition: mesh_mapping.c:869
void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map, int **r_mem, const MPoly *mpoly, const int mpoly_num, const MLoopTri *looptri, const int looptri_num)
Definition: mesh_mapping.c:522
bool BKE_mesh_calc_islands_loop_poly_edgeseam(MVert *verts, const int totvert, MEdge *edges, const int totedge, MPoly *polys, const int totpoly, MLoop *loops, const int totloop, MeshIslandStore *r_island_store)
void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem, const MEdge *UNUSED(medge), const int totedge, const MPoly *mpoly, const int totpoly, const MLoop *mloop, const int totloop)
Definition: mesh_mapping.c:433
static bool mesh_check_island_boundary_uv(const MPoly *UNUSED(mp), const MLoop *ml, const MEdge *me, const int UNUSED(edge_user_count), const MPoly *UNUSED(mpoly_array), const MeshElemMap *UNUSED(edge_poly_map), void *user_data)
Definition: mesh_mapping.c:935
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned a[3]
Definition: RandGen.cpp:78
SocketIndexByIdentifierMap * map
unsigned int v1
unsigned int v2
unsigned int poly
unsigned int tri[3]
unsigned int e
unsigned int v
const MeshElemMap * edge_loop_map
Definition: mesh_mapping.c:932
struct MemArena * mem
struct MeshElemMap ** innercuts
struct MeshElemMap ** islands
struct UvMapVert * next
unsigned short loop_of_poly_index
unsigned int poly_index
struct UvMapVert * buf
struct UvMapVert ** vert