Blender  V3.3
mesh_legacy_convert.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
10 // #include <climits>
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "DNA_mesh_types.h"
15 #include "DNA_meshdata_types.h"
16 
17 #include "BLI_edgehash.h"
18 #include "BLI_math.h"
19 #include "BLI_memarena.h"
20 #include "BLI_polyfill_2d.h"
21 #include "BLI_utildefines.h"
22 
23 #include "BKE_customdata.h"
24 #include "BKE_mesh.h"
26 #include "BKE_multires.h"
27 
28 /* -------------------------------------------------------------------- */
32 static void bm_corners_to_loops_ex(ID *id,
33  CustomData *fdata,
34  CustomData *ldata,
35  MFace *mface,
36  int totloop,
37  int findex,
38  int loopstart,
39  int numTex,
40  int numCol)
41 {
42  MFace *mf = mface + findex;
43 
44  for (int i = 0; i < numTex; i++) {
45  const MTFace *texface = (const MTFace *)CustomData_get_n(fdata, CD_MTFACE, findex, i);
46 
47  MLoopUV *mloopuv = (MLoopUV *)CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
48  copy_v2_v2(mloopuv->uv, texface->uv[0]);
49  mloopuv++;
50  copy_v2_v2(mloopuv->uv, texface->uv[1]);
51  mloopuv++;
52  copy_v2_v2(mloopuv->uv, texface->uv[2]);
53  mloopuv++;
54 
55  if (mf->v4) {
56  copy_v2_v2(mloopuv->uv, texface->uv[3]);
57  mloopuv++;
58  }
59  }
60 
61  for (int i = 0; i < numCol; i++) {
62  MLoopCol *mloopcol = (MLoopCol *)CustomData_get_n(ldata, CD_PROP_BYTE_COLOR, loopstart, i);
63  const MCol *mcol = (const MCol *)CustomData_get_n(fdata, CD_MCOL, findex, i);
64 
65  MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[0]);
66  mloopcol++;
67  MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[1]);
68  mloopcol++;
69  MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[2]);
70  mloopcol++;
71  if (mf->v4) {
72  MESH_MLOOPCOL_FROM_MCOL(mloopcol, &mcol[3]);
73  mloopcol++;
74  }
75  }
76 
78  float(*lnors)[3] = (float(*)[3])CustomData_get(ldata, loopstart, CD_NORMAL);
79  const short(*tlnors)[3] = (short(*)[3])CustomData_get(fdata, findex, CD_TESSLOOPNORMAL);
80  const int max = mf->v4 ? 4 : 3;
81 
82  for (int i = 0; i < max; i++, lnors++, tlnors++) {
83  normal_short_to_float_v3(*lnors, *tlnors);
84  }
85  }
86 
87  if (CustomData_has_layer(fdata, CD_MDISPS)) {
88  MDisps *ld = (MDisps *)CustomData_get(ldata, loopstart, CD_MDISPS);
89  const MDisps *fd = (const MDisps *)CustomData_get(fdata, findex, CD_MDISPS);
90  const float(*disps)[3] = fd->disps;
91  int tot = mf->v4 ? 4 : 3;
92  int corners;
93 
94  if (CustomData_external_test(fdata, CD_MDISPS)) {
95  if (id && fdata->external) {
96  CustomData_external_add(ldata, id, CD_MDISPS, totloop, fdata->external->filepath);
97  }
98  }
99 
100  corners = multires_mdisp_corners(fd);
101 
102  if (corners == 0) {
103  /* Empty #MDisp layers appear in at least one of the `sintel.blend` files.
104  * Not sure why this happens, but it seems fine to just ignore them here.
105  * If `corners == 0` for a non-empty layer though, something went wrong. */
106  BLI_assert(fd->totdisp == 0);
107  }
108  else {
109  const int side = (int)sqrtf((float)(fd->totdisp / corners));
110  const int side_sq = side * side;
111 
112  for (int i = 0; i < tot; i++, disps += side_sq, ld++) {
113  ld->totdisp = side_sq;
114  ld->level = (int)(logf((float)side - 1.0f) / (float)M_LN2) + 1;
115 
116  if (ld->disps) {
117  MEM_freeN(ld->disps);
118  }
119 
120  ld->disps = (float(*)[3])MEM_malloc_arrayN(
121  (size_t)side_sq, sizeof(float[3]), "converted loop mdisps");
122  if (fd->disps) {
123  memcpy(ld->disps, disps, (size_t)side_sq * sizeof(float[3]));
124  }
125  else {
126  memset(ld->disps, 0, (size_t)side_sq * sizeof(float[3]));
127  }
128  }
129  }
130  }
131 }
132 
133 static void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int totloop)
134 {
135  for (int i = 0; i < fdata->totlayer; i++) {
136  if (fdata->layers[i].type == CD_MTFACE) {
138  ldata, CD_MLOOPUV, CD_CALLOC, nullptr, totloop, fdata->layers[i].name);
139  }
140  else if (fdata->layers[i].type == CD_MCOL) {
142  ldata, CD_PROP_BYTE_COLOR, CD_CALLOC, nullptr, totloop, fdata->layers[i].name);
143  }
144  else if (fdata->layers[i].type == CD_MDISPS) {
146  ldata, CD_MDISPS, CD_CALLOC, nullptr, totloop, fdata->layers[i].name);
147  }
148  else if (fdata->layers[i].type == CD_TESSLOOPNORMAL) {
150  ldata, CD_NORMAL, CD_CALLOC, nullptr, totloop, fdata->layers[i].name);
151  }
152  }
153 }
154 
155 static void convert_mfaces_to_mpolys(ID *id,
156  CustomData *fdata,
157  CustomData *ldata,
158  CustomData *pdata,
159  int totedge_i,
160  int totface_i,
161  int totloop_i,
162  int totpoly_i,
163  MEdge *medge,
164  MFace *mface,
165  int *r_totloop,
166  int *r_totpoly,
167  MLoop **r_mloop,
168  MPoly **r_mpoly)
169 {
170  MFace *mf;
171  MLoop *ml, *mloop;
172  MPoly *mp, *mpoly;
173  MEdge *me;
174  EdgeHash *eh;
175  int numTex, numCol;
176  int i, j, totloop, totpoly, *polyindex;
177 
178  /* old flag, clear to allow for reuse */
179 #define ME_FGON (1 << 3)
180 
181  /* just in case some of these layers are filled in (can happen with python created meshes) */
182  CustomData_free(ldata, totloop_i);
183  CustomData_free(pdata, totpoly_i);
184 
185  totpoly = totface_i;
186  mpoly = (MPoly *)MEM_calloc_arrayN((size_t)totpoly, sizeof(MPoly), "mpoly converted");
187  CustomData_add_layer(pdata, CD_MPOLY, CD_ASSIGN, mpoly, totpoly);
188 
189  numTex = CustomData_number_of_layers(fdata, CD_MTFACE);
190  numCol = CustomData_number_of_layers(fdata, CD_MCOL);
191 
192  totloop = 0;
193  mf = mface;
194  for (i = 0; i < totface_i; i++, mf++) {
195  totloop += mf->v4 ? 4 : 3;
196  }
197 
198  mloop = (MLoop *)MEM_calloc_arrayN((size_t)totloop, sizeof(MLoop), "mloop converted");
199 
200  CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop);
201 
202  CustomData_to_bmeshpoly(fdata, ldata, totloop);
203 
204  if (id) {
205  /* ensure external data is transferred */
206  /* TODO(sergey): Use multiresModifier_ensure_external_read(). */
207  CustomData_external_read(fdata, id, CD_MASK_MDISPS, totface_i);
208  }
209 
210  eh = BLI_edgehash_new_ex(__func__, (uint)totedge_i);
211 
212  /* build edge hash */
213  me = medge;
214  for (i = 0; i < totedge_i; i++, me++) {
215  BLI_edgehash_insert(eh, me->v1, me->v2, POINTER_FROM_UINT(i));
216 
217  /* unrelated but avoid having the FGON flag enabled,
218  * so we can reuse it later for something else */
219  me->flag &= ~ME_FGON;
220  }
221 
222  polyindex = (int *)CustomData_get_layer(fdata, CD_ORIGINDEX);
223 
224  j = 0; /* current loop index */
225  ml = mloop;
226  mf = mface;
227  mp = mpoly;
228  for (i = 0; i < totface_i; i++, mf++, mp++) {
229  mp->loopstart = j;
230 
231  mp->totloop = mf->v4 ? 4 : 3;
232 
233  mp->mat_nr = mf->mat_nr;
234  mp->flag = mf->flag;
235 
236 #define ML(v1, v2) \
237  { \
238  ml->v = mf->v1; \
239  ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(eh, mf->v1, mf->v2)); \
240  ml++; \
241  j++; \
242  } \
243  (void)0
244 
245  ML(v1, v2);
246  ML(v2, v3);
247  if (mf->v4) {
248  ML(v3, v4);
249  ML(v4, v1);
250  }
251  else {
252  ML(v3, v1);
253  }
254 
255 #undef ML
256 
257  bm_corners_to_loops_ex(id, fdata, ldata, mface, totloop, i, mp->loopstart, numTex, numCol);
258 
259  if (polyindex) {
260  *polyindex = i;
261  polyindex++;
262  }
263  }
264 
265  /* NOTE: we don't convert NGons at all, these are not even real ngons,
266  * they have their own UV's, colors etc - its more an editing feature. */
267 
268  BLI_edgehash_free(eh, nullptr);
269 
270  *r_totpoly = totpoly;
271  *r_totloop = totloop;
272  *r_mpoly = mpoly;
273  *r_mloop = mloop;
274 
275 #undef ME_FGON
276 }
277 
279 {
281  &mesh->fdata,
282  &mesh->ldata,
283  &mesh->pdata,
284  mesh->totedge,
285  mesh->totface,
286  mesh->totloop,
287  mesh->totpoly,
288  mesh->medge,
289  mesh->mface,
290  &mesh->totloop,
291  &mesh->totpoly,
292  &mesh->mloop,
293  &mesh->mpoly);
294 
296 }
297 
305 {
306  int act;
307 
308  if (CustomData_has_layer(fdata, CD_MTFACE)) {
311 
314 
317 
320  }
321 
322  if (CustomData_has_layer(fdata, CD_MCOL)) {
323  act = CustomData_get_active_layer(fdata, CD_MCOL);
325 
326  act = CustomData_get_render_layer(fdata, CD_MCOL);
328 
329  act = CustomData_get_clone_layer(fdata, CD_MCOL);
331 
334  }
335 }
336 
338 {
340  &mesh->fdata,
341  &mesh->ldata,
342  &mesh->pdata,
343  mesh->totedge,
344  mesh->totface,
345  mesh->totloop,
346  mesh->totpoly,
347  mesh->medge,
348  mesh->mface,
349  &mesh->totloop,
350  &mesh->totpoly,
351  &mesh->mloop,
352  &mesh->mpoly);
353 
355 
357 }
358 
361 /* -------------------------------------------------------------------- */
377  CustomData *ldata,
378  MFace *mface,
379  const int *polyindices,
380  uint (*loopindices)[4],
381  const int num_faces)
382 {
383  /* NOTE(mont29): performances are sub-optimal when we get a null #MFace,
384  * we could be ~25% quicker with dedicated code.
385  * The issue is, unless having two different functions with nearly the same code,
386  * there's not much ways to solve this. Better IMHO to live with it for now (sigh). */
387  const int numUV = CustomData_number_of_layers(ldata, CD_MLOOPUV);
388  const int numCol = CustomData_number_of_layers(ldata, CD_PROP_BYTE_COLOR);
389  const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
390  const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
391  const bool hasLoopNormal = CustomData_has_layer(ldata, CD_NORMAL);
392  const bool hasLoopTangent = CustomData_has_layer(ldata, CD_TANGENT);
393  int findex, i, j;
394  const int *pidx;
395  uint(*lidx)[4];
396 
397  for (i = 0; i < numUV; i++) {
398  MTFace *texface = (MTFace *)CustomData_get_layer_n(fdata, CD_MTFACE, i);
399  const MLoopUV *mloopuv = (const MLoopUV *)CustomData_get_layer_n(ldata, CD_MLOOPUV, i);
400 
401  for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces;
402  pidx++, lidx++, findex++, texface++) {
403  for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
404  copy_v2_v2(texface->uv[j], mloopuv[(*lidx)[j]].uv);
405  }
406  }
407  }
408 
409  for (i = 0; i < numCol; i++) {
410  MCol(*mcol)[4] = (MCol(*)[4])CustomData_get_layer_n(fdata, CD_MCOL, i);
411  const MLoopCol *mloopcol = (const MLoopCol *)CustomData_get_layer_n(
412  ldata, CD_PROP_BYTE_COLOR, i);
413 
414  for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) {
415  for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
416  MESH_MLOOPCOL_TO_MCOL(&mloopcol[(*lidx)[j]], &(*mcol)[j]);
417  }
418  }
419  }
420 
421  if (hasPCol) {
422  MCol(*mcol)[4] = (MCol(*)[4])CustomData_get_layer(fdata, CD_PREVIEW_MCOL);
423  const MLoopCol *mloopcol = (const MLoopCol *)CustomData_get_layer(ldata, CD_PREVIEW_MLOOPCOL);
424 
425  for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) {
426  for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
427  MESH_MLOOPCOL_TO_MCOL(&mloopcol[(*lidx)[j]], &(*mcol)[j]);
428  }
429  }
430  }
431 
432  if (hasOrigSpace) {
434  const OrigSpaceLoop *lof = (const OrigSpaceLoop *)CustomData_get_layer(ldata,
436 
437  for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, of++) {
438  for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
439  copy_v2_v2(of->uv[j], lof[(*lidx)[j]].uv);
440  }
441  }
442  }
443 
444  if (hasLoopNormal) {
445  short(*fnors)[4][3] = (short(*)[4][3])CustomData_get_layer(fdata, CD_TESSLOOPNORMAL);
446  const float(*lnors)[3] = (const float(*)[3])CustomData_get_layer(ldata, CD_NORMAL);
447 
448  for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, fnors++) {
449  for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
450  normal_float_to_short_v3((*fnors)[j], lnors[(*lidx)[j]]);
451  }
452  }
453  }
454 
455  if (hasLoopTangent) {
456  /* Need to do for all UV maps at some point. */
457  float(*ftangents)[4] = (float(*)[4])CustomData_get_layer(fdata, CD_TANGENT);
458  const float(*ltangents)[4] = (const float(*)[4])CustomData_get_layer(ldata, CD_TANGENT);
459 
460  for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces;
461  pidx++, lidx++, findex++) {
462  int nverts = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3;
463  for (j = nverts; j--;) {
464  copy_v4_v4(ftangents[findex * 4 + j], ltangents[(*lidx)[j]]);
465  }
466  }
467  }
468 }
469 
470 int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex, int nr)
471 {
472  /* first test if the face is legal */
473  if ((mface->v3 || nr == 4) && mface->v3 == mface->v4) {
474  mface->v4 = 0;
475  nr--;
476  }
477  if ((mface->v2 || mface->v4) && mface->v2 == mface->v3) {
478  mface->v3 = mface->v4;
479  mface->v4 = 0;
480  nr--;
481  }
482  if (mface->v1 == mface->v2) {
483  mface->v2 = mface->v3;
484  mface->v3 = mface->v4;
485  mface->v4 = 0;
486  nr--;
487  }
488 
489  /* Check corrupt cases, bow-tie geometry,
490  * can't handle these because edge data won't exist so just return 0. */
491  if (nr == 3) {
492  if (
493  /* real edges */
494  mface->v1 == mface->v2 || mface->v2 == mface->v3 || mface->v3 == mface->v1) {
495  return 0;
496  }
497  }
498  else if (nr == 4) {
499  if (
500  /* real edges */
501  mface->v1 == mface->v2 || mface->v2 == mface->v3 || mface->v3 == mface->v4 ||
502  mface->v4 == mface->v1 ||
503  /* across the face */
504  mface->v1 == mface->v3 || mface->v2 == mface->v4) {
505  return 0;
506  }
507  }
508 
509  /* prevent a zero at wrong index location */
510  if (nr == 3) {
511  if (mface->v3 == 0) {
512  static int corner_indices[4] = {1, 2, 0, 3};
513 
514  SWAP(uint, mface->v1, mface->v2);
515  SWAP(uint, mface->v2, mface->v3);
516 
517  if (fdata) {
518  CustomData_swap_corners(fdata, mfindex, corner_indices);
519  }
520  }
521  }
522  else if (nr == 4) {
523  if (mface->v3 == 0 || mface->v4 == 0) {
524  static int corner_indices[4] = {2, 3, 0, 1};
525 
526  SWAP(uint, mface->v1, mface->v3);
527  SWAP(uint, mface->v2, mface->v4);
528 
529  if (fdata) {
530  CustomData_swap_corners(fdata, mfindex, corner_indices);
531  }
532  }
533  }
534 
535  return nr;
536 }
537 
538 static int mesh_tessface_calc(CustomData *fdata,
539  CustomData *ldata,
540  CustomData *pdata,
541  MVert *mvert,
542  int totface,
543  int totloop,
544  int totpoly)
545 {
546 #define USE_TESSFACE_SPEEDUP
547 #define USE_TESSFACE_QUADS
548 
549 /* We abuse #MFace.edcode to tag quad faces. See below for details. */
550 #define TESSFACE_IS_QUAD 1
551 
552  const int looptri_num = poly_to_tri_count(totpoly, totloop);
553 
554  const MPoly *mp, *mpoly;
555  const MLoop *ml, *mloop;
556  MFace *mface, *mf;
557  MemArena *arena = nullptr;
558  int *mface_to_poly_map;
559  uint(*lindices)[4];
560  int poly_index, mface_index;
561  uint j;
562 
563  mpoly = (const MPoly *)CustomData_get_layer(pdata, CD_MPOLY);
564  mloop = (const MLoop *)CustomData_get_layer(ldata, CD_MLOOP);
565 
566  /* Allocate the length of `totfaces`, avoid many small reallocation's,
567  * if all faces are triangles it will be correct, `quads == 2x` allocations. */
568  /* Take care since memory is _not_ zeroed so be sure to initialize each field. */
569  mface_to_poly_map = (int *)MEM_malloc_arrayN(
570  (size_t)looptri_num, sizeof(*mface_to_poly_map), __func__);
571  mface = (MFace *)MEM_malloc_arrayN((size_t)looptri_num, sizeof(*mface), __func__);
572  lindices = (uint(*)[4])MEM_malloc_arrayN((size_t)looptri_num, sizeof(*lindices), __func__);
573 
574  mface_index = 0;
575  mp = mpoly;
576  for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) {
577  const uint mp_loopstart = (uint)mp->loopstart;
578  const uint mp_totloop = (uint)mp->totloop;
579  uint l1, l2, l3, l4;
580  uint *lidx;
581  if (mp_totloop < 3) {
582  /* Do nothing. */
583  }
584 
585 #ifdef USE_TESSFACE_SPEEDUP
586 
587 # define ML_TO_MF(i1, i2, i3) \
588  mface_to_poly_map[mface_index] = poly_index; \
589  mf = &mface[mface_index]; \
590  lidx = lindices[mface_index]; \
591  /* Set loop indices, transformed to vert indices later. */ \
592  l1 = mp_loopstart + i1; \
593  l2 = mp_loopstart + i2; \
594  l3 = mp_loopstart + i3; \
595  mf->v1 = mloop[l1].v; \
596  mf->v2 = mloop[l2].v; \
597  mf->v3 = mloop[l3].v; \
598  mf->v4 = 0; \
599  lidx[0] = l1; \
600  lidx[1] = l2; \
601  lidx[2] = l3; \
602  lidx[3] = 0; \
603  mf->mat_nr = mp->mat_nr; \
604  mf->flag = mp->flag; \
605  mf->edcode = 0; \
606  (void)0
607 
608 /* ALMOST IDENTICAL TO DEFINE ABOVE (see EXCEPTION) */
609 # define ML_TO_MF_QUAD() \
610  mface_to_poly_map[mface_index] = poly_index; \
611  mf = &mface[mface_index]; \
612  lidx = lindices[mface_index]; \
613  /* Set loop indices, transformed to vert indices later. */ \
614  l1 = mp_loopstart + 0; /* EXCEPTION */ \
615  l2 = mp_loopstart + 1; /* EXCEPTION */ \
616  l3 = mp_loopstart + 2; /* EXCEPTION */ \
617  l4 = mp_loopstart + 3; /* EXCEPTION */ \
618  mf->v1 = mloop[l1].v; \
619  mf->v2 = mloop[l2].v; \
620  mf->v3 = mloop[l3].v; \
621  mf->v4 = mloop[l4].v; \
622  lidx[0] = l1; \
623  lidx[1] = l2; \
624  lidx[2] = l3; \
625  lidx[3] = l4; \
626  mf->mat_nr = mp->mat_nr; \
627  mf->flag = mp->flag; \
628  mf->edcode = TESSFACE_IS_QUAD; \
629  (void)0
630 
631  else if (mp_totloop == 3) {
632  ML_TO_MF(0, 1, 2);
633  mface_index++;
634  }
635  else if (mp_totloop == 4) {
636 # ifdef USE_TESSFACE_QUADS
637  ML_TO_MF_QUAD();
638  mface_index++;
639 # else
640  ML_TO_MF(0, 1, 2);
641  mface_index++;
642  ML_TO_MF(0, 2, 3);
643  mface_index++;
644 # endif
645  }
646 #endif /* USE_TESSFACE_SPEEDUP */
647  else {
648  const float *co_curr, *co_prev;
649 
650  float normal[3];
651 
652  float axis_mat[3][3];
653  float(*projverts)[2];
654  uint(*tris)[3];
655 
656  const uint totfilltri = mp_totloop - 2;
657 
658  if (UNLIKELY(arena == nullptr)) {
659  arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
660  }
661 
662  tris = (uint(*)[3])BLI_memarena_alloc(arena, sizeof(*tris) * (size_t)totfilltri);
663  projverts = (float(*)[2])BLI_memarena_alloc(arena, sizeof(*projverts) * (size_t)mp_totloop);
664 
665  zero_v3(normal);
666 
667  /* Calculate the normal, flipped: to get a positive 2D cross product. */
668  ml = mloop + mp_loopstart;
669  co_prev = mvert[ml[mp_totloop - 1].v].co;
670  for (j = 0; j < mp_totloop; j++, ml++) {
671  co_curr = mvert[ml->v].co;
672  add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
673  co_prev = co_curr;
674  }
675  if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
676  normal[2] = 1.0f;
677  }
678 
679  /* Project verts to 2D. */
681 
682  ml = mloop + mp_loopstart;
683  for (j = 0; j < mp_totloop; j++, ml++) {
684  mul_v2_m3v3(projverts[j], axis_mat, mvert[ml->v].co);
685  }
686 
687  BLI_polyfill_calc_arena(projverts, mp_totloop, 1, tris, arena);
688 
689  /* Apply fill. */
690  for (j = 0; j < totfilltri; j++) {
691  uint *tri = tris[j];
692  lidx = lindices[mface_index];
693 
694  mface_to_poly_map[mface_index] = poly_index;
695  mf = &mface[mface_index];
696 
697  /* Set loop indices, transformed to vert indices later. */
698  l1 = mp_loopstart + tri[0];
699  l2 = mp_loopstart + tri[1];
700  l3 = mp_loopstart + tri[2];
701 
702  mf->v1 = mloop[l1].v;
703  mf->v2 = mloop[l2].v;
704  mf->v3 = mloop[l3].v;
705  mf->v4 = 0;
706 
707  lidx[0] = l1;
708  lidx[1] = l2;
709  lidx[2] = l3;
710  lidx[3] = 0;
711 
712  mf->mat_nr = mp->mat_nr;
713  mf->flag = mp->flag;
714  mf->edcode = 0;
715 
716  mface_index++;
717  }
718 
719  BLI_memarena_clear(arena);
720  }
721  }
722 
723  if (arena) {
724  BLI_memarena_free(arena);
725  arena = nullptr;
726  }
727 
728  CustomData_free(fdata, totface);
729  totface = mface_index;
730 
731  BLI_assert(totface <= looptri_num);
732 
733  /* Not essential but without this we store over-allocated memory in the #CustomData layers. */
734  if (LIKELY(looptri_num != totface)) {
735  mface = (MFace *)MEM_reallocN(mface, sizeof(*mface) * (size_t)totface);
736  mface_to_poly_map = (int *)MEM_reallocN(mface_to_poly_map,
737  sizeof(*mface_to_poly_map) * (size_t)totface);
738  }
739 
740  CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface);
741 
742  /* #CD_ORIGINDEX will contain an array of indices from tessellation-faces to the polygons
743  * they are directly tessellated from. */
744  CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface);
745  BKE_mesh_add_mface_layers(fdata, ldata, totface);
746 
747  /* NOTE: quad detection issue - fourth vertidx vs fourth loopidx:
748  * Polygons take care of their loops ordering, hence not of their vertices ordering.
749  * Currently, our tfaces' fourth vertex index might be 0 even for a quad.
750  * However, we know our fourth loop index is never 0 for quads
751  * (because they are sorted for polygons, and our quads are still mere copies of their polygons).
752  * So we pass nullptr as MFace pointer, and #mesh_loops_to_tessdata
753  * will use the fourth loop index as quad test. */
754  mesh_loops_to_tessdata(fdata, ldata, nullptr, mface_to_poly_map, lindices, totface);
755 
756  /* NOTE: quad detection issue - fourth vertidx vs fourth loopidx:
757  * ...However, most TFace code uses 'MFace->v4 == 0' test to check whether it is a tri or quad.
758  * BKE_mesh_mface_index_validate() will check this and rotate the tessellated face if needed.
759  */
760 #ifdef USE_TESSFACE_QUADS
761  mf = mface;
762  for (mface_index = 0; mface_index < totface; mface_index++, mf++) {
763  if (mf->edcode == TESSFACE_IS_QUAD) {
764  BKE_mesh_mface_index_validate(mf, fdata, mface_index, 4);
765  mf->edcode = 0;
766  }
767  }
768 #endif
769 
770  MEM_freeN(lindices);
771 
772  return totface;
773 
774 #undef USE_TESSFACE_SPEEDUP
775 #undef USE_TESSFACE_QUADS
776 
777 #undef ML_TO_MF
778 #undef ML_TO_MF_QUAD
779 }
780 
782 {
784  &mesh->ldata,
785  &mesh->pdata,
786  mesh->mvert,
787  mesh->totface,
788  mesh->totloop,
789  mesh->totpoly);
790 
792 }
793 
795 {
796  if (mesh->totpoly && mesh->totface == 0) {
798  }
799 }
800 
801 #ifndef NDEBUG
808 static bool check_matching_legacy_layer_counts(CustomData *fdata, CustomData *ldata, bool fallback)
809 {
810  int a_num = 0, b_num = 0;
811 # define LAYER_CMP(l_a, t_a, l_b, t_b) \
812  ((a_num += CustomData_number_of_layers(l_a, t_a)) == \
813  (b_num += CustomData_number_of_layers(l_b, t_b)))
814 
815  if (!LAYER_CMP(ldata, CD_MLOOPUV, fdata, CD_MTFACE)) {
816  return false;
817  }
818  if (!LAYER_CMP(ldata, CD_PROP_BYTE_COLOR, fdata, CD_MCOL)) {
819  return false;
820  }
821  if (!LAYER_CMP(ldata, CD_PREVIEW_MLOOPCOL, fdata, CD_PREVIEW_MCOL)) {
822  return false;
823  }
824  if (!LAYER_CMP(ldata, CD_ORIGSPACE_MLOOP, fdata, CD_ORIGSPACE)) {
825  return false;
826  }
827  if (!LAYER_CMP(ldata, CD_NORMAL, fdata, CD_TESSLOOPNORMAL)) {
828  return false;
829  }
830  if (!LAYER_CMP(ldata, CD_TANGENT, fdata, CD_TANGENT)) {
831  return false;
832  }
833 
834 # undef LAYER_CMP
835 
836  /* if no layers are on either CustomData's,
837  * then there was nothing to do... */
838  return a_num ? true : fallback;
839 }
840 #endif
841 
842 void BKE_mesh_add_mface_layers(CustomData *fdata, CustomData *ldata, int total)
843 {
844  /* avoid accumulating extra layers */
845  BLI_assert(!check_matching_legacy_layer_counts(fdata, ldata, false));
846 
847  for (int i = 0; i < ldata->totlayer; i++) {
848  if (ldata->layers[i].type == CD_MLOOPUV) {
850  fdata, CD_MTFACE, CD_CALLOC, nullptr, total, ldata->layers[i].name);
851  }
852  if (ldata->layers[i].type == CD_PROP_BYTE_COLOR) {
853  CustomData_add_layer_named(fdata, CD_MCOL, CD_CALLOC, nullptr, total, ldata->layers[i].name);
854  }
855  else if (ldata->layers[i].type == CD_PREVIEW_MLOOPCOL) {
857  fdata, CD_PREVIEW_MCOL, CD_CALLOC, nullptr, total, ldata->layers[i].name);
858  }
859  else if (ldata->layers[i].type == CD_ORIGSPACE_MLOOP) {
861  fdata, CD_ORIGSPACE, CD_CALLOC, nullptr, total, ldata->layers[i].name);
862  }
863  else if (ldata->layers[i].type == CD_NORMAL) {
865  fdata, CD_TESSLOOPNORMAL, CD_CALLOC, nullptr, total, ldata->layers[i].name);
866  }
867  else if (ldata->layers[i].type == CD_TANGENT) {
869  fdata, CD_TANGENT, CD_CALLOC, nullptr, total, ldata->layers[i].name);
870  }
871  }
872 
874 }
875 
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
void CustomData_free(struct CustomData *data, int totelem)
Definition: customdata.cc:2373
int CustomData_number_of_layers(const struct CustomData *data, int type)
int CustomData_get_clone_layer(const struct CustomData *data, int type)
void CustomData_set_layer_active(struct CustomData *data, int type, int n)
Definition: customdata.cc:2542
@ CD_ASSIGN
@ CD_CALLOC
void CustomData_external_add(struct CustomData *data, struct ID *id, int type, int totelem, const char *filepath)
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem, const char *name)
Definition: customdata.cc:2792
void CustomData_set_layer_clone(struct CustomData *data, int type, int n)
Definition: customdata.cc:2560
int CustomData_get_active_layer(const struct CustomData *data, int type)
void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct CustomData *ldata)
Definition: customdata.cc:3508
int CustomData_get_stencil_layer(const struct CustomData *data, int type)
void CustomData_set_layer_render(struct CustomData *data, int type, int n)
Definition: customdata.cc:2551
void * CustomData_get_n(const struct CustomData *data, int type, int index, int n)
void * CustomData_get_layer_n(const struct CustomData *data, int type, int n)
void * CustomData_get_layer(const struct CustomData *data, int type)
bool CustomData_external_test(struct CustomData *data, int type)
Definition: customdata.cc:4772
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.cc:2776
void CustomData_external_read(struct CustomData *data, struct ID *id, eCustomDataMask mask, int totelem)
Definition: customdata.cc:4547
void * CustomData_get(const struct CustomData *data, int index, int type)
void CustomData_swap_corners(struct CustomData *data, int index, const int *corner_indices)
Definition: customdata.cc:3306
void CustomData_set_layer_stencil(struct CustomData *data, int type, int n)
Definition: customdata.cc:2569
int CustomData_get_render_layer(const struct CustomData *data, int type)
void BKE_mesh_update_customdata_pointers(struct Mesh *me, bool do_ensure_tess_cd)
Definition: mesh.cc:874
int multires_mdisp_corners(const struct MDisps *s)
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP free_value)
Definition: edgehash.c:230
void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val)
Definition: edgehash.c:261
EdgeHash * BLI_edgehash_new_ex(const char *info, unsigned int nentries_reserve)
Definition: edgehash.c:212
#define M_LN2
Definition: BLI_math_base.h:53
void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
Definition: math_geom.c:3544
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
Definition: math_matrix.c:917
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void normal_float_to_short_v3(short r[3], const float n[3])
MINLINE float normalize_v3(float r[3])
MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3])
MINLINE void normal_short_to_float_v3(float r[3], const short n[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void zero_v3(float r[3])
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
void BLI_polyfill_calc_arena(const float(*coords)[2], unsigned int coords_num, int coords_sign, unsigned int(*r_tris)[3], struct MemArena *arena)
Definition: polyfill_2d.c:830
unsigned int uint
Definition: BLI_sys_types.h:67
#define SWAP(type, a, b)
#define UNLIKELY(x)
#define POINTER_FROM_UINT(i)
#define LIKELY(x)
@ CD_PROP_BYTE_COLOR
@ CD_TESSLOOPNORMAL
@ CD_MTFACE
@ CD_PREVIEW_MCOL
@ CD_MFACE
@ CD_ORIGINDEX
@ CD_ORIGSPACE_MLOOP
@ CD_ORIGSPACE
@ CD_PREVIEW_MLOOPCOL
@ CD_MLOOPUV
@ CD_TANGENT
#define CD_MASK_MDISPS
struct MLoop MLoop
struct MCol MCol
#define MESH_MLOOPCOL_FROM_MCOL(_mloopcol, _mcol)
#define MESH_MLOOPCOL_TO_MCOL(_mloopcol, _mcol)
struct MPoly MPoly
_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.
#define MEM_reallocN(vmemh, len)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
#define logf(x)
Definition: cuda/compat.h:105
IconTextureDrawCall normal
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
static void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, CustomData *ldata)
#define ML(v1, v2)
static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata, MFace *mface, int totloop, int findex, int loopstart, int numTex, int numCol)
void BKE_mesh_convert_mfaces_to_mpolys(Mesh *mesh)
void BKE_mesh_add_mface_layers(CustomData *fdata, CustomData *ldata, int total)
void BKE_mesh_tessface_calc(Mesh *mesh)
void BKE_mesh_tessface_ensure(struct Mesh *mesh)
int BKE_mesh_mface_index_validate(MFace *mface, CustomData *fdata, int mfindex, int nr)
#define LAYER_CMP(l_a, t_a, l_b, t_b)
#define TESSFACE_IS_QUAD
#define ML_TO_MF_QUAD()
static void mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, MFace *mface, const int *polyindices, uint(*loopindices)[4], const int num_faces)
static int mesh_tessface_calc(CustomData *fdata, CustomData *ldata, CustomData *pdata, MVert *mvert, int totface, int totloop, int totpoly)
static bool check_matching_legacy_layer_counts(CustomData *fdata, CustomData *ldata, bool fallback)
#define ME_FGON
#define ML_TO_MF(i1, i2, i3)
static void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int totloop)
static void convert_mfaces_to_mpolys(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata, int totedge_i, int totface_i, int totloop_i, int totpoly_i, MEdge *medge, MFace *mface, int *r_totloop, int *r_totpoly, MLoop **r_mloop, MPoly **r_mpoly)
void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh)
#define sqrtf(x)
Definition: metal/compat.h:243
CustomDataLayer * layers
CustomDataExternal * external
Definition: DNA_ID.h:368
float(* disps)[3]
unsigned int v1
unsigned int v2
unsigned int v2
unsigned int v1
unsigned int v4
unsigned int v3
unsigned int v
short mat_nr
float uv[4][2]
float co[3]
struct MEdge * medge
struct MVert * mvert
int totedge
struct MLoop * mloop
int totface
CustomData pdata
CustomData fdata
int totpoly
int totloop
struct MFace * mface
struct MPoly * mpoly
CustomData ldata
float max