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