Blender  V3.3
mesh_convert.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "CLG_log.h"
8 
9 #include "MEM_guardedalloc.h"
10 
11 #include "DNA_curve_types.h"
12 #include "DNA_key_types.h"
13 #include "DNA_material_types.h"
14 #include "DNA_mesh_types.h"
15 #include "DNA_meshdata_types.h"
16 #include "DNA_meta_types.h"
17 #include "DNA_object_types.h"
18 #include "DNA_pointcloud_types.h"
19 #include "DNA_scene_types.h"
20 
21 #include "BLI_edgehash.h"
22 #include "BLI_index_range.hh"
23 #include "BLI_listbase.h"
24 #include "BLI_math.h"
25 #include "BLI_string.h"
26 #include "BLI_utildefines.h"
27 
28 #include "BKE_DerivedMesh.h"
29 #include "BKE_curves.hh"
30 #include "BKE_deform.h"
31 #include "BKE_displist.h"
32 #include "BKE_editmesh.h"
33 #include "BKE_geometry_set.hh"
34 #include "BKE_key.h"
35 #include "BKE_lib_id.h"
36 #include "BKE_lib_query.h"
37 #include "BKE_main.h"
38 #include "BKE_material.h"
39 #include "BKE_mball.h"
40 #include "BKE_mesh.h"
41 #include "BKE_mesh_runtime.h"
42 #include "BKE_mesh_wrapper.h"
43 #include "BKE_modifier.h"
44 /* these 2 are only used by conversion functions */
45 #include "BKE_curve.h"
46 /* -- */
47 #include "BKE_object.h"
48 /* -- */
49 #include "BKE_pointcloud.h"
50 
51 #include "BKE_curve_to_mesh.hh"
52 
53 #include "DEG_depsgraph.h"
54 #include "DEG_depsgraph_query.h"
55 
57 
58 /* Define for cases when you want extra validation of mesh
59  * after certain modifications.
60  */
61 // #undef VALIDATE_MESH
62 
63 #ifdef VALIDATE_MESH
64 # define ASSERT_IS_VALID_MESH(mesh) \
65  (BLI_assert((mesh == nullptr) || (BKE_mesh_is_valid(mesh) == true)))
66 #else
67 # define ASSERT_IS_VALID_MESH(mesh)
68 #endif
69 
70 static CLG_LogRef LOG = {"bke.mesh_convert"};
71 
73 {
74  DispList *dl;
75  MVert *mvert;
76  MLoop *mloop, *allloop;
77  MPoly *mpoly;
78  int a, *index;
79 
80  dl = (DispList *)lb->first;
81  if (dl == nullptr) {
82  return;
83  }
84 
85  if (dl->type == DL_INDEX4) {
86  mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, nullptr, dl->nr);
87  allloop = mloop = (MLoop *)CustomData_add_layer(
88  &me->ldata, CD_MLOOP, CD_CALLOC, nullptr, dl->parts * 4);
89  mpoly = (MPoly *)CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, nullptr, dl->parts);
90  me->mvert = mvert;
91  me->mloop = mloop;
92  me->mpoly = mpoly;
93  me->totvert = dl->nr;
94  me->totpoly = dl->parts;
95 
96  for (const int i : IndexRange(dl->nr)) {
97  copy_v3_v3(me->mvert[i].co, &dl->verts[3 * i]);
98  }
99 
100  a = dl->parts;
101  index = dl->index;
102  while (a--) {
103  int count = index[2] != index[3] ? 4 : 3;
104 
105  mloop[0].v = index[0];
106  mloop[1].v = index[1];
107  mloop[2].v = index[2];
108  if (count == 4) {
109  mloop[3].v = index[3];
110  }
111 
112  mpoly->totloop = count;
113  mpoly->loopstart = (int)(mloop - allloop);
114  mpoly->flag = ME_SMOOTH;
115 
116  mpoly++;
117  mloop += count;
118  me->totloop += count;
119  index += 4;
120  }
121 
123  BKE_mesh_calc_edges(me, true, false);
124  }
125 }
126 
131  MEdge **r_alledge, int *r_totedge, const MPoly *mpoly, MLoop *mloop, const int totpoly)
132 {
133  int totedge = *r_totedge;
134  int totedge_new;
135  EdgeHash *eh;
136  uint eh_reserve;
137  const MPoly *mp;
138  int i;
139 
140  eh_reserve = max_ii(totedge, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly));
141  eh = BLI_edgehash_new_ex(__func__, eh_reserve);
142 
143  for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
144  BKE_mesh_poly_edgehash_insert(eh, mp, mloop + mp->loopstart);
145  }
146 
147  totedge_new = BLI_edgehash_len(eh);
148 
149 #ifdef DEBUG
150  /* ensure that there's no overlap! */
151  if (totedge_new) {
152  MEdge *medge = *r_alledge;
153  for (i = 0; i < totedge; i++, medge++) {
154  BLI_assert(BLI_edgehash_haskey(eh, medge->v1, medge->v2) == false);
155  }
156  }
157 #endif
158 
159  if (totedge_new) {
160  EdgeHashIterator *ehi;
161  MEdge *medge;
162  uint e_index = totedge;
163 
164  *r_alledge = medge = (MEdge *)(*r_alledge ?
165  MEM_reallocN(*r_alledge,
166  sizeof(MEdge) * (totedge + totedge_new)) :
167  MEM_calloc_arrayN(totedge_new, sizeof(MEdge), __func__));
168  medge += totedge;
169 
170  totedge += totedge_new;
171 
172  /* --- */
173  for (ehi = BLI_edgehashIterator_new(eh); BLI_edgehashIterator_isDone(ehi) == false;
174  BLI_edgehashIterator_step(ehi), ++medge, e_index++) {
175  BLI_edgehashIterator_getKey(ehi, &medge->v1, &medge->v2);
177 
178  medge->crease = medge->bweight = 0;
179  medge->flag = ME_EDGEDRAW | ME_EDGERENDER;
180  }
182 
183  *r_totedge = totedge;
184 
185  for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
186  MLoop *l = &mloop[mp->loopstart];
187  MLoop *l_prev = (l + (mp->totloop - 1));
188  int j;
189  for (j = 0; j < mp->totloop; j++, l++) {
190  /* lookup hashed edge index */
191  l_prev->e = POINTER_AS_UINT(BLI_edgehash_lookup(eh, l_prev->v, l->v));
192  l_prev = l;
193  }
194  }
195  }
196 
197  BLI_edgehash_free(eh, nullptr);
198 }
199 
200 /* Initialize mverts, medges and, faces for converting nurbs to mesh and derived mesh */
201 /* use specified dispbase */
202 static int mesh_nurbs_displist_to_mdata(const Curve *cu,
203  const ListBase *dispbase,
204  MVert **r_allvert,
205  int *r_totvert,
206  MEdge **r_alledge,
207  int *r_totedge,
208  MLoop **r_allloop,
209  MPoly **r_allpoly,
210  MLoopUV **r_alluv,
211  int *r_totloop,
212  int *r_totpoly)
213 {
214  MVert *mvert;
215  MPoly *mpoly;
216  MLoop *mloop;
217  MLoopUV *mloopuv = nullptr;
218  MEdge *medge;
219  const float *data;
220  int a, b, ofs, vertcount, startvert, totvert = 0, totedge = 0, totloop = 0, totpoly = 0;
221  int p1, p2, p3, p4, *index;
222  const bool conv_polys = (
223  /* 2D polys are filled with #DispList.type == #DL_INDEX3. */
224  (CU_DO_2DFILL(cu) == false) ||
225  /* surf polys are never filled */
226  BKE_curve_type_get(cu) == OB_SURF);
227 
228  /* count */
229  LISTBASE_FOREACH (const DispList *, dl, dispbase) {
230  if (dl->type == DL_SEGM) {
231  totvert += dl->parts * dl->nr;
232  totedge += dl->parts * (dl->nr - 1);
233  }
234  else if (dl->type == DL_POLY) {
235  if (conv_polys) {
236  totvert += dl->parts * dl->nr;
237  totedge += dl->parts * dl->nr;
238  }
239  }
240  else if (dl->type == DL_SURF) {
241  if (dl->parts != 0) {
242  int tot;
243  totvert += dl->parts * dl->nr;
244  tot = (((dl->flag & DL_CYCL_U) ? 1 : 0) + (dl->nr - 1)) *
245  (((dl->flag & DL_CYCL_V) ? 1 : 0) + (dl->parts - 1));
246  totpoly += tot;
247  totloop += tot * 4;
248  }
249  }
250  else if (dl->type == DL_INDEX3) {
251  int tot;
252  totvert += dl->nr;
253  tot = dl->parts;
254  totpoly += tot;
255  totloop += tot * 3;
256  }
257  }
258 
259  if (totvert == 0) {
260  /* Make Sure you check ob->data is a curve. */
261  // error("can't convert");
262  return -1;
263  }
264 
265  *r_allvert = mvert = (MVert *)MEM_calloc_arrayN(totvert, sizeof(MVert), "nurbs_init mvert");
266  *r_alledge = medge = (MEdge *)MEM_calloc_arrayN(totedge, sizeof(MEdge), "nurbs_init medge");
267  *r_allloop = mloop = (MLoop *)MEM_calloc_arrayN(
268  totpoly, sizeof(MLoop[4]), "nurbs_init mloop"); /* totloop */
269  *r_allpoly = mpoly = (MPoly *)MEM_calloc_arrayN(totpoly, sizeof(MPoly), "nurbs_init mloop");
270 
271  if (r_alluv) {
272  *r_alluv = mloopuv = (MLoopUV *)MEM_calloc_arrayN(
273  totpoly, sizeof(MLoopUV[4]), "nurbs_init mloopuv");
274  }
275 
276  /* verts and faces */
277  vertcount = 0;
278 
279  LISTBASE_FOREACH (const DispList *, dl, dispbase) {
280  const bool is_smooth = (dl->rt & CU_SMOOTH) != 0;
281 
282  if (dl->type == DL_SEGM) {
283  startvert = vertcount;
284  a = dl->parts * dl->nr;
285  data = dl->verts;
286  while (a--) {
287  copy_v3_v3(mvert->co, data);
288  data += 3;
289  vertcount++;
290  mvert++;
291  }
292 
293  for (a = 0; a < dl->parts; a++) {
294  ofs = a * dl->nr;
295  for (b = 1; b < dl->nr; b++) {
296  medge->v1 = startvert + ofs + b - 1;
297  medge->v2 = startvert + ofs + b;
299 
300  medge++;
301  }
302  }
303  }
304  else if (dl->type == DL_POLY) {
305  if (conv_polys) {
306  startvert = vertcount;
307  a = dl->parts * dl->nr;
308  data = dl->verts;
309  while (a--) {
310  copy_v3_v3(mvert->co, data);
311  data += 3;
312  vertcount++;
313  mvert++;
314  }
315 
316  for (a = 0; a < dl->parts; a++) {
317  ofs = a * dl->nr;
318  for (b = 0; b < dl->nr; b++) {
319  medge->v1 = startvert + ofs + b;
320  if (b == dl->nr - 1) {
321  medge->v2 = startvert + ofs;
322  }
323  else {
324  medge->v2 = startvert + ofs + b + 1;
325  }
327  medge++;
328  }
329  }
330  }
331  }
332  else if (dl->type == DL_INDEX3) {
333  startvert = vertcount;
334  a = dl->nr;
335  data = dl->verts;
336  while (a--) {
337  copy_v3_v3(mvert->co, data);
338  data += 3;
339  vertcount++;
340  mvert++;
341  }
342 
343  a = dl->parts;
344  index = dl->index;
345  while (a--) {
346  mloop[0].v = startvert + index[0];
347  mloop[1].v = startvert + index[2];
348  mloop[2].v = startvert + index[1];
349  mpoly->loopstart = (int)(mloop - (*r_allloop));
350  mpoly->totloop = 3;
351  mpoly->mat_nr = dl->col;
352 
353  if (mloopuv) {
354  for (int i = 0; i < 3; i++, mloopuv++) {
355  mloopuv->uv[0] = (mloop[i].v - startvert) / (float)(dl->nr - 1);
356  mloopuv->uv[1] = 0.0f;
357  }
358  }
359 
360  if (is_smooth) {
361  mpoly->flag |= ME_SMOOTH;
362  }
363  mpoly++;
364  mloop += 3;
365  index += 3;
366  }
367  }
368  else if (dl->type == DL_SURF) {
369  startvert = vertcount;
370  a = dl->parts * dl->nr;
371  data = dl->verts;
372  while (a--) {
373  copy_v3_v3(mvert->co, data);
374  data += 3;
375  vertcount++;
376  mvert++;
377  }
378 
379  for (a = 0; a < dl->parts; a++) {
380 
381  if ((dl->flag & DL_CYCL_V) == 0 && a == dl->parts - 1) {
382  break;
383  }
384 
385  if (dl->flag & DL_CYCL_U) { /* p2 -> p1 -> */
386  p1 = startvert + dl->nr * a; /* p4 -> p3 -> */
387  p2 = p1 + dl->nr - 1; /* -----> next row */
388  p3 = p1 + dl->nr;
389  p4 = p2 + dl->nr;
390  b = 0;
391  }
392  else {
393  p2 = startvert + dl->nr * a;
394  p1 = p2 + 1;
395  p4 = p2 + dl->nr;
396  p3 = p1 + dl->nr;
397  b = 1;
398  }
399  if ((dl->flag & DL_CYCL_V) && a == dl->parts - 1) {
400  p3 -= dl->parts * dl->nr;
401  p4 -= dl->parts * dl->nr;
402  }
403 
404  for (; b < dl->nr; b++) {
405  mloop[0].v = p1;
406  mloop[1].v = p3;
407  mloop[2].v = p4;
408  mloop[3].v = p2;
409  mpoly->loopstart = (int)(mloop - (*r_allloop));
410  mpoly->totloop = 4;
411  mpoly->mat_nr = dl->col;
412 
413  if (mloopuv) {
414  int orco_sizeu = dl->nr - 1;
415  int orco_sizev = dl->parts - 1;
416 
417  /* exception as handled in convertblender.c too */
418  if (dl->flag & DL_CYCL_U) {
419  orco_sizeu++;
420  if (dl->flag & DL_CYCL_V) {
421  orco_sizev++;
422  }
423  }
424  else if (dl->flag & DL_CYCL_V) {
425  orco_sizev++;
426  }
427 
428  for (int i = 0; i < 4; i++, mloopuv++) {
429  /* find uv based on vertex index into grid array */
430  int v = mloop[i].v - startvert;
431 
432  mloopuv->uv[0] = (v / dl->nr) / (float)orco_sizev;
433  mloopuv->uv[1] = (v % dl->nr) / (float)orco_sizeu;
434 
435  /* cyclic correction */
436  if ((ELEM(i, 1, 2)) && mloopuv->uv[0] == 0.0f) {
437  mloopuv->uv[0] = 1.0f;
438  }
439  if ((ELEM(i, 0, 1)) && mloopuv->uv[1] == 0.0f) {
440  mloopuv->uv[1] = 1.0f;
441  }
442  }
443  }
444 
445  if (is_smooth) {
446  mpoly->flag |= ME_SMOOTH;
447  }
448  mpoly++;
449  mloop += 4;
450 
451  p4 = p3;
452  p3++;
453  p2 = p1;
454  p1++;
455  }
456  }
457  }
458  }
459 
460  if (totpoly) {
461  make_edges_mdata_extend(r_alledge, &totedge, *r_allpoly, *r_allloop, totpoly);
462  }
463 
464  *r_totpoly = totpoly;
465  *r_totloop = totloop;
466  *r_totedge = totedge;
467  *r_totvert = totvert;
468 
469  return 0;
470 }
471 
480 {
481  me->texflag = cu->texflag & ~CU_AUTOSPACE;
482  copy_v3_v3(me->loc, cu->loc);
483  copy_v3_v3(me->size, cu->size);
485 }
486 
488 {
489  const Curve *cu = (const Curve *)ob->data;
490  Mesh *mesh;
491  MVert *allvert;
492  MEdge *alledge;
493  MLoop *allloop;
494  MPoly *allpoly;
495  MLoopUV *alluv = nullptr;
496  int totvert, totedge, totloop, totpoly;
497 
499  dispbase,
500  &allvert,
501  &totvert,
502  &alledge,
503  &totedge,
504  &allloop,
505  &allpoly,
506  &alluv,
507  &totloop,
508  &totpoly) != 0) {
509  /* Error initializing mdata. This often happens when curve is empty */
510  return BKE_mesh_new_nomain(0, 0, 0, 0, 0);
511  }
512 
513  mesh = BKE_mesh_new_nomain(totvert, totedge, 0, totloop, totpoly);
514 
515  if (totvert != 0) {
516  memcpy(mesh->mvert, allvert, totvert * sizeof(MVert));
517  }
518  if (totedge != 0) {
519  memcpy(mesh->medge, alledge, totedge * sizeof(MEdge));
520  }
521  if (totloop != 0) {
522  memcpy(mesh->mloop, allloop, totloop * sizeof(MLoop));
523  }
524  if (totpoly != 0) {
525  memcpy(mesh->mpoly, allpoly, totpoly * sizeof(MPoly));
526  }
527 
528  if (alluv) {
529  const char *uvname = "UVMap";
530  CustomData_add_layer_named(&mesh->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, totloop, uvname);
531  }
532 
534 
535  /* Copy curve materials. */
536  mesh->mat = (Material **)MEM_dupallocN(cu->mat);
537  mesh->totcol = cu->totcol;
538 
539  MEM_freeN(allvert);
540  MEM_freeN(alledge);
541  MEM_freeN(allloop);
542  MEM_freeN(allpoly);
543 
544  return mesh;
545 }
546 
548 {
549  ListBase disp = {nullptr, nullptr};
550 
551  if (ob->runtime.curve_cache) {
552  disp = ob->runtime.curve_cache->disp;
553  }
554 
555  return BKE_mesh_new_nomain_from_curve_displist(ob, &disp);
556 }
557 
558 struct EdgeLink {
559  struct EdgeLink *next, *prev;
560  void *edge;
561 };
562 
563 struct VertLink {
566 };
567 
568 static void prependPolyLineVert(ListBase *lb, uint index)
569 {
570  VertLink *vl = MEM_cnew<VertLink>("VertLink");
571  vl->index = index;
572  BLI_addhead(lb, vl);
573 }
574 
575 static void appendPolyLineVert(ListBase *lb, uint index)
576 {
577  VertLink *vl = MEM_cnew<VertLink>("VertLink");
578  vl->index = index;
579  BLI_addtail(lb, vl);
580 }
581 
582 void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int edge_users_test)
583 {
584  MVert *mvert = me->mvert;
585  MEdge *med, *medge = me->medge;
586  MPoly *mp, *mpoly = me->mpoly;
587  MLoop *mloop = me->mloop;
588 
589  int medge_len = me->totedge;
590  int mpoly_len = me->totpoly;
591  int totedges = 0;
592  int i;
593 
594  /* only to detect edge polylines */
595  int *edge_users;
596 
597  ListBase edges = {nullptr, nullptr};
598 
599  /* get boundary edges */
600  edge_users = (int *)MEM_calloc_arrayN(medge_len, sizeof(int), __func__);
601  for (i = 0, mp = mpoly; i < mpoly_len; i++, mp++) {
602  MLoop *ml = &mloop[mp->loopstart];
603  int j;
604  for (j = 0; j < mp->totloop; j++, ml++) {
605  edge_users[ml->e]++;
606  }
607  }
608 
609  /* create edges from all faces (so as to find edges not in any faces) */
610  med = medge;
611  for (i = 0; i < medge_len; i++, med++) {
612  if (edge_users[i] == edge_users_test) {
613  EdgeLink *edl = MEM_cnew<EdgeLink>("EdgeLink");
614  edl->edge = med;
615 
616  BLI_addtail(&edges, edl);
617  totedges++;
618  }
619  }
620  MEM_freeN(edge_users);
621 
622  if (edges.first) {
623  while (edges.first) {
624  /* each iteration find a polyline and add this as a nurbs poly spline */
625 
626  ListBase polyline = {nullptr, nullptr}; /* store a list of VertLink's */
627  bool closed = false;
628  int totpoly = 0;
629  MEdge *med_current = (MEdge *)((EdgeLink *)edges.last)->edge;
630  uint startVert = med_current->v1;
631  uint endVert = med_current->v2;
632  bool ok = true;
633 
634  appendPolyLineVert(&polyline, startVert);
635  totpoly++;
636  appendPolyLineVert(&polyline, endVert);
637  totpoly++;
638  BLI_freelinkN(&edges, edges.last);
639  totedges--;
640 
641  while (ok) { /* while connected edges are found... */
642  EdgeLink *edl = (EdgeLink *)edges.last;
643  ok = false;
644  while (edl) {
645  EdgeLink *edl_prev = edl->prev;
646 
647  med = (MEdge *)edl->edge;
648 
649  if (med->v1 == endVert) {
650  endVert = med->v2;
651  appendPolyLineVert(&polyline, med->v2);
652  totpoly++;
653  BLI_freelinkN(&edges, edl);
654  totedges--;
655  ok = true;
656  }
657  else if (med->v2 == endVert) {
658  endVert = med->v1;
659  appendPolyLineVert(&polyline, endVert);
660  totpoly++;
661  BLI_freelinkN(&edges, edl);
662  totedges--;
663  ok = true;
664  }
665  else if (med->v1 == startVert) {
666  startVert = med->v2;
667  prependPolyLineVert(&polyline, startVert);
668  totpoly++;
669  BLI_freelinkN(&edges, edl);
670  totedges--;
671  ok = true;
672  }
673  else if (med->v2 == startVert) {
674  startVert = med->v1;
675  prependPolyLineVert(&polyline, startVert);
676  totpoly++;
677  BLI_freelinkN(&edges, edl);
678  totedges--;
679  ok = true;
680  }
681 
682  edl = edl_prev;
683  }
684  }
685 
686  /* Now we have a polyline, make into a curve */
687  if (startVert == endVert) {
688  BLI_freelinkN(&polyline, polyline.last);
689  totpoly--;
690  closed = true;
691  }
692 
693  /* --- nurbs --- */
694  {
695  Nurb *nu;
696  BPoint *bp;
697  VertLink *vl;
698 
699  /* create new 'nurb' within the curve */
700  nu = MEM_new<Nurb>("MeshNurb", blender::dna::shallow_zero_initialize());
701 
702  nu->pntsu = totpoly;
703  nu->pntsv = 1;
704  nu->orderu = 4;
705  nu->flagu = CU_NURB_ENDPOINT | (closed ? CU_NURB_CYCLIC : 0); /* endpoint */
706  nu->resolu = 12;
707 
708  nu->bp = (BPoint *)MEM_calloc_arrayN(totpoly, sizeof(BPoint), "bpoints");
709 
710  /* add points */
711  vl = (VertLink *)polyline.first;
712  for (i = 0, bp = nu->bp; i < totpoly; i++, bp++, vl = (VertLink *)vl->next) {
713  copy_v3_v3(bp->vec, mvert[vl->index].co);
714  bp->f1 = SELECT;
715  bp->radius = bp->weight = 1.0;
716  }
717  BLI_freelistN(&polyline);
718 
719  /* add nurb to curve */
720  BLI_addtail(nurblist, nu);
721  }
722  /* --- done with nurbs --- */
723  }
724  }
725 }
726 
728 {
729  /* make new mesh data from the original copy */
730  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
731  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
732  Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
733  ListBase nurblist = {nullptr, nullptr};
734 
735  BKE_mesh_to_curve_nurblist(me_eval, &nurblist, 0);
736  BKE_mesh_to_curve_nurblist(me_eval, &nurblist, 1);
737 
738  if (nurblist.first) {
739  Curve *cu = BKE_curve_add(bmain, ob->id.name + 2, OB_CURVES_LEGACY);
740  cu->flag |= CU_3D;
741 
742  cu->nurb = nurblist;
743 
744  id_us_min(&((Mesh *)ob->data)->id);
745  ob->data = cu;
746  ob->type = OB_CURVES_LEGACY;
747 
749  }
750 }
751 
753 {
754  using namespace blender;
755 
756  BLI_assert(me != nullptr);
757 
758  pointcloud->totpoint = me->totvert;
759  CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint);
760 
761  /* Copy over all attributes. */
763 
766  *pointcloud);
767 
768  const VArray<float3> mesh_positions = mesh_attributes.lookup_or_default<float3>(
769  "position", ATTR_DOMAIN_POINT, float3(0));
770  bke::SpanAttributeWriter<float3> point_positions =
771  point_attributes.lookup_or_add_for_write_only_span<float3>("position", ATTR_DOMAIN_POINT);
772  mesh_positions.materialize(point_positions.span);
773  point_positions.finish();
774 }
775 
777 {
778  BLI_assert(ob->type == OB_MESH);
779 
780  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
781  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
782  Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
783 
784  PointCloud *pointcloud = (PointCloud *)BKE_pointcloud_add(bmain, ob->id.name + 2);
785 
786  BKE_pointcloud_from_mesh(me_eval, pointcloud);
787 
788  BKE_id_materials_copy(bmain, (ID *)ob->data, (ID *)pointcloud);
789 
790  id_us_min(&((Mesh *)ob->data)->id);
791  ob->data = pointcloud;
792  ob->type = OB_POINTCLOUD;
793 
795 }
796 
797 void BKE_mesh_from_pointcloud(const PointCloud *pointcloud, Mesh *me)
798 {
799  BLI_assert(pointcloud != nullptr);
800 
801  me->totvert = pointcloud->totpoint;
802 
803  /* Merge over all attributes. */
805  &pointcloud->pdata, &me->vdata, CD_MASK_PROP_ALL, CD_DUPLICATE, pointcloud->totpoint);
806 
807  /* Convert the Position attribute to a mesh vertex. */
808  me->mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, nullptr, me->totvert);
810 
811  const int layer_idx = CustomData_get_named_layer_index(
813  CustomDataLayer *pos_layer = &me->vdata.layers[layer_idx];
814  float(*positions)[3] = (float(*)[3])pos_layer->data;
815 
816  MVert *mvert;
817  mvert = me->mvert;
818  for (int i = 0; i < me->totvert; i++, mvert++) {
819  copy_v3_v3(mvert->co, positions[i]);
820  }
821 
822  /* Delete Position attribute since it is now in vertex coordinates. */
823  CustomData_free_layer(&me->vdata, CD_PROP_FLOAT3, me->totvert, layer_idx);
824 }
825 
827 {
828  MEdge *med = mesh->medge;
829  for (int i = 0; i < mesh->totedge; i++, med++) {
830  med->flag |= ME_EDGEDRAW | ME_EDGERENDER;
831  }
832 }
833 
835 {
836  BLI_assert(ob->type == OB_POINTCLOUD);
837 
838  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
839  PointCloud *pointcloud_eval = (PointCloud *)ob_eval->runtime.data_eval;
840 
841  Mesh *me = BKE_mesh_add(bmain, ob->id.name + 2);
842 
843  BKE_mesh_from_pointcloud(pointcloud_eval, me);
844 
845  BKE_id_materials_copy(bmain, (ID *)ob->data, (ID *)me);
846 
847  id_us_min(&((PointCloud *)ob->data)->id);
848  ob->data = me;
849  ob->type = OB_MESH;
850 
852 }
853 
854 /* Create a temporary object to be used for nurbs-to-mesh conversion. */
856 {
857  const Curve *curve = (const Curve *)object->data;
858 
859  /* Create a temporary object which can be evaluated and modified by generic
860  * curve evaluation (hence the #LIB_ID_COPY_SET_COPIED_ON_WRITE flag). */
861  Object *temp_object = (Object *)BKE_id_copy_ex(
862  nullptr, &object->id, nullptr, LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_SET_COPIED_ON_WRITE);
863 
864  /* Remove all modifiers, since we don't want them to be applied. */
866 
867  /* Need to create copy of curve itself as well, since it will be changed by the curve evaluation
868  * process. NOTE: Copies the data, but not the shape-keys. */
869  temp_object->data = BKE_id_copy_ex(nullptr,
870  (const ID *)object->data,
871  nullptr,
873  Curve *temp_curve = (Curve *)temp_object->data;
874 
875  /* Make sure texture space is calculated for a copy of curve, it will be used for the final
876  * result. */
877  BKE_curve_texspace_calc(temp_curve);
878 
879  /* Temporarily set edit so we get updates from edit mode, but also because for text data-blocks
880  * copying it while in edit mode gives invalid data structures. */
881  temp_curve->editfont = curve->editfont;
882  temp_curve->editnurb = curve->editnurb;
883 
884  return temp_object;
885 }
886 
887 static void object_for_curve_to_mesh_free(Object *temp_object)
888 {
889  /* Clear edit mode pointers that were explicitly copied to the temporary curve. */
890  ID *final_object_data = static_cast<ID *>(temp_object->data);
891  if (GS(final_object_data->name) == ID_CU_LEGACY) {
892  Curve &curve = *reinterpret_cast<Curve *>(final_object_data);
893  curve.editfont = nullptr;
894  curve.editnurb = nullptr;
895  }
896 
897  /* Only free the final object data if it is *not* stored in the #data_eval field. This is still
898  * necessary because #temp_object's data could be replaced by a #Curve data-block that isn't also
899  * assigned to #data_eval. */
900  const bool object_data_stored_in_data_eval = final_object_data == temp_object->runtime.data_eval;
901 
902  BKE_id_free(nullptr, temp_object);
903  if (!object_data_stored_in_data_eval) {
904  BKE_id_free(nullptr, final_object_data);
905  }
906 }
907 
911 static void curve_to_mesh_eval_ensure(Object &object)
912 {
913  BLI_assert(GS(static_cast<ID *>(object.data)->name) == ID_CU_LEGACY);
914  Curve &curve = *static_cast<Curve *>(object.data);
915  /* Clear all modifiers for the bevel object.
916  *
917  * This is because they can not be reliably evaluated for an original object (at least because
918  * the state of dependencies is not know).
919  *
920  * So we create temporary copy of the object which will use same data as the original bevel, but
921  * will have no modifiers. */
922  Object bevel_object = blender::dna::shallow_zero_initialize();
923  if (curve.bevobj != nullptr) {
924  bevel_object = blender::dna::shallow_copy(*curve.bevobj);
925  BLI_listbase_clear(&bevel_object.modifiers);
926  BKE_object_runtime_reset(&bevel_object);
927  curve.bevobj = &bevel_object;
928  }
929 
930  /* Same thing for taper. */
931  Object taper_object = blender::dna::shallow_zero_initialize();
932  if (curve.taperobj != nullptr) {
933  taper_object = blender::dna::shallow_copy(*curve.taperobj);
934  BLI_listbase_clear(&taper_object.modifiers);
935  BKE_object_runtime_reset(&taper_object);
936  curve.taperobj = &taper_object;
937  }
938 
939  /* NOTE: We don't have dependency graph or scene here, so we pass nullptr. This is all fine since
940  * they are only used for modifier stack, which we have explicitly disabled for all objects.
941  *
942  * TODO(sergey): This is a very fragile logic, but proper solution requires re-writing quite a
943  * bit of internal functions (#BKE_mesh_nomain_to_mesh) and also Mesh From Curve operator.
944  * Brecht says hold off with that. */
945  BKE_displist_make_curveTypes(nullptr, nullptr, &object, true);
946 
947  BKE_object_runtime_free_data(&bevel_object);
948  BKE_object_runtime_free_data(&taper_object);
949 }
950 
951 static const Curves *get_evaluated_curves_from_object(const Object *object)
952 {
953  if (GeometrySet *geometry_set_eval = object->runtime.geometry_set_eval) {
954  return geometry_set_eval->get_curves_for_read();
955  }
956  return nullptr;
957 }
958 
959 static Mesh *mesh_new_from_evaluated_curve_type_object(const Object *evaluated_object)
960 {
961  if (const Mesh *mesh = BKE_object_get_evaluated_mesh(evaluated_object)) {
962  return BKE_mesh_copy_for_eval(mesh, false);
963  }
964  if (const Curves *curves = get_evaluated_curves_from_object(evaluated_object)) {
966  }
967  return nullptr;
968 }
969 
971 {
972  /* If the object is evaluated, it should either have an evaluated mesh or curve data already.
973  * The mesh can be duplicated, or the curve converted to wire mesh edges. */
974  if (DEG_is_evaluated_object(object)) {
976  }
977 
978  /* Otherwise, create a temporary "fake" evaluated object and try again. This might have
979  * different results, since in order to avoid having adverse affects to other original objects,
980  * modifiers are cleared. An alternative would be to create a temporary depsgraph only for this
981  * object and its dependencies. */
982  Object *temp_object = object_for_curve_to_mesh_create(object);
983  ID *temp_data = static_cast<ID *>(temp_object->data);
984  curve_to_mesh_eval_ensure(*temp_object);
985 
986  /* If evaluating the curve replaced object data with different data, free the original data. */
987  if (temp_data != temp_object->data) {
988  if (GS(temp_data->name) == ID_CU_LEGACY) {
989  /* Clear edit mode pointers that were explicitly copied to the temporary curve. */
990  Curve *curve = reinterpret_cast<Curve *>(temp_data);
991  curve->editfont = nullptr;
992  curve->editnurb = nullptr;
993  }
994  BKE_id_free(nullptr, temp_data);
995  }
996 
998 
999  object_for_curve_to_mesh_free(temp_object);
1000 
1001  return mesh;
1002 }
1003 
1005 {
1006  MetaBall *mball = (MetaBall *)object->data;
1007 
1008  /* NOTE: We can only create mesh for a polygonized meta ball. This figures out all original meta
1009  * balls and all evaluated child meta balls (since polygonization is only stored in the mother
1010  * ball).
1011  *
1012  * Create empty mesh so script-authors don't run into None objects. */
1013  if (!DEG_is_evaluated_object(object) || object->runtime.curve_cache == nullptr ||
1015  return (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
1016  }
1017 
1018  Mesh *mesh_result = (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
1019  BKE_mesh_from_metaball(&object->runtime.curve_cache->disp, mesh_result);
1020  BKE_mesh_texspace_copy_from_object(mesh_result, object);
1021 
1022  /* Copy materials. */
1023  mesh_result->totcol = mball->totcol;
1024  mesh_result->mat = (Material **)MEM_dupallocN(mball->mat);
1025  if (mball->mat != nullptr) {
1026  for (int i = mball->totcol; i-- > 0;) {
1027  mesh_result->mat[i] = BKE_object_material_get(object, i + 1);
1028  }
1029  }
1030 
1031  return mesh_result;
1032 }
1033 
1035 {
1036  /* While we could copy this into the new mesh,
1037  * add the data to 'mesh' so future calls to this function don't need to re-convert the data. */
1040  }
1041  else {
1043  }
1044 
1045  Mesh *mesh_result = (Mesh *)BKE_id_copy_ex(
1047  /* NOTE: Materials should already be copied. */
1048  /* Copy original mesh name. This is because edit meshes might not have one properly set name. */
1049  BLI_strncpy(mesh_result->id.name, ((ID *)object->data)->name, sizeof(mesh_result->id.name));
1050  return mesh_result;
1051 }
1052 
1054  Object *object,
1055  const bool preserve_origindex)
1056 {
1057  if (DEG_is_original_id(&object->id)) {
1058  return mesh_new_from_mesh(object, (Mesh *)object->data);
1059  }
1060 
1061  if (depsgraph == nullptr) {
1062  return nullptr;
1063  }
1064 
1065  Object object_for_eval = blender::dna::shallow_copy(*object);
1066  if (object_for_eval.runtime.data_orig != nullptr) {
1067  object_for_eval.data = object_for_eval.runtime.data_orig;
1068  }
1069 
1072  if (preserve_origindex) {
1073  mask.vmask |= CD_MASK_ORIGINDEX;
1074  mask.emask |= CD_MASK_ORIGINDEX;
1075  mask.lmask |= CD_MASK_ORIGINDEX;
1076  mask.pmask |= CD_MASK_ORIGINDEX;
1077  }
1078  Mesh *result = mesh_create_eval_final(depsgraph, scene, &object_for_eval, &mask);
1080 }
1081 
1083  Object *object,
1084  const bool preserve_all_data_layers,
1085  const bool preserve_origindex)
1086 {
1087  if (preserve_all_data_layers || preserve_origindex) {
1088  return mesh_new_from_mesh_object_with_layers(depsgraph, object, preserve_origindex);
1089  }
1090  Mesh *mesh_input = (Mesh *)object->data;
1091  /* If we are in edit mode, use evaluated mesh from edit structure, matching to what
1092  * viewport is using for visualization. */
1093  if (mesh_input->edit_mesh != nullptr) {
1094  Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object);
1095  if (editmesh_eval_final != nullptr) {
1096  mesh_input = editmesh_eval_final;
1097  }
1098  }
1099  return mesh_new_from_mesh(object, mesh_input);
1100 }
1101 
1103  Object *object,
1104  const bool preserve_all_data_layers,
1105  const bool preserve_origindex)
1106 {
1107  Mesh *new_mesh = nullptr;
1108  switch (object->type) {
1109  case OB_FONT:
1110  case OB_CURVES_LEGACY:
1111  case OB_SURF:
1112  new_mesh = mesh_new_from_curve_type_object(object);
1113  break;
1114  case OB_MBALL:
1115  new_mesh = mesh_new_from_mball_object(object);
1116  break;
1117  case OB_MESH:
1118  new_mesh = mesh_new_from_mesh_object(
1119  depsgraph, object, preserve_all_data_layers, preserve_origindex);
1120  break;
1121  default:
1122  /* Object does not have geometry data. */
1123  return nullptr;
1124  }
1125  if (new_mesh == nullptr) {
1126  /* Happens in special cases like request of mesh for non-mother meta ball. */
1127  return nullptr;
1128  }
1129 
1130  /* The result must have 0 users, since it's just a mesh which is free-dangling data-block.
1131  * All the conversion functions are supposed to ensure mesh is not counted. */
1132  BLI_assert(new_mesh->id.us == 0);
1133 
1134  /* It is possible that mesh came from modifier stack evaluation, which preserves edit_mesh
1135  * pointer (which allows draw manager to access edit mesh when drawing). Normally this does
1136  * not cause ownership problems because evaluated object runtime is keeping track of the real
1137  * ownership.
1138  *
1139  * Here we are constructing a mesh which is supposed to be independent, which means no shared
1140  * ownership is allowed, so we make sure edit mesh is reset to nullptr (which is similar to as if
1141  * one duplicates the objects and applies all the modifiers). */
1142  new_mesh->edit_mesh = nullptr;
1143 
1144  return new_mesh;
1145 }
1146 
1148 {
1149  ID **id_p = cb_data->id_pointer;
1150  if (*id_p == nullptr) {
1151  return IDWALK_RET_NOP;
1152  }
1153  *id_p = DEG_get_original_id(*id_p);
1154 
1155  return IDWALK_RET_NOP;
1156 }
1157 
1159 {
1160  ID **id_p = cb_data->id_pointer;
1161  if (*id_p == nullptr) {
1162  return IDWALK_RET_NOP;
1163  }
1164 
1165  const int cb_flag = cb_data->cb_flag;
1166  if (cb_flag & IDWALK_CB_USER) {
1167  id_us_plus(*id_p);
1168  }
1169  else if (cb_flag & IDWALK_CB_USER_ONE) {
1170  /* NOTE: in that context, that one should not be needed (since there should be at least already
1171  * one USER_ONE user of that ID), but better be consistent. */
1172  id_us_ensure_real(*id_p);
1173  }
1174  return IDWALK_RET_NOP;
1175 }
1176 
1179  Object *object,
1180  bool preserve_all_data_layers)
1181 {
1183 
1184  Mesh *mesh = BKE_mesh_new_from_object(depsgraph, object, preserve_all_data_layers, false);
1185  if (mesh == nullptr) {
1186  /* Unable to convert the object to a mesh, return an empty one. */
1187  Mesh *mesh_in_bmain = BKE_mesh_add(bmain, ((ID *)object->data)->name + 2);
1188  id_us_min(&mesh_in_bmain->id);
1189  return mesh_in_bmain;
1190  }
1191 
1192  /* Make sure mesh only points original data-blocks, also increase users of materials and other
1193  * possibly referenced data-blocks.
1194  *
1195  * Going to original data-blocks is required to have bmain in a consistent state, where
1196  * everything is only allowed to reference original data-blocks.
1197  *
1198  * Note that user-count updates has to be done *after* mesh has been transferred to Main database
1199  * (since doing refcounting on non-Main IDs is forbidden). */
1202 
1203  /* Append the mesh to 'bmain'.
1204  * We do it a bit longer way since there is no simple and clear way of adding existing data-block
1205  * to the 'bmain'. So we allocate new empty mesh in the 'bmain' (which guarantees all the naming
1206  * and orders and flags) and move the temporary mesh in place there. */
1207  Mesh *mesh_in_bmain = BKE_mesh_add(bmain, mesh->id.name + 2);
1208 
1209  /* NOTE: BKE_mesh_nomain_to_mesh() does not copy materials and instead it preserves them in the
1210  * destination mesh. So we "steal" all related fields before calling it.
1211  *
1212  * TODO(sergey): We really better have a function which gets and ID and accepts it for the bmain.
1213  */
1214  mesh_in_bmain->mat = mesh->mat;
1215  mesh_in_bmain->totcol = mesh->totcol;
1216  mesh_in_bmain->flag = mesh->flag;
1217  mesh_in_bmain->smoothresh = mesh->smoothresh;
1218  mesh->mat = nullptr;
1219 
1220  BKE_mesh_nomain_to_mesh(mesh, mesh_in_bmain, nullptr, &CD_MASK_MESH, true);
1221 
1222  /* Anonymous attributes shouldn't exist on original data. */
1224 
1225  /* User-count is required because so far mesh was in a limbo, where library management does
1226  * not perform any user management (i.e. copy of a mesh will not increase users of materials). */
1228  nullptr, &mesh_in_bmain->id, foreach_libblock_make_usercounts_callback, nullptr, IDWALK_NOP);
1229 
1230  /* Make sure user count from BKE_mesh_add() is the one we expect here and bring it down to 0. */
1231  BLI_assert(mesh_in_bmain->id.us == 1);
1232  id_us_min(&mesh_in_bmain->id);
1233 
1234  return mesh_in_bmain;
1235 }
1236 
1237 static void add_shapekey_layers(Mesh *mesh_dest, Mesh *mesh_src)
1238 {
1239  KeyBlock *kb;
1240  Key *key = mesh_src->key;
1241  int i;
1242 
1243  if (!mesh_src->key) {
1244  return;
1245  }
1246 
1247  /* ensure we can use mesh vertex count for derived mesh custom data */
1248  if (mesh_src->totvert != mesh_dest->totvert) {
1249  CLOG_ERROR(&LOG,
1250  "vertex size mismatch (mesh/dm) '%s' (%d != %d)",
1251  mesh_src->id.name + 2,
1252  mesh_src->totvert,
1253  mesh_dest->totvert);
1254  return;
1255  }
1256 
1257  for (i = 0, kb = (KeyBlock *)key->block.first; kb; kb = kb->next, i++) {
1258  int ci;
1259  float *array;
1260 
1261  if (mesh_src->totvert != kb->totelem) {
1262  CLOG_ERROR(&LOG,
1263  "vertex size mismatch (Mesh '%s':%d != KeyBlock '%s':%d)",
1264  mesh_src->id.name + 2,
1265  mesh_src->totvert,
1266  kb->name,
1267  kb->totelem);
1268  array = (float *)MEM_calloc_arrayN((size_t)mesh_src->totvert, sizeof(float[3]), __func__);
1269  }
1270  else {
1271  array = (float *)MEM_malloc_arrayN((size_t)mesh_src->totvert, sizeof(float[3]), __func__);
1272  memcpy(array, kb->data, sizeof(float[3]) * (size_t)mesh_src->totvert);
1273  }
1274 
1276  &mesh_dest->vdata, CD_SHAPEKEY, CD_ASSIGN, array, mesh_dest->totvert, kb->name);
1277  ci = CustomData_get_layer_index_n(&mesh_dest->vdata, CD_SHAPEKEY, i);
1278 
1279  mesh_dest->vdata.layers[ci].uid = kb->uid;
1280  }
1281 }
1282 
1284  Scene *scene,
1285  Object *ob_eval,
1286  ModifierData *md_eval,
1287  const bool use_virtual_modifiers,
1288  const bool build_shapekey_layers)
1289 {
1290  Mesh *me = ob_eval->runtime.data_orig ? (Mesh *)ob_eval->runtime.data_orig :
1291  (Mesh *)ob_eval->data;
1292  const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md_eval->type);
1293  Mesh *result = nullptr;
1294  KeyBlock *kb;
1296 
1297  if (!(md_eval->mode & eModifierMode_Realtime)) {
1298  return result;
1299  }
1300 
1301  if (mti->isDisabled && mti->isDisabled(scene, md_eval, false)) {
1302  return result;
1303  }
1304 
1305  if (build_shapekey_layers && me->key &&
1306  (kb = (KeyBlock *)BLI_findlink(&me->key->block, ob_eval->shapenr - 1))) {
1308  }
1309 
1310  Mesh *mesh_temp = (Mesh *)BKE_id_copy_ex(nullptr, &me->id, nullptr, LIB_ID_COPY_LOCALIZE);
1311  int numVerts = 0;
1312  float(*deformedVerts)[3] = nullptr;
1313 
1314  if (use_virtual_modifiers) {
1315  VirtualModifierData virtualModifierData;
1316  for (ModifierData *md_eval_virt =
1317  BKE_modifiers_get_virtual_modifierlist(ob_eval, &virtualModifierData);
1318  md_eval_virt && (md_eval_virt != ob_eval->modifiers.first);
1319  md_eval_virt = md_eval_virt->next) {
1320  if (!BKE_modifier_is_enabled(scene, md_eval_virt, eModifierMode_Realtime)) {
1321  continue;
1322  }
1323  /* All virtual modifiers are deform modifiers. */
1324  const ModifierTypeInfo *mti_virt = BKE_modifier_get_info((ModifierType)md_eval_virt->type);
1326  if (mti_virt->type != eModifierTypeType_OnlyDeform) {
1327  continue;
1328  }
1329 
1330  if (deformedVerts == nullptr) {
1331  deformedVerts = BKE_mesh_vert_coords_alloc(me, &numVerts);
1332  }
1333  mti_virt->deformVerts(md_eval_virt, &mectx, mesh_temp, deformedVerts, numVerts);
1334  }
1335  }
1336 
1337  if (mti->type == eModifierTypeType_OnlyDeform) {
1338  if (deformedVerts == nullptr) {
1339  deformedVerts = BKE_mesh_vert_coords_alloc(me, &numVerts);
1340  }
1341  result = mesh_temp;
1342  mti->deformVerts(md_eval, &mectx, result, deformedVerts, numVerts);
1343  BKE_mesh_vert_coords_apply(result, deformedVerts);
1344 
1345  if (build_shapekey_layers) {
1347  }
1348  }
1349  else {
1350  if (deformedVerts != nullptr) {
1351  BKE_mesh_vert_coords_apply(mesh_temp, deformedVerts);
1352  }
1353 
1354  if (build_shapekey_layers) {
1355  add_shapekey_layers(mesh_temp, me);
1356  }
1357 
1358  result = mti->modifyMesh(md_eval, &mectx, mesh_temp);
1360 
1361  if (mesh_temp != result) {
1362  BKE_id_free(nullptr, mesh_temp);
1363  }
1364  }
1365 
1366  if (deformedVerts != nullptr) {
1367  MEM_freeN(deformedVerts);
1368  }
1369 
1370  return result;
1371 }
1372 
1373 /* This is a Mesh-based copy of the same function in DerivedMesh.cc */
1374 static void shapekey_layers_to_keyblocks(Mesh *mesh_src, Mesh *mesh_dst, int actshape_uid)
1375 {
1376  KeyBlock *kb;
1377  int i, j, tot;
1378 
1379  if (!mesh_dst->key) {
1380  return;
1381  }
1382 
1383  tot = CustomData_number_of_layers(&mesh_src->vdata, CD_SHAPEKEY);
1384  for (i = 0; i < tot; i++) {
1385  CustomDataLayer *layer =
1386  &mesh_src->vdata.layers[CustomData_get_layer_index_n(&mesh_src->vdata, CD_SHAPEKEY, i)];
1387  float(*kbcos)[3];
1388 
1389  for (kb = (KeyBlock *)mesh_dst->key->block.first; kb; kb = kb->next) {
1390  if (kb->uid == layer->uid) {
1391  break;
1392  }
1393  }
1394 
1395  if (!kb) {
1396  kb = BKE_keyblock_add(mesh_dst->key, layer->name);
1397  kb->uid = layer->uid;
1398  }
1399 
1400  if (kb->data) {
1401  MEM_freeN(kb->data);
1402  }
1403 
1404  const float(*cos)[3] = (const float(*)[3])CustomData_get_layer_n(
1405  &mesh_src->vdata, CD_SHAPEKEY, i);
1406  kb->totelem = mesh_src->totvert;
1407 
1408  kb->data = kbcos = (float(*)[3])MEM_malloc_arrayN(kb->totelem, sizeof(float[3]), __func__);
1409  if (kb->uid == actshape_uid) {
1410  MVert *mvert = mesh_src->mvert;
1411 
1412  for (j = 0; j < mesh_src->totvert; j++, kbcos++, mvert++) {
1413  copy_v3_v3(*kbcos, mvert->co);
1414  }
1415  }
1416  else {
1417  for (j = 0; j < kb->totelem; j++, cos++, kbcos++) {
1418  copy_v3_v3(*kbcos, *cos);
1419  }
1420  }
1421  }
1422 
1423  for (kb = (KeyBlock *)mesh_dst->key->block.first; kb; kb = kb->next) {
1424  if (kb->totelem != mesh_src->totvert) {
1425  if (kb->data) {
1426  MEM_freeN(kb->data);
1427  }
1428 
1429  kb->totelem = mesh_src->totvert;
1430  kb->data = MEM_calloc_arrayN(kb->totelem, sizeof(float[3]), __func__);
1431  CLOG_ERROR(&LOG, "lost a shapekey layer: '%s'! (bmesh internal error)", kb->name);
1432  }
1433  }
1434 }
1435 
1437  Mesh *mesh_dst,
1438  Object *ob,
1439  const CustomData_MeshMasks *mask,
1440  bool take_ownership)
1441 {
1442  BLI_assert(mesh_src->id.tag & LIB_TAG_NO_MAIN);
1443 
1444  /* mesh_src might depend on mesh_dst, so we need to do everything with a local copy */
1445  /* TODO(Sybren): the above claim came from 2.7x derived-mesh code (DM_to_mesh);
1446  * check whether it is still true with Mesh */
1447  Mesh tmp = blender::dna::shallow_copy(*mesh_dst);
1448  int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly;
1449  bool did_shapekeys = false;
1450  eCDAllocType alloctype = CD_DUPLICATE;
1451 
1452  if (take_ownership /* && dm->type == DM_TYPE_CDDM && dm->needsFree */) {
1453  bool has_any_referenced_layers = CustomData_has_referenced(&mesh_src->vdata) ||
1454  CustomData_has_referenced(&mesh_src->edata) ||
1455  CustomData_has_referenced(&mesh_src->ldata) ||
1456  CustomData_has_referenced(&mesh_src->fdata) ||
1457  CustomData_has_referenced(&mesh_src->pdata);
1458  if (!has_any_referenced_layers) {
1459  alloctype = CD_ASSIGN;
1460  }
1461  }
1462  CustomData_reset(&tmp.vdata);
1463  CustomData_reset(&tmp.edata);
1464  CustomData_reset(&tmp.fdata);
1465  CustomData_reset(&tmp.ldata);
1466  CustomData_reset(&tmp.pdata);
1467 
1468  totvert = tmp.totvert = mesh_src->totvert;
1469  totedge = tmp.totedge = mesh_src->totedge;
1470  totloop = tmp.totloop = mesh_src->totloop;
1471  totpoly = tmp.totpoly = mesh_src->totpoly;
1472  tmp.totface = 0;
1473 
1474  CustomData_copy(&mesh_src->vdata, &tmp.vdata, mask->vmask, alloctype, totvert);
1475  CustomData_copy(&mesh_src->edata, &tmp.edata, mask->emask, alloctype, totedge);
1476  CustomData_copy(&mesh_src->ldata, &tmp.ldata, mask->lmask, alloctype, totloop);
1477  CustomData_copy(&mesh_src->pdata, &tmp.pdata, mask->pmask, alloctype, totpoly);
1478  tmp.cd_flag = mesh_src->cd_flag;
1479  tmp.runtime.deformed_only = mesh_src->runtime.deformed_only;
1480 
1481  /* Clear the normals completely, since the new vertex / polygon count might be different. */
1483 
1484  if (CustomData_has_layer(&mesh_src->vdata, CD_SHAPEKEY)) {
1485  KeyBlock *kb;
1486  int uid;
1487 
1488  if (ob) {
1489  kb = (KeyBlock *)BLI_findlink(&mesh_dst->key->block, ob->shapenr - 1);
1490  if (kb) {
1491  uid = kb->uid;
1492  }
1493  else {
1494  CLOG_ERROR(&LOG, "could not find active shapekey %d!", ob->shapenr - 1);
1495 
1496  uid = INT_MAX;
1497  }
1498  }
1499  else {
1500  /* if no object, set to INT_MAX so we don't mess up any shapekey layers */
1501  uid = INT_MAX;
1502  }
1503 
1504  shapekey_layers_to_keyblocks(mesh_src, mesh_dst, uid);
1505  did_shapekeys = true;
1506  }
1507 
1508  /* copy texture space */
1509  if (ob) {
1511  }
1512 
1513  /* not all DerivedMeshes store their verts/edges/faces in CustomData, so
1514  * we set them here in case they are missing */
1515  /* TODO(Sybren): we could probably replace CD_ASSIGN with alloctype and
1516  * always directly pass mesh_src->mxxx, instead of using a ternary operator. */
1517  if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) {
1519  CD_MVERT,
1520  CD_ASSIGN,
1521  (alloctype == CD_ASSIGN) ? mesh_src->mvert :
1522  MEM_dupallocN(mesh_src->mvert),
1523  totvert);
1524  }
1525  if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) {
1527  CD_MEDGE,
1528  CD_ASSIGN,
1529  (alloctype == CD_ASSIGN) ? mesh_src->medge :
1530  MEM_dupallocN(mesh_src->medge),
1531  totedge);
1532  }
1533  if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) {
1535  CD_MLOOP,
1536  CD_ASSIGN,
1537  (alloctype == CD_ASSIGN) ? mesh_src->mloop :
1538  MEM_dupallocN(mesh_src->mloop),
1539  tmp.totloop);
1541  CD_MPOLY,
1542  CD_ASSIGN,
1543  (alloctype == CD_ASSIGN) ? mesh_src->mpoly :
1544  MEM_dupallocN(mesh_src->mpoly),
1545  tmp.totpoly);
1546  }
1547 
1548  /* object had got displacement layer, should copy this layer to save sculpted data */
1549  /* NOTE(nazgul): maybe some other layers should be copied? */
1550  if (CustomData_has_layer(&mesh_dst->ldata, CD_MDISPS)) {
1551  if (totloop == mesh_dst->totloop) {
1552  MDisps *mdisps = (MDisps *)CustomData_get_layer(&mesh_dst->ldata, CD_MDISPS);
1553  CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop);
1554  if (alloctype == CD_ASSIGN) {
1555  /* Assign nullptr to prevent double-free. */
1556  CustomData_set_layer(&mesh_dst->ldata, CD_MDISPS, nullptr);
1557  }
1558  }
1559  }
1560 
1561  /* yes, must be before _and_ after tessellate */
1563 
1564  CustomData_free(&mesh_dst->vdata, mesh_dst->totvert);
1565  CustomData_free(&mesh_dst->edata, mesh_dst->totedge);
1566  CustomData_free(&mesh_dst->fdata, mesh_dst->totface);
1567  CustomData_free(&mesh_dst->ldata, mesh_dst->totloop);
1568  CustomData_free(&mesh_dst->pdata, mesh_dst->totpoly);
1569 
1570  /* ok, this should now use new CD shapekey data,
1571  * which should be fed through the modifier
1572  * stack */
1573  if (tmp.totvert != mesh_dst->totvert && !did_shapekeys && mesh_dst->key) {
1574  CLOG_ERROR(&LOG, "YEEK! this should be recoded! Shape key loss!: ID '%s'", tmp.id.name);
1575  if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) {
1576  id_us_min(&tmp.key->id);
1577  }
1578  tmp.key = nullptr;
1579  }
1580 
1581  /* Clear selection history */
1582  MEM_SAFE_FREE(tmp.mselect);
1583  tmp.totselect = 0;
1585 
1586  /* Clear any run-time data.
1587  * Even though this mesh won't typically have run-time data, the Python API can for e.g.
1588  * create loop-triangle cache here, which is confusing when left in the mesh, see: T81136. */
1590 
1591  /* skip the listbase */
1592  MEMCPY_STRUCT_AFTER(mesh_dst, &tmp, id.prev);
1593 
1594  BLI_freelistN(&mesh_dst->vertex_group_names);
1597 
1598  if (take_ownership) {
1599  if (alloctype == CD_ASSIGN) {
1600  CustomData_free_typemask(&mesh_src->vdata, mesh_src->totvert, ~mask->vmask);
1601  CustomData_free_typemask(&mesh_src->edata, mesh_src->totedge, ~mask->emask);
1602  CustomData_free_typemask(&mesh_src->ldata, mesh_src->totloop, ~mask->lmask);
1603  CustomData_free_typemask(&mesh_src->pdata, mesh_src->totpoly, ~mask->pmask);
1604  }
1605  BKE_id_free(nullptr, mesh_src);
1606  }
1607 
1609 }
1610 
1611 void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb)
1612 {
1613  BLI_assert(mesh_src->id.tag & LIB_TAG_NO_MAIN);
1614 
1615  int a, totvert = mesh_src->totvert;
1616  float *fp;
1617  MVert *mvert;
1618 
1619  if (totvert == 0 || mesh_dst->totvert == 0 || mesh_dst->totvert != totvert) {
1620  return;
1621  }
1622 
1623  if (kb->data) {
1624  MEM_freeN(kb->data);
1625  }
1626  kb->data = MEM_malloc_arrayN(mesh_dst->key->elemsize, mesh_dst->totvert, "kb->data");
1627  kb->totelem = totvert;
1628 
1629  fp = (float *)kb->data;
1630  mvert = mesh_src->mvert;
1631 
1632  for (a = 0; a < kb->totelem; a++, fp += 3, mvert++) {
1633  copy_v3_v3(fp, mvert->co);
1634  }
1635 }
typedef float(TangentPoint)[2]
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:27
struct Curve * BKE_curve_add(struct Main *bmain, const char *name, int type)
Definition: curve.cc:414
#define CU_DO_2DFILL(cu)
Definition: BKE_curve.h:70
short BKE_curve_type_get(const struct Curve *cu)
void BKE_curve_texspace_calc(struct Curve *cu)
Definition: curve.cc:518
Low-level operations for curves.
bool CustomData_merge(const struct CustomData *source, struct CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
void CustomData_free(struct CustomData *data, int totelem)
Definition: customdata.cc:2373
int CustomData_number_of_layers(const struct CustomData *data, int type)
bool CustomData_free_layer(struct CustomData *data, int type, int totelem, int index)
Definition: customdata.cc:2831
eCDAllocType
@ CD_ASSIGN
@ CD_CALLOC
@ CD_DUPLICATE
void CustomData_copy(const struct CustomData *source, struct CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
bool CustomData_has_layer(const struct CustomData *data, int type)
int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name)
void * CustomData_set_layer(const struct CustomData *data, int type, void *ptr)
int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n)
void * CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem, const char *name)
Definition: customdata.cc:2792
bool CustomData_has_referenced(const struct CustomData *data)
void * CustomData_get_layer_n(const struct CustomData *data, int type, int n)
void * CustomData_get_layer(const struct CustomData *data, int type)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.cc:2776
void CustomData_realloc(struct CustomData *data, int totelem)
Definition: customdata.cc:2307
const CustomData_MeshMasks CD_MASK_MESH
Definition: customdata.cc:2065
void CustomData_free_typemask(struct CustomData *data, int totelem, eCustomDataMask mask)
Definition: customdata.cc:2387
void CustomData_reset(struct CustomData *data)
Definition: customdata.cc:2367
void CustomData_update_typemap(struct CustomData *data)
Definition: customdata.cc:2193
support for deformation groups and hooks.
void BKE_defgroup_copy_list(struct ListBase *outbase, const struct ListBase *inbase)
display list (or rather multi purpose list) stuff.
@ DL_CYCL_V
Definition: BKE_displist.h:38
@ DL_CYCL_U
Definition: BKE_displist.h:37
void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, bool for_render)
@ DL_SURF
Definition: BKE_displist.h:24
@ DL_INDEX4
Definition: BKE_displist.h:28
@ DL_INDEX3
Definition: BKE_displist.h:26
@ DL_POLY
Definition: BKE_displist.h:20
@ DL_SEGM
Definition: BKE_displist.h:22
void BKE_keyblock_convert_to_mesh(const struct KeyBlock *kb, struct MVert *mvert, int totvert)
struct KeyBlock * BKE_keyblock_add(struct Key *key, const char *name)
Definition: key.c:1814
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
Definition: BKE_lib_id.h:143
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:187
@ LIB_ID_CREATE_NO_USER_REFCOUNT
Definition: BKE_lib_id.h:126
@ LIB_ID_CREATE_NO_MAIN
Definition: BKE_lib_id.h:122
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, int flag)
void id_us_min(struct ID *id)
Definition: lib_id.c:313
void * BKE_id_new_nomain(short type, const char *name)
Definition: lib_id.c:1173
void BKE_id_free(struct Main *bmain, void *idv)
void id_us_ensure_real(struct ID *id)
Definition: lib_id.c:260
void id_us_plus(struct ID *id)
Definition: lib_id.c:305
void BKE_library_foreach_ID_link(struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
Definition: lib_query.c:350
@ IDWALK_NOP
@ IDWALK_CB_USER_ONE
Definition: BKE_lib_query.h:79
@ IDWALK_CB_USER
Definition: BKE_lib_query.h:73
@ IDWALK_RET_NOP
Definition: BKE_lib_query.h:83
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
void BKE_id_materials_copy(struct Main *bmain, struct ID *id_src, struct ID *id_dst)
Definition: material.c:507
struct Mesh * BKE_mesh_copy_for_eval(const struct Mesh *source, bool reference)
void BKE_mesh_poly_edgehash_insert(struct EdgeHash *ehash, const struct MPoly *mp, const struct MLoop *mloop)
struct Mesh * BKE_mesh_add(struct Main *bmain, const char *name)
Definition: mesh.cc:963
void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float(*vert_coords)[3])
Definition: mesh.cc:1834
void BKE_mesh_assert_normals_dirty_or_calculated(const struct Mesh *mesh)
struct Mesh * BKE_mesh_new_nomain(int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
Definition: mesh.cc:991
void BKE_mesh_update_customdata_pointers(struct Mesh *me, bool do_ensure_tess_cd)
Definition: mesh.cc:874
void BKE_mesh_texspace_copy_from_object(struct Mesh *me, struct Object *ob)
Definition: mesh.cc:1302
void BKE_mesh_clear_derived_normals(struct Mesh *mesh)
void BKE_mesh_texspace_calc(struct Mesh *me)
Definition: mesh.cc:1231
float(* BKE_mesh_vert_coords_alloc(const struct Mesh *mesh, int *r_vert_len))[3]
void BKE_mesh_calc_edges(struct Mesh *mesh, bool keep_existing_edges, bool select_new_edges)
struct Mesh * mesh_create_eval_final(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
void BKE_mesh_runtime_clear_geometry(struct Mesh *mesh)
struct Mesh * mesh_get_eval_final(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me)
Definition: mesh_wrapper.cc:94
struct Mesh * BKE_mesh_wrapper_ensure_subdivision(struct Mesh *me)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode)
struct ModifierData * BKE_modifiers_get_virtual_modifierlist(const struct Object *ob, struct VirtualModifierData *data)
@ eModifierTypeType_OnlyDeform
Definition: BKE_modifier.h:44
@ MOD_APPLY_TO_BASE_MESH
Definition: BKE_modifier.h:128
General operations, lookup, etc. for blender objects.
void BKE_object_free_modifiers(struct Object *ob, int flag)
Definition: object.cc:1289
struct Mesh * BKE_object_get_editmesh_eval_final(const struct Object *object)
struct Mesh * BKE_object_get_evaluated_mesh(const struct Object *object)
void BKE_object_free_derived_caches(struct Object *ob)
Definition: object.cc:1774
void BKE_object_runtime_free_data(struct Object *object)
Definition: object.cc:5110
void BKE_object_runtime_reset(struct Object *object)
Definition: object.cc:5090
General operations for point clouds.
void * BKE_pointcloud_add(struct Main *bmain, const char *name)
Definition: pointcloud.cc:219
const char * POINTCLOUD_ATTR_POSITION
Definition: pointcloud.cc:54
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP free_value)
Definition: edgehash.c:230
BLI_INLINE void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *r_v0, unsigned int *r_v1)
Definition: BLI_edgehash.h:161
EdgeHashIterator * BLI_edgehashIterator_new(EdgeHash *eh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: edgehash.c:394
int BLI_edgehash_len(const EdgeHash *eh) ATTR_WARN_UNUSED_RESULT
Definition: edgehash.c:368
BLI_INLINE void BLI_edgehashIterator_step(EdgeHashIterator *ehi)
Definition: BLI_edgehash.h:153
#define BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly)
Definition: BLI_edgehash.h:183
void BLI_edgehashIterator_free(EdgeHashIterator *ehi)
Definition: edgehash.c:408
bool BLI_edgehash_haskey(const EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT
Definition: edgehash.c:363
BLI_INLINE bool BLI_edgehashIterator_isDone(const EdgeHashIterator *ehi)
Definition: BLI_edgehash.h:157
EdgeHash * BLI_edgehash_new_ex(const char *info, unsigned int nentries_reserve)
Definition: edgehash.c:212
void * BLI_edgehash_lookup(const EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT
Definition: edgehash.c:295
BLI_INLINE void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val)
Definition: BLI_edgehash.h:177
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int max_ii(int a, int b)
MINLINE void copy_v3_v3(float r[3], const float a[3])
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
unsigned int uint
Definition: BLI_sys_types.h:67
#define POINTER_AS_UINT(i)
#define UNUSED(x)
#define ELEM(...)
#define POINTER_FROM_UINT(i)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
bool DEG_is_original_id(const struct ID *id)
bool DEG_is_evaluated_object(const struct Object *object)
struct ID * DEG_get_original_id(struct ID *id)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ LIB_TAG_NO_MAIN
Definition: DNA_ID.h:744
@ ID_CU_LEGACY
Definition: DNA_ID_enums.h:49
@ ID_ME
Definition: DNA_ID_enums.h:48
@ CU_AUTOSPACE
@ CU_SMOOTH
@ CU_NURB_CYCLIC
@ CU_NURB_ENDPOINT
@ CU_3D
#define CD_MASK_ORIGINDEX
#define CD_MASK_PROP_ALL
@ CD_PROP_FLOAT3
@ CD_SHAPEKEY
@ CD_MEDGE
@ CD_MVERT
@ CD_MLOOPUV
@ ME_WRAPPER_TYPE_BMESH
@ ME_AUTOSPACE_EVALUATED
@ ME_SMOOTH
@ ME_EDGEDRAW
@ ME_EDGERENDER
@ ME_LOOSEEDGE
@ eModifierMode_Realtime
ModifierType
Object is a sort of wrapper for general info.
@ OB_MBALL
@ OB_SURF
@ OB_FONT
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES_LEGACY
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
void materialize(MutableSpan< T > r_span) const
GVArray lookup_or_default(const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type, const void *default_value=nullptr) const
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
Definition: BKE_curves.hh:138
#define SELECT
Scene scene
Curve curve
const Depsgraph * depsgraph
int count
#define GS(x)
Definition: iris.c:225
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_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
void BKE_mesh_from_metaball(ListBase *lb, Mesh *me)
Definition: mesh_convert.cc:72
Mesh * BKE_mesh_new_nomain_from_curve(const Object *ob)
void BKE_pointcloud_from_mesh(Mesh *me, PointCloud *pointcloud)
void BKE_mesh_from_pointcloud(const PointCloud *pointcloud, Mesh *me)
static Mesh * mesh_new_from_mesh_object(Depsgraph *depsgraph, Object *object, const bool preserve_all_data_layers, const bool preserve_origindex)
static void add_shapekey_layers(Mesh *mesh_dest, Mesh *mesh_src)
Mesh * BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, Scene *scene, Object *ob_eval, ModifierData *md_eval, const bool use_virtual_modifiers, const bool build_shapekey_layers)
void BKE_pointcloud_to_mesh(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob)
void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb)
static void appendPolyLineVert(ListBase *lb, uint index)
void BKE_mesh_edges_set_draw_render(Mesh *mesh)
void BKE_mesh_to_pointcloud(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob)
static void curve_to_mesh_eval_ensure(Object &object)
static void mesh_copy_texture_space_from_curve_type(const Curve *cu, Mesh *me)
static int foreach_libblock_make_original_callback(LibraryIDLinkCallbackData *cb_data)
static Mesh * mesh_new_from_evaluated_curve_type_object(const Object *evaluated_object)
void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob)
static Mesh * mesh_new_from_curve_type_object(const Object *object)
void BKE_mesh_to_curve_nurblist(const Mesh *me, ListBase *nurblist, const int edge_users_test)
static void prependPolyLineVert(ListBase *lb, uint index)
static Object * object_for_curve_to_mesh_create(const Object *object)
static void shapekey_layers_to_keyblocks(Mesh *mesh_src, Mesh *mesh_dst, int actshape_uid)
static Mesh * mesh_new_from_mesh_object_with_layers(Depsgraph *depsgraph, Object *object, const bool preserve_origindex)
static Mesh * mesh_new_from_mball_object(Object *object)
static void make_edges_mdata_extend(MEdge **r_alledge, int *r_totedge, const MPoly *mpoly, MLoop *mloop, const int totpoly)
static const Curves * get_evaluated_curves_from_object(const Object *object)
static Mesh * mesh_new_from_mesh(Object *object, Mesh *mesh)
Mesh * BKE_mesh_new_from_object(Depsgraph *depsgraph, Object *object, const bool preserve_all_data_layers, const bool preserve_origindex)
static int foreach_libblock_make_usercounts_callback(LibraryIDLinkCallbackData *cb_data)
static CLG_LogRef LOG
Definition: mesh_convert.cc:70
Mesh * BKE_mesh_new_nomain_from_curve_displist(const Object *ob, const ListBase *dispbase)
Mesh * BKE_mesh_new_from_object_to_bmain(Main *bmain, Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers)
static int mesh_nurbs_displist_to_mdata(const Curve *cu, const ListBase *dispbase, MVert **r_allvert, int *r_totvert, MEdge **r_alledge, int *r_totedge, MLoop **r_allloop, MPoly **r_allpoly, MLoopUV **r_alluv, int *r_totloop, int *r_totpoly)
#define ASSERT_IS_VALID_MESH(mesh)
Definition: mesh_convert.cc:67
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob, const CustomData_MeshMasks *mask, bool take_ownership)
static void object_for_curve_to_mesh_free(Object *temp_object)
static unsigned a[3]
Definition: RandGen.cpp:78
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:319
Mesh * curve_to_wire_mesh(const CurvesGeometry &curve)
MutableAttributeAccessor pointcloud_attributes_for_write(PointCloud &pointcloud)
AttributeAccessor mesh_attributes(const Mesh &mesh)
MutableAttributeAccessor mesh_attributes_for_write(Mesh &mesh)
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
vec_base< float, 3 > float3
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
MutableSpan< float3 > positions
Map< AttributeIDRef, GMutableSpan > point_attributes
struct BMVert * v
Definition: bmesh_class.h:153
float weight
uint8_t f1
float vec[4]
float radius
ListBase disp
Definition: BKE_curve.h:33
struct Object * bevobj
float loc[3]
struct Material ** mat
short totcol
struct EditFont * editfont
char texflag
EditNurb * editnurb
ListBase nurb
struct Object * taperobj
float size[3]
CustomDataLayer * layers
short type
Definition: BKE_displist.h:55
float * verts
Definition: BKE_displist.h:58
int * index
Definition: BKE_displist.h:59
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
int us
Definition: DNA_ID.h:388
char name[66]
Definition: DNA_ID.h:378
char name[64]
Definition: DNA_key_types.h:52
struct KeyBlock * next
Definition: DNA_key_types.h:25
void * data
Definition: DNA_key_types.h:50
ID id
Definition: DNA_key_types.h:63
int elemsize
Definition: DNA_key_types.h:80
ListBase block
Definition: DNA_key_types.h:84
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
unsigned int v1
unsigned int v2
unsigned int e
unsigned int v
short mat_nr
float co[3]
Definition: BKE_main.h:121
struct MEdge * medge
struct BMEditMesh * edit_mesh
float smoothresh
CustomData vdata
struct MVert * mvert
float size[3]
uint16_t flag
struct Material ** mat
int totedge
ListBase vertex_group_names
char cd_flag
int totvert
struct MLoop * mloop
int totface
Mesh_Runtime runtime
CustomData pdata
CustomData fdata
int totpoly
short totcol
char texflag
int vertex_group_active_index
CustomData edata
int totloop
struct Key * key
int totselect
struct MPoly * mpoly
CustomData ldata
float loc[3]
struct MSelect * mselect
short totcol
struct Material ** mat
struct ModifierData * next
bool(* isDisabled)(const struct Scene *scene, struct ModifierData *md, bool userRenderParams)
Definition: BKE_modifier.h:291
ModifierTypeType type
Definition: BKE_modifier.h:160
struct Mesh *(* modifyMesh)(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct Mesh *mesh)
Definition: BKE_modifier.h:231
void(* deformVerts)(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct Mesh *mesh, float(*vertexCos)[3], int numVerts)
Definition: BKE_modifier.h:184
short flagu
short orderu
BPoint * bp
short resolu
struct CurveCache * curve_cache
struct ID * data_eval
struct GeometrySet * geometry_set_eval
struct ID * data_orig
ListBase modifiers
short shapenr
Object_Runtime runtime
void * data
struct CustomData pdata