Blender  V2.93
bmesh_construct.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2007 Blender Foundation.
17  * All rights reserved.
18  */
19 
26 #include "MEM_guardedalloc.h"
27 
28 #include "BLI_alloca.h"
29 #include "BLI_math.h"
30 #include "BLI_sort_utils.h"
31 
32 #include "BKE_customdata.h"
33 
34 #include "DNA_mesh_types.h"
35 #include "DNA_meshdata_types.h"
36 
37 #include "bmesh.h"
38 #include "intern/bmesh_private.h"
39 
40 #define SELECT 1
41 
47 bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len)
48 {
49  int i, i_prev = len - 1;
50  for (i = 0; i < len; i++) {
51  vert_arr[i] = BM_edge_share_vert(edge_arr[i_prev], edge_arr[i]);
52  if (vert_arr[i] == NULL) {
53  return false;
54  }
55  i_prev = i;
56  }
57  return true;
58 }
59 
65 bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
66 {
67  int i, i_prev = len - 1;
68  for (i = 0; i < len; i++) {
69  edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
70  if (edge_arr[i_prev] == NULL) {
71  return false;
72  }
73  i_prev = i;
74  }
75  return true;
76 }
77 
82 void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len)
83 {
84  int i, i_prev = len - 1;
85  for (i = 0; i < len; i++) {
86  edge_arr[i_prev] = BM_edge_create(
87  bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
88  i_prev = i;
89  }
90 }
91 
92 /* prototypes */
93 static void bm_loop_attrs_copy(
94  BMesh *bm_src, BMesh *bm_dst, const BMLoop *l_src, BMLoop *l_dst, CustomDataMask mask_exclude);
95 
111  BMVert *v1,
112  BMVert *v2,
113  BMVert *v3,
114  BMVert *v4,
115  const BMFace *f_example,
116  const eBMCreateFlag create_flag)
117 {
118  BMVert *vtar[4] = {v1, v2, v3, v4};
119  return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true);
120 }
121 
133 {
134  BMLoop *l_first;
135  BMLoop *l_iter;
136 
137 #ifdef DEBUG
138  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
139  do {
141  } while ((l_iter = l_iter->next) != l_first);
142 #endif
143 
144  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
145  do {
146  BMLoop *l_other = l_iter->radial_next;
147 
148  if (l_other && l_other != l_iter) {
149  BMLoop *l_src[2];
150  BMLoop *l_dst[2] = {l_iter, l_iter->next};
151  uint j;
152 
153  if (l_other->v == l_iter->v) {
154  l_src[0] = l_other;
155  l_src[1] = l_other->next;
156  }
157  else {
158  l_src[0] = l_other->next;
159  l_src[1] = l_other;
160  }
161 
162  for (j = 0; j < 2; j++) {
163  BLI_assert(l_dst[j]->v == l_src[j]->v);
164  if (BM_ELEM_API_FLAG_TEST(l_dst[j], _FLAG_OVERLAP) == 0) {
165  if ((filter_fn == NULL) || filter_fn(l_src[j], user_data)) {
166  bm_loop_attrs_copy(bm, bm, l_src[j], l_dst[j], 0x0);
168  }
169  }
170  }
171  }
172  } while ((l_iter = l_iter->next) != l_first);
173 
174  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
175  do {
177  } while ((l_iter = l_iter->next) != l_first);
178 }
179 
188  BMVert *v2,
189  BMEdge **edges,
190  const int len,
191  BMEdge **edges_sort,
192  BMVert **verts_sort)
193 {
194  BMEdge *e_iter, *e_first;
195  BMVert *v_iter;
196  int i;
197 
198  /* all flags _must_ be cleared on exit! */
199  for (i = 0; i < len; i++) {
201  BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV);
202  BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV);
203  }
204 
205  /* find first edge */
206  i = 0;
207  v_iter = v1;
208  e_iter = e_first = v1->e;
209  do {
210  if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) && (BM_edge_other_vert(e_iter, v_iter) == v2)) {
211  i = 1;
212  break;
213  }
214  } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
215  if (i == 0) {
216  goto error;
217  }
218 
219  i = 0;
220  do {
221  /* entering loop will always succeed */
222  if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) {
223  if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) {
224  /* vert is in loop multiple times */
225  goto error;
226  }
227 
229  edges_sort[i] = e_iter;
230 
232  verts_sort[i] = v_iter;
233 
234  i += 1;
235 
236  /* walk onto the next vertex */
237  v_iter = BM_edge_other_vert(e_iter, v_iter);
238  if (i == len) {
239  if (UNLIKELY(v_iter != verts_sort[0])) {
240  goto error;
241  }
242  break;
243  }
244 
245  e_first = e_iter;
246  }
247  } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
248 
249  if (i == len) {
250  return true;
251  }
252 
253 error:
254  for (i = 0; i < len; i++) {
258  }
259 
260  return false;
261 }
262 
278  BMVert *v1,
279  BMVert *v2,
280  BMEdge **edges,
281  const int len,
282  const BMFace *f_example,
283  const eBMCreateFlag create_flag)
284 {
285  BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
286  BMVert **verts_sort = BLI_array_alloca(verts_sort, len);
287 
288  BLI_assert(len && v1 && v2 && edges && bm);
289 
290  if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) {
291  return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
292  }
293 
294  return NULL;
295 }
296 
306  BMVert **vert_arr,
307  const int len,
308  const BMFace *f_example,
309  const eBMCreateFlag create_flag,
310  const bool calc_winding,
311  const bool create_edges)
312 {
313  BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
314  uint winding[2] = {0, 0};
315  int i, i_prev = len - 1;
316  BMVert *v_winding[2] = {vert_arr[i_prev], vert_arr[0]};
317 
318  BLI_assert(len > 2);
319 
320  for (i = 0; i < len; i++) {
321  if (create_edges) {
322  edge_arr[i] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
323  }
324  else {
325  edge_arr[i] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
326  if (edge_arr[i] == NULL) {
327  return NULL;
328  }
329  }
330 
331  if (calc_winding) {
332  /* the edge may exist already and be attached to a face
333  * in this case we can find the best winding to use for the new face */
334  if (edge_arr[i]->l) {
335  BMVert *test_v1, *test_v2;
336  /* we want to use the reverse winding to the existing order */
337  BM_edge_ordered_verts(edge_arr[i], &test_v2, &test_v1);
338  winding[(vert_arr[i_prev] == test_v2)]++;
339  BLI_assert(ELEM(vert_arr[i_prev], test_v2, test_v1));
340  }
341  }
342 
343  i_prev = i;
344  }
345 
346  /* --- */
347 
348  if (calc_winding) {
349  if (winding[0] < winding[1]) {
350  winding[0] = 1;
351  winding[1] = 0;
352  }
353  else {
354  winding[0] = 0;
355  winding[1] = 1;
356  }
357  }
358  else {
359  winding[0] = 0;
360  winding[1] = 1;
361  }
362 
363  /* --- */
364 
365  /* create the face */
366  return BM_face_create_ngon(
367  bm, v_winding[winding[0]], v_winding[winding[1]], edge_arr, len, f_example, create_flag);
368 }
369 
386 void BM_verts_sort_radial_plane(BMVert **vert_arr, int len)
387 {
388  struct SortIntByFloat *vang = BLI_array_alloca(vang, len);
389  BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len);
390 
391  float nor[3], cent[3];
392  int index_tangent = 0;
393  BM_verts_calc_normal_from_cloud_ex(vert_arr, len, nor, cent, &index_tangent);
394  const float *far = vert_arr[index_tangent]->co;
395 
396  /* Now calculate every points angle around the normal (signed). */
397  for (int i = 0; i < len; i++) {
398  vang[i].sort_value = angle_signed_on_axis_v3v3v3_v3(far, cent, vert_arr[i]->co, nor);
399  vang[i].data = i;
400  vert_arr_map[i] = vert_arr[i];
401  }
402 
403  /* sort by angle and magic! - we have our ngon */
404  qsort(vang, len, sizeof(*vang), BLI_sortutil_cmp_float);
405 
406  /* --- */
407 
408  for (int i = 0; i < len; i++) {
409  vert_arr[i] = vert_arr_map[vang[i].data];
410  }
411 }
412 
413 /*************************************************************/
414 
415 static void bm_vert_attrs_copy(
416  BMesh *bm_src, BMesh *bm_dst, const BMVert *v_src, BMVert *v_dst, CustomDataMask mask_exclude)
417 {
418  if ((bm_src == bm_dst) && (v_src == v_dst)) {
419  BLI_assert(!"BMVert: source and target match");
420  return;
421  }
422  if ((mask_exclude & CD_MASK_NORMAL) == 0) {
423  copy_v3_v3(v_dst->no, v_src->no);
424  }
425  CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->vdata, v_dst->head.data, mask_exclude);
427  &bm_src->vdata, &bm_dst->vdata, v_src->head.data, &v_dst->head.data, mask_exclude);
428 }
429 
430 static void bm_edge_attrs_copy(
431  BMesh *bm_src, BMesh *bm_dst, const BMEdge *e_src, BMEdge *e_dst, CustomDataMask mask_exclude)
432 {
433  if ((bm_src == bm_dst) && (e_src == e_dst)) {
434  BLI_assert(!"BMEdge: source and target match");
435  return;
436  }
437  CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->edata, e_dst->head.data, mask_exclude);
439  &bm_src->edata, &bm_dst->edata, e_src->head.data, &e_dst->head.data, mask_exclude);
440 }
441 
442 static void bm_loop_attrs_copy(
443  BMesh *bm_src, BMesh *bm_dst, const BMLoop *l_src, BMLoop *l_dst, CustomDataMask mask_exclude)
444 {
445  if ((bm_src == bm_dst) && (l_src == l_dst)) {
446  BLI_assert(!"BMLoop: source and target match");
447  return;
448  }
449  CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->ldata, l_dst->head.data, mask_exclude);
451  &bm_src->ldata, &bm_dst->ldata, l_src->head.data, &l_dst->head.data, mask_exclude);
452 }
453 
454 static void bm_face_attrs_copy(
455  BMesh *bm_src, BMesh *bm_dst, const BMFace *f_src, BMFace *f_dst, CustomDataMask mask_exclude)
456 {
457  if ((bm_src == bm_dst) && (f_src == f_dst)) {
458  BLI_assert(!"BMFace: source and target match");
459  return;
460  }
461  if ((mask_exclude & CD_MASK_NORMAL) == 0) {
462  copy_v3_v3(f_dst->no, f_src->no);
463  }
464  CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->pdata, f_dst->head.data, mask_exclude);
466  &bm_src->pdata, &bm_dst->pdata, f_src->head.data, &f_dst->head.data, mask_exclude);
467  f_dst->mat_nr = f_src->mat_nr;
468 }
469 
470 /* BMESH_TODO: Special handling for hide flags? */
471 /* BMESH_TODO: swap src/dst args, everywhere else in bmesh does other way round */
472 
478  BMesh *bm_dst,
479  const void *ele_src_v,
480  void *ele_dst_v,
481  const char hflag_mask,
482  const uint64_t cd_mask_exclude)
483 {
484  const BMHeader *ele_src = ele_src_v;
485  BMHeader *ele_dst = ele_dst_v;
486 
487  BLI_assert(ele_src->htype == ele_dst->htype);
488  BLI_assert(ele_src != ele_dst);
489 
490  if ((hflag_mask & BM_ELEM_SELECT) == 0) {
491  /* First we copy select */
492  if (BM_elem_flag_test((BMElem *)ele_src, BM_ELEM_SELECT)) {
493  BM_elem_select_set(bm_dst, (BMElem *)ele_dst, true);
494  }
495  }
496 
497  /* Now we copy flags */
498  if (hflag_mask == 0) {
499  ele_dst->hflag = ele_src->hflag;
500  }
501  else if (hflag_mask == 0xff) {
502  /* pass */
503  }
504  else {
505  ele_dst->hflag = ((ele_dst->hflag & hflag_mask) | (ele_src->hflag & ~hflag_mask));
506  }
507 
508  /* Copy specific attributes */
509  switch (ele_dst->htype) {
510  case BM_VERT:
512  bm_src, bm_dst, (const BMVert *)ele_src, (BMVert *)ele_dst, cd_mask_exclude);
513  break;
514  case BM_EDGE:
516  bm_src, bm_dst, (const BMEdge *)ele_src, (BMEdge *)ele_dst, cd_mask_exclude);
517  break;
518  case BM_LOOP:
520  bm_src, bm_dst, (const BMLoop *)ele_src, (BMLoop *)ele_dst, cd_mask_exclude);
521  break;
522  case BM_FACE:
524  bm_src, bm_dst, (const BMFace *)ele_src, (BMFace *)ele_dst, cd_mask_exclude);
525  break;
526  default:
527  BLI_assert(0);
528  break;
529  }
530 }
531 
532 void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst)
533 {
534  /* BMESH_TODO, default 'use_flags' to false */
535  BM_elem_attrs_copy_ex(bm_src, bm_dst, ele_src, ele_dst, BM_ELEM_SELECT, 0x0);
536 }
537 
538 void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v)
539 {
540  BMHeader *ele_dst = ele_dst_v;
541  const BMHeader *ele_src = ele_src_v;
542 
543  BLI_assert(ele_src->htype == ele_dst->htype);
544 
545  if ((ele_src->hflag & BM_ELEM_SELECT) != (ele_dst->hflag & BM_ELEM_SELECT)) {
546  BM_elem_select_set(bm_dst, (BMElem *)ele_dst, (ele_src->hflag & BM_ELEM_SELECT) != 0);
547  }
548 }
549 
550 /* helper function for 'BM_mesh_copy' */
552  BMesh *bm_new, BMesh *bm_old, BMVert **vtable, BMEdge **etable, BMFace *f)
553 {
554  BMLoop **loops = BLI_array_alloca(loops, f->len);
556  BMEdge **edges = BLI_array_alloca(edges, f->len);
557 
558  BMFace *f_new;
559  BMLoop *l_iter, *l_first;
560  int j;
561 
562  j = 0;
563  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
564  do {
565  loops[j] = l_iter;
566  verts[j] = vtable[BM_elem_index_get(l_iter->v)];
567  edges[j] = etable[BM_elem_index_get(l_iter->e)];
568  j++;
569  } while ((l_iter = l_iter->next) != l_first);
570 
571  f_new = BM_face_create(bm_new, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD);
572 
573  if (UNLIKELY(f_new == NULL)) {
574  return NULL;
575  }
576 
577  /* use totface in case adding some faces fails */
578  BM_elem_index_set(f_new, (bm_new->totface - 1)); /* set_inline */
579 
580  BM_elem_attrs_copy_ex(bm_old, bm_new, f, f_new, 0xff, 0x0);
581  f_new->head.hflag = f->head.hflag; /* low level! don't do this for normal api use */
582 
583  j = 0;
584  l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
585  do {
586  BM_elem_attrs_copy(bm_old, bm_new, loops[j], l_iter);
587  j++;
588  } while ((l_iter = l_iter->next) != l_first);
589 
590  return f_new;
591 }
592 
594  const Mesh *me_src,
595  const BMAllocTemplate *allocsize)
596 {
597  if (allocsize == NULL) {
598  allocsize = &bm_mesh_allocsize_default;
599  }
600 
601  CustomData_copy(&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
602  CustomData_copy(&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
603  CustomData_copy(&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
604  CustomData_copy(&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
605 
606  CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
607  CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
608  CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
609  CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
610 }
611 
612 void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
613 {
614  if (allocsize == NULL) {
615  allocsize = &bm_mesh_allocsize_default;
616  }
617 
618  CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
619  CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
620  CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
621  CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
622 
623  CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
624  CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
625  CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
626  CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
627 }
628 
639  BMesh *bm_src,
640  const char htype,
641  const BMAllocTemplate *allocsize)
642 {
643  if (allocsize == NULL) {
644  allocsize = &bm_mesh_allocsize_default;
645  }
646 
647  const char htypes[4] = {BM_VERT, BM_EDGE, BM_LOOP, BM_FACE};
648  BLI_assert(((&bm_dst->vdata + 1) == &bm_dst->edata) &&
649  ((&bm_dst->vdata + 2) == &bm_dst->ldata) && ((&bm_dst->vdata + 3) == &bm_dst->pdata));
650 
651  BLI_assert(((&allocsize->totvert + 1) == &allocsize->totedge) &&
652  ((&allocsize->totvert + 2) == &allocsize->totloop) &&
653  ((&allocsize->totvert + 3) == &allocsize->totface));
654 
655  for (int i = 0; i < 4; i++) {
656  if (!(htypes[i] & htype)) {
657  continue;
658  }
659  CustomData *dst = &bm_dst->vdata + i;
660  CustomData *src = &bm_src->vdata + i;
661  const int size = *(&allocsize->totvert + i);
662 
663  for (int l = 0; l < src->totlayer; l++) {
665  dst, src->layers[l].type, CD_CALLOC, NULL, 0, src->layers[l].name);
666  }
667  CustomData_bmesh_init_pool(dst, size, htypes[i]);
668  }
669 }
670 
672 {
673  BMesh *bm_new;
674  BMVert *v, *v_new, **vtable = NULL;
675  BMEdge *e, *e_new, **etable = NULL;
676  BMFace *f, *f_new, **ftable = NULL;
677  BMElem **eletable;
678  BMEditSelection *ese;
679  BMIter iter;
680  int i;
681  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm_old);
682 
683  /* allocate a bmesh */
684  bm_new = BM_mesh_create(&allocsize,
685  &((struct BMeshCreateParams){
686  .use_toolflags = bm_old->use_toolflags,
687  }));
688 
689  BM_mesh_copy_init_customdata(bm_new, bm_old, &allocsize);
690 
691  vtable = MEM_mallocN(sizeof(BMVert *) * bm_old->totvert, "BM_mesh_copy vtable");
692  etable = MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable");
693  ftable = MEM_mallocN(sizeof(BMFace *) * bm_old->totface, "BM_mesh_copy ftable");
694 
695  BM_ITER_MESH_INDEX (v, &iter, bm_old, BM_VERTS_OF_MESH, i) {
696  /* copy between meshes so cant use 'example' argument */
697  v_new = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD);
698  BM_elem_attrs_copy_ex(bm_old, bm_new, v, v_new, 0xff, 0x0);
699  v_new->head.hflag = v->head.hflag; /* low level! don't do this for normal api use */
700  vtable[i] = v_new;
701  BM_elem_index_set(v, i); /* set_inline */
702  BM_elem_index_set(v_new, i); /* set_inline */
703  }
704  bm_old->elem_index_dirty &= ~BM_VERT;
705  bm_new->elem_index_dirty &= ~BM_VERT;
706 
707  /* safety check */
708  BLI_assert(i == bm_old->totvert);
709 
710  BM_ITER_MESH_INDEX (e, &iter, bm_old, BM_EDGES_OF_MESH, i) {
711  e_new = BM_edge_create(bm_new,
712  vtable[BM_elem_index_get(e->v1)],
713  vtable[BM_elem_index_get(e->v2)],
714  e,
716 
717  BM_elem_attrs_copy_ex(bm_old, bm_new, e, e_new, 0xff, 0x0);
718  e_new->head.hflag = e->head.hflag; /* low level! don't do this for normal api use */
719  etable[i] = e_new;
720  BM_elem_index_set(e, i); /* set_inline */
721  BM_elem_index_set(e_new, i); /* set_inline */
722  }
723  bm_old->elem_index_dirty &= ~BM_EDGE;
724  bm_new->elem_index_dirty &= ~BM_EDGE;
725 
726  /* safety check */
727  BLI_assert(i == bm_old->totedge);
728 
729  BM_ITER_MESH_INDEX (f, &iter, bm_old, BM_FACES_OF_MESH, i) {
730  BM_elem_index_set(f, i); /* set_inline */
731 
732  f_new = bm_mesh_copy_new_face(bm_new, bm_old, vtable, etable, f);
733 
734  ftable[i] = f_new;
735 
736  if (f == bm_old->act_face) {
737  bm_new->act_face = f_new;
738  }
739  }
740  bm_old->elem_index_dirty &= ~BM_FACE;
741  bm_new->elem_index_dirty &= ~BM_FACE;
742 
743  /* low level! don't do this for normal api use */
744  bm_new->totvertsel = bm_old->totvertsel;
745  bm_new->totedgesel = bm_old->totedgesel;
746  bm_new->totfacesel = bm_old->totfacesel;
747 
748  /* safety check */
749  BLI_assert(i == bm_old->totface);
750 
751  /* copy over edit selection history */
752  for (ese = bm_old->selected.first; ese; ese = ese->next) {
753  BMElem *ele = NULL;
754 
755  switch (ese->htype) {
756  case BM_VERT:
757  eletable = (BMElem **)vtable;
758  break;
759  case BM_EDGE:
760  eletable = (BMElem **)etable;
761  break;
762  case BM_FACE:
763  eletable = (BMElem **)ftable;
764  break;
765  default:
766  eletable = NULL;
767  break;
768  }
769 
770  if (eletable) {
771  ele = eletable[BM_elem_index_get(ese->ele)];
772  if (ele) {
773  BM_select_history_store(bm_new, ele);
774  }
775  }
776  }
777 
778  MEM_freeN(etable);
779  MEM_freeN(vtable);
780  MEM_freeN(ftable);
781 
782  /* Copy various settings. */
783  bm_new->shapenr = bm_old->shapenr;
784  bm_new->selectmode = bm_old->selectmode;
785 
786  return bm_new;
787 }
788 
789 /* ME -> BM */
790 char BM_vert_flag_from_mflag(const char mflag)
791 {
792  return (((mflag & SELECT) ? BM_ELEM_SELECT : 0) | ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
793 }
794 char BM_edge_flag_from_mflag(const short mflag)
795 {
796  return (((mflag & SELECT) ? BM_ELEM_SELECT : 0) | ((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) |
797  ((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) |
798  ((mflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0) | /* invert */
799  ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
800 }
801 char BM_face_flag_from_mflag(const char mflag)
802 {
803  return (((mflag & ME_FACE_SEL) ? BM_ELEM_SELECT : 0) |
804  ((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0) | ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
805 }
806 
807 /* BM -> ME */
809 {
810  const char hflag = v->head.hflag;
811 
812  return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0));
813 }
814 
816 {
817  const char hflag = e->head.hflag;
818 
819  return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) |
820  ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) |
821  ((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) |
822  ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) |
823  ((BM_edge_is_wire(e)) ? ME_LOOSEEDGE : 0) | /* not typical */
824  ME_EDGERENDER);
825 }
827 {
828  const char hflag = f->head.hflag;
829 
830  return (((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) |
831  ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0));
832 }
CustomData interface, see also DNA_customdata_types.h.
void CustomData_bmesh_copy_data_exclude_by_type(const struct CustomData *source, struct CustomData *dest, void *src_block, void **dest_block, const CustomDataMask mask_exclude)
@ CD_CALLOC
uint64_t CustomDataMask
void * CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem, const char *name)
Definition: customdata.c:2637
void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, const char htype)
Definition: customdata.c:3482
const CustomData_MeshMasks CD_MASK_BMESH
Definition: customdata.c:1964
void CustomData_bmesh_free_block_data_exclude_by_type(struct CustomData *data, void *block, const CustomDataMask mask_exclude)
Definition: customdata.c:3669
void CustomData_copy(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, eCDAllocType alloctype, int totelem)
Definition: customdata.c:2193
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:36
#define BLI_assert(a)
Definition: BLI_assert.h:58
float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:587
MINLINE void copy_v3_v3(float r[3], const float a[3])
int BLI_sortutil_cmp_float(const void *a_, const void *b_)
Definition: sort_utils.c:40
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNLIKELY(x)
#define ELEM(...)
#define CD_MASK_NORMAL
@ ME_HIDE
@ ME_EDGEDRAW
@ ME_SEAM
@ ME_EDGERENDER
@ ME_LOOSEEDGE
@ ME_SHARP
@ ME_SMOOTH
@ ME_FACE_SEL
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
bool(* BMLoopFilterFunc)(const BMLoop *, void *user_data)
Definition: bmesh_class.h:506
@ BM_LOOP
Definition: bmesh_class.h:385
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
@ BM_ELEM_SEAM
Definition: bmesh_class.h:473
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
@ BM_ELEM_SMOOTH
Definition: bmesh_class.h:477
@ BM_ELEM_DRAW
Definition: bmesh_class.h:486
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:553
void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
BMFace * BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, const BMFace *f_example, const eBMCreateFlag create_flag, const bool calc_winding, const bool create_edges)
void BM_verts_sort_radial_plane(BMVert **vert_arr, int len)
static bool bm_edges_sort_winding(BMVert *v1, BMVert *v2, BMEdge **edges, const int len, BMEdge **edges_sort, BMVert **verts_sort)
void BM_face_copy_shared(BMesh *bm, BMFace *f, BMLoopFilterFunc filter_fn, void *user_data)
copies face loop data from shared adjacent faces.
bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len)
void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, const char hflag_mask, const uint64_t cd_mask_exclude)
char BM_face_flag_from_mflag(const char mflag)
static void bm_loop_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const BMLoop *l_src, BMLoop *l_dst, CustomDataMask mask_exclude)
static void bm_vert_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const BMVert *v_src, BMVert *v_dst, CustomDataMask mask_exclude)
static void bm_face_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const BMFace *f_src, BMFace *f_dst, CustomDataMask mask_exclude)
void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v)
#define SELECT
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst)
BMFace * BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, const BMFace *f_example, const eBMCreateFlag create_flag)
Make Quad/Triangle.
char BM_face_flag_to_mflag(BMFace *f)
void BM_mesh_copy_init_customdata_from_mesh(BMesh *bm_dst, const Mesh *me_src, const BMAllocTemplate *allocsize)
void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len)
BMFace * BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, const BMFace *f_example, const eBMCreateFlag create_flag)
Make NGon.
static void bm_edge_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const BMEdge *e_src, BMEdge *e_dst, CustomDataMask mask_exclude)
short BM_edge_flag_to_mflag(BMEdge *e)
char BM_vert_flag_from_mflag(const char mflag)
char BM_edge_flag_from_mflag(const short mflag)
void BM_mesh_copy_init_customdata_all_layers(BMesh *bm_dst, BMesh *bm_src, const char htype, const BMAllocTemplate *allocsize)
char BM_vert_flag_to_mflag(BMVert *v)
static BMFace * bm_mesh_copy_new_face(BMesh *bm_new, BMesh *bm_old, BMVert **vtable, BMEdge **etable, BMFace *f)
BMesh * BM_mesh_copy(BMesh *bm_old)
bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
BMVert * BM_vert_create(BMesh *bm, const float co[3], const BMVert *v_example, const eBMCreateFlag create_flag)
Main function for creating a new vertex.
Definition: bmesh_core.c:58
BMFace * BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len, const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
Definition: bmesh_core.c:500
BMFace * BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const BMFace *f_example, const eBMCreateFlag create_flag)
Definition: bmesh_core.c:428
BMEdge * BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag)
Main function for creating a new edge.
Definition: bmesh_core.c:147
eBMCreateFlag
Definition: bmesh_core.h:26
@ BM_CREATE_SKIP_CD
Definition: bmesh_core.h:33
@ BM_CREATE_NO_DOUBLE
Definition: bmesh_core.h:29
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:125
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select)
#define BM_select_history_store(bm, ele)
const BMAllocTemplate bm_mesh_allocsize_default
Definition: bmesh_mesh.c:46
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
BMesh Make Mesh.
Definition: bmesh_mesh.c:157
#define BMALLOC_TEMPLATE_FROM_BM(bm)
Definition: bmesh_mesh.h:146
void BM_verts_calc_normal_from_cloud_ex(BMVert **varr, int varr_len, float r_normal[3], float r_center[3], int *r_index_tangent)
#define BM_ELEM_API_FLAG_DISABLE(element, f)
Definition: bmesh_private.h:76
#define BM_ELEM_API_FLAG_TEST(element, f)
Definition: bmesh_private.h:81
@ _FLAG_MV
Definition: bmesh_private.h:63
@ _FLAG_MF
Definition: bmesh_private.h:62
@ _FLAG_OVERLAP
Definition: bmesh_private.h:64
#define BM_ELEM_API_FLAG_ENABLE(element, f)
Definition: bmesh_private.h:71
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1995
void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
Definition: bmesh_query.c:1464
BMVert * BM_edge_share_vert(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1366
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
BLI_INLINE BMEdge * bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void * user_data
static float verts[][3]
uint nor
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static void error(const char *str)
Definition: meshlaplacian.c:65
unsigned __int64 uint64_t
Definition: stdint.h:93
BMHeader head
Definition: bmesh_class.h:123
struct BMEditSelection * next
Definition: bmesh_marking.h:24
short mat_nr
Definition: bmesh_class.h:281
int len
Definition: bmesh_class.h:279
BMHeader head
Definition: bmesh_class.h:267
float no[3]
Definition: bmesh_class.h:280
char htype
Definition: bmesh_class.h:76
char hflag
Definition: bmesh_class.h:78
void * data
Definition: bmesh_class.h:63
BMHeader head
Definition: bmesh_class.h:157
struct BMVert * v
Definition: bmesh_class.h:165
struct BMEdge * e
Definition: bmesh_class.h:176
struct BMLoop * radial_next
Definition: bmesh_class.h:216
struct BMLoop * next
Definition: bmesh_class.h:245
float co[3]
Definition: bmesh_class.h:99
float no[3]
Definition: bmesh_class.h:100
BMHeader head
Definition: bmesh_class.h:97
int totvert
Definition: bmesh_class.h:297
int totfacesel
Definition: bmesh_class.h:298
int shapenr
Definition: bmesh_class.h:353
char elem_index_dirty
Definition: bmesh_class.h:305
CustomData vdata
Definition: bmesh_class.h:337
int totedge
Definition: bmesh_class.h:297
ListBase selected
Definition: bmesh_class.h:356
CustomData edata
Definition: bmesh_class.h:337
uint use_toolflags
Definition: bmesh_class.h:333
int totvertsel
Definition: bmesh_class.h:298
BMFace * act_face
Definition: bmesh_class.h:366
short selectmode
Definition: bmesh_class.h:350
int totedgesel
Definition: bmesh_class.h:298
CustomData pdata
Definition: bmesh_class.h:337
CustomData ldata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
CustomDataLayer * layers
void * first
Definition: DNA_listBase.h:47
struct CustomData pdata ldata
uint len