Blender  V3.3
bmesh_construct.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2007 Blender Foundation. All rights reserved. */
3 
10 #include "MEM_guardedalloc.h"
11 
12 #include "BLI_alloca.h"
13 #include "BLI_math.h"
14 #include "BLI_sort_utils.h"
15 
16 #include "BKE_customdata.h"
17 
18 #include "DNA_mesh_types.h"
19 #include "DNA_meshdata_types.h"
20 
21 #include "bmesh.h"
22 #include "intern/bmesh_private.h"
23 
24 #define SELECT 1
25 
26 bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len)
27 {
28  int i, i_prev = len - 1;
29  for (i = 0; i < len; i++) {
30  vert_arr[i] = BM_edge_share_vert(edge_arr[i_prev], edge_arr[i]);
31  if (vert_arr[i] == NULL) {
32  return false;
33  }
34  i_prev = i;
35  }
36  return true;
37 }
38 
39 bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
40 {
41  int i, i_prev = len - 1;
42  for (i = 0; i < len; i++) {
43  edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
44  if (edge_arr[i_prev] == NULL) {
45  return false;
46  }
47  i_prev = i;
48  }
49  return true;
50 }
51 
52 void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len)
53 {
54  int i, i_prev = len - 1;
55  for (i = 0; i < len; i++) {
56  edge_arr[i_prev] = BM_edge_create(
57  bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
58  i_prev = i;
59  }
60 }
61 
62 /* prototypes */
63 static void bm_loop_attrs_copy(BMesh *bm_src,
64  BMesh *bm_dst,
65  const BMLoop *l_src,
66  BMLoop *l_dst,
67  eCustomDataMask mask_exclude);
68 
70  BMVert *v1,
71  BMVert *v2,
72  BMVert *v3,
73  BMVert *v4,
74  const BMFace *f_example,
75  const eBMCreateFlag create_flag)
76 {
77  BMVert *vtar[4] = {v1, v2, v3, v4};
78  return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true);
79 }
80 
82 {
83  BMLoop *l_first;
84  BMLoop *l_iter;
85 
86 #ifdef DEBUG
87  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
88  do {
90  } while ((l_iter = l_iter->next) != l_first);
91 #endif
92 
93  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
94  do {
95  BMLoop *l_other = l_iter->radial_next;
96 
97  if (l_other && l_other != l_iter) {
98  BMLoop *l_src[2];
99  BMLoop *l_dst[2] = {l_iter, l_iter->next};
100  uint j;
101 
102  if (l_other->v == l_iter->v) {
103  l_src[0] = l_other;
104  l_src[1] = l_other->next;
105  }
106  else {
107  l_src[0] = l_other->next;
108  l_src[1] = l_other;
109  }
110 
111  for (j = 0; j < 2; j++) {
112  BLI_assert(l_dst[j]->v == l_src[j]->v);
113  if (BM_ELEM_API_FLAG_TEST(l_dst[j], _FLAG_OVERLAP) == 0) {
114  if ((filter_fn == NULL) || filter_fn(l_src[j], user_data)) {
115  bm_loop_attrs_copy(bm, bm, l_src[j], l_dst[j], 0x0);
117  }
118  }
119  }
120  }
121  } while ((l_iter = l_iter->next) != l_first);
122 
123  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
124  do {
126  } while ((l_iter = l_iter->next) != l_first);
127 }
128 
137  BMVert *v2,
138  BMEdge **edges,
139  const int len,
140  BMEdge **edges_sort,
141  BMVert **verts_sort)
142 {
143  BMEdge *e_iter, *e_first;
144  BMVert *v_iter;
145  int i;
146 
147  /* all flags _must_ be cleared on exit! */
148  for (i = 0; i < len; i++) {
150  BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV);
151  BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV);
152  }
153 
154  /* find first edge */
155  i = 0;
156  v_iter = v1;
157  e_iter = e_first = v1->e;
158  do {
159  if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) && (BM_edge_other_vert(e_iter, v_iter) == v2)) {
160  i = 1;
161  break;
162  }
163  } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
164  if (i == 0) {
165  goto error;
166  }
167 
168  i = 0;
169  do {
170  /* entering loop will always succeed */
171  if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) {
172  if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) {
173  /* vert is in loop multiple times */
174  goto error;
175  }
176 
178  edges_sort[i] = e_iter;
179 
181  verts_sort[i] = v_iter;
182 
183  i += 1;
184 
185  /* walk onto the next vertex */
186  v_iter = BM_edge_other_vert(e_iter, v_iter);
187  if (i == len) {
188  if (UNLIKELY(v_iter != verts_sort[0])) {
189  goto error;
190  }
191  break;
192  }
193 
194  e_first = e_iter;
195  }
196  } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
197 
198  if (i == len) {
199  return true;
200  }
201 
202 error:
203  for (i = 0; i < len; i++) {
207  }
208 
209  return false;
210 }
211 
213  BMVert *v1,
214  BMVert *v2,
215  BMEdge **edges,
216  const int len,
217  const BMFace *f_example,
218  const eBMCreateFlag create_flag)
219 {
220  BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
221  BMVert **verts_sort = BLI_array_alloca(verts_sort, len);
222 
223  BLI_assert(len && v1 && v2 && edges && bm);
224 
225  if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) {
226  return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
227  }
228 
229  return NULL;
230 }
231 
233  BMVert **vert_arr,
234  const int len,
235  const BMFace *f_example,
236  const eBMCreateFlag create_flag,
237  const bool calc_winding,
238  const bool create_edges)
239 {
240  BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
241  uint winding[2] = {0, 0};
242  int i, i_prev = len - 1;
243  BMVert *v_winding[2] = {vert_arr[i_prev], vert_arr[0]};
244 
245  BLI_assert(len > 2);
246 
247  for (i = 0; i < len; i++) {
248  if (create_edges) {
249  edge_arr[i] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
250  }
251  else {
252  edge_arr[i] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
253  if (edge_arr[i] == NULL) {
254  return NULL;
255  }
256  }
257 
258  if (calc_winding) {
259  /* the edge may exist already and be attached to a face
260  * in this case we can find the best winding to use for the new face */
261  if (edge_arr[i]->l) {
262  BMVert *test_v1, *test_v2;
263  /* we want to use the reverse winding to the existing order */
264  BM_edge_ordered_verts(edge_arr[i], &test_v2, &test_v1);
265  winding[(vert_arr[i_prev] == test_v2)]++;
266  BLI_assert(ELEM(vert_arr[i_prev], test_v2, test_v1));
267  }
268  }
269 
270  i_prev = i;
271  }
272 
273  /* --- */
274 
275  if (calc_winding) {
276  if (winding[0] < winding[1]) {
277  winding[0] = 1;
278  winding[1] = 0;
279  }
280  else {
281  winding[0] = 0;
282  winding[1] = 1;
283  }
284  }
285  else {
286  winding[0] = 0;
287  winding[1] = 1;
288  }
289 
290  /* --- */
291 
292  /* create the face */
293  return BM_face_create_ngon(
294  bm, v_winding[winding[0]], v_winding[winding[1]], edge_arr, len, f_example, create_flag);
295 }
296 
297 void BM_verts_sort_radial_plane(BMVert **vert_arr, int len)
298 {
299  struct SortIntByFloat *vang = BLI_array_alloca(vang, len);
300  BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len);
301 
302  float nor[3], cent[3];
303  int index_tangent = 0;
304  BM_verts_calc_normal_from_cloud_ex(vert_arr, len, nor, cent, &index_tangent);
305  const float *far = vert_arr[index_tangent]->co;
306 
307  /* Now calculate every points angle around the normal (signed). */
308  for (int i = 0; i < len; i++) {
309  vang[i].sort_value = angle_signed_on_axis_v3v3v3_v3(far, cent, vert_arr[i]->co, nor);
310  vang[i].data = i;
311  vert_arr_map[i] = vert_arr[i];
312  }
313 
314  /* sort by angle and magic! - we have our ngon */
315  qsort(vang, len, sizeof(*vang), BLI_sortutil_cmp_float);
316 
317  /* --- */
318 
319  for (int i = 0; i < len; i++) {
320  vert_arr[i] = vert_arr_map[vang[i].data];
321  }
322 }
323 
324 /*************************************************************/
325 
326 static void bm_vert_attrs_copy(
327  BMesh *bm_src, BMesh *bm_dst, const BMVert *v_src, BMVert *v_dst, eCustomDataMask mask_exclude)
328 {
329  if ((bm_src == bm_dst) && (v_src == v_dst)) {
330  BLI_assert_msg(0, "BMVert: source and target match");
331  return;
332  }
333  if ((mask_exclude & CD_MASK_NORMAL) == 0) {
334  copy_v3_v3(v_dst->no, v_src->no);
335  }
336  CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->vdata, v_dst->head.data, mask_exclude);
338  &bm_src->vdata, &bm_dst->vdata, v_src->head.data, &v_dst->head.data, mask_exclude);
339 }
340 
341 static void bm_edge_attrs_copy(
342  BMesh *bm_src, BMesh *bm_dst, const BMEdge *e_src, BMEdge *e_dst, eCustomDataMask mask_exclude)
343 {
344  if ((bm_src == bm_dst) && (e_src == e_dst)) {
345  BLI_assert_msg(0, "BMEdge: source and target match");
346  return;
347  }
348  CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->edata, e_dst->head.data, mask_exclude);
350  &bm_src->edata, &bm_dst->edata, e_src->head.data, &e_dst->head.data, mask_exclude);
351 }
352 
353 static void bm_loop_attrs_copy(
354  BMesh *bm_src, BMesh *bm_dst, const BMLoop *l_src, BMLoop *l_dst, eCustomDataMask mask_exclude)
355 {
356  if ((bm_src == bm_dst) && (l_src == l_dst)) {
357  BLI_assert_msg(0, "BMLoop: source and target match");
358  return;
359  }
360  CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->ldata, l_dst->head.data, mask_exclude);
362  &bm_src->ldata, &bm_dst->ldata, l_src->head.data, &l_dst->head.data, mask_exclude);
363 }
364 
365 static void bm_face_attrs_copy(
366  BMesh *bm_src, BMesh *bm_dst, const BMFace *f_src, BMFace *f_dst, eCustomDataMask mask_exclude)
367 {
368  if ((bm_src == bm_dst) && (f_src == f_dst)) {
369  BLI_assert_msg(0, "BMFace: source and target match");
370  return;
371  }
372  if ((mask_exclude & CD_MASK_NORMAL) == 0) {
373  copy_v3_v3(f_dst->no, f_src->no);
374  }
375  CustomData_bmesh_free_block_data_exclude_by_type(&bm_dst->pdata, f_dst->head.data, mask_exclude);
377  &bm_src->pdata, &bm_dst->pdata, f_src->head.data, &f_dst->head.data, mask_exclude);
378  f_dst->mat_nr = f_src->mat_nr;
379 }
380 
382  BMesh *bm_dst,
383  const void *ele_src_v,
384  void *ele_dst_v,
385  const char hflag_mask,
386  const uint64_t cd_mask_exclude)
387 {
388  /* TODO: Special handling for hide flags? */
389  /* TODO: swap src/dst args, everywhere else in bmesh does other way round. */
390 
391  const BMHeader *ele_src = ele_src_v;
392  BMHeader *ele_dst = ele_dst_v;
393 
394  BLI_assert(ele_src->htype == ele_dst->htype);
395  BLI_assert(ele_src != ele_dst);
396 
397  if ((hflag_mask & BM_ELEM_SELECT) == 0) {
398  /* First we copy select */
399  if (BM_elem_flag_test((BMElem *)ele_src, BM_ELEM_SELECT)) {
400  BM_elem_select_set(bm_dst, (BMElem *)ele_dst, true);
401  }
402  }
403 
404  /* Now we copy flags */
405  if (hflag_mask == 0) {
406  ele_dst->hflag = ele_src->hflag;
407  }
408  else if (hflag_mask == 0xff) {
409  /* pass */
410  }
411  else {
412  ele_dst->hflag = ((ele_dst->hflag & hflag_mask) | (ele_src->hflag & ~hflag_mask));
413  }
414 
415  /* Copy specific attributes */
416  switch (ele_dst->htype) {
417  case BM_VERT:
419  bm_src, bm_dst, (const BMVert *)ele_src, (BMVert *)ele_dst, cd_mask_exclude);
420  break;
421  case BM_EDGE:
423  bm_src, bm_dst, (const BMEdge *)ele_src, (BMEdge *)ele_dst, cd_mask_exclude);
424  break;
425  case BM_LOOP:
427  bm_src, bm_dst, (const BMLoop *)ele_src, (BMLoop *)ele_dst, cd_mask_exclude);
428  break;
429  case BM_FACE:
431  bm_src, bm_dst, (const BMFace *)ele_src, (BMFace *)ele_dst, cd_mask_exclude);
432  break;
433  default:
434  BLI_assert(0);
435  break;
436  }
437 }
438 
439 void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst)
440 {
441  /* BMESH_TODO, default 'use_flags' to false */
442  BM_elem_attrs_copy_ex(bm_src, bm_dst, ele_src, ele_dst, BM_ELEM_SELECT, 0x0);
443 }
444 
445 void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v)
446 {
447  BMHeader *ele_dst = ele_dst_v;
448  const BMHeader *ele_src = ele_src_v;
449 
450  BLI_assert(ele_src->htype == ele_dst->htype);
451 
452  if ((ele_src->hflag & BM_ELEM_SELECT) != (ele_dst->hflag & BM_ELEM_SELECT)) {
453  BM_elem_select_set(bm_dst, (BMElem *)ele_dst, (ele_src->hflag & BM_ELEM_SELECT) != 0);
454  }
455 }
456 
457 /* helper function for 'BM_mesh_copy' */
459  BMesh *bm_new, BMesh *bm_old, BMVert **vtable, BMEdge **etable, BMFace *f)
460 {
461  BMLoop **loops = BLI_array_alloca(loops, f->len);
463  BMEdge **edges = BLI_array_alloca(edges, f->len);
464 
465  BMFace *f_new;
466  BMLoop *l_iter, *l_first;
467  int j;
468 
469  j = 0;
470  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
471  do {
472  loops[j] = l_iter;
473  verts[j] = vtable[BM_elem_index_get(l_iter->v)];
474  edges[j] = etable[BM_elem_index_get(l_iter->e)];
475  j++;
476  } while ((l_iter = l_iter->next) != l_first);
477 
478  f_new = BM_face_create(bm_new, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD);
479 
480  if (UNLIKELY(f_new == NULL)) {
481  return NULL;
482  }
483 
484  /* use totface in case adding some faces fails */
485  BM_elem_index_set(f_new, (bm_new->totface - 1)); /* set_inline */
486 
487  BM_elem_attrs_copy_ex(bm_old, bm_new, f, f_new, 0xff, 0x0);
488  f_new->head.hflag = f->head.hflag; /* low level! don't do this for normal api use */
489 
490  j = 0;
491  l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
492  do {
493  BM_elem_attrs_copy(bm_old, bm_new, loops[j], l_iter);
494  j++;
495  } while ((l_iter = l_iter->next) != l_first);
496 
497  return f_new;
498 }
499 
501  const Mesh *me_src_array[],
502  const int me_src_array_len,
503  const BMAllocTemplate *allocsize)
504 
505 {
506  if (allocsize == NULL) {
507  allocsize = &bm_mesh_allocsize_default;
508  }
509 
510  char cd_flag = 0;
511 
512  for (int i = 0; i < me_src_array_len; i++) {
513  const Mesh *me_src = me_src_array[i];
514  if (i == 0) {
515  CustomData_copy(&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
516  CustomData_copy(&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
517  CustomData_copy(&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
518  CustomData_copy(&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
519  }
520  else {
521  CustomData_merge(&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
522  CustomData_merge(&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
523  CustomData_merge(&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
524  CustomData_merge(&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
525  }
526 
527  cd_flag |= me_src->cd_flag;
528  }
529 
530  cd_flag |= BM_mesh_cd_flag_from_bmesh(bm_dst);
531 
532  CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
533  CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
534  CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
535  CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
536 
537  BM_mesh_cd_flag_apply(bm_dst, cd_flag);
538 }
539 
541  const Mesh *me_src,
542  const BMAllocTemplate *allocsize)
543 {
544  BM_mesh_copy_init_customdata_from_mesh_array(bm_dst, &me_src, 1, allocsize);
545 }
546 
547 void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
548 {
549  if (allocsize == NULL) {
550  allocsize = &bm_mesh_allocsize_default;
551  }
552 
553  CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
554  CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
555  CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
556  CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
557 
558  CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
559  CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
560  CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
561  CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
562 }
563 
565  BMesh *bm_src,
566  const char htype,
567  const BMAllocTemplate *allocsize)
568 {
569  if (allocsize == NULL) {
570  allocsize = &bm_mesh_allocsize_default;
571  }
572 
573  const char htypes[4] = {BM_VERT, BM_EDGE, BM_LOOP, BM_FACE};
574  BLI_assert(((&bm_dst->vdata + 1) == &bm_dst->edata) &&
575  ((&bm_dst->vdata + 2) == &bm_dst->ldata) && ((&bm_dst->vdata + 3) == &bm_dst->pdata));
576 
577  BLI_assert(((&allocsize->totvert + 1) == &allocsize->totedge) &&
578  ((&allocsize->totvert + 2) == &allocsize->totloop) &&
579  ((&allocsize->totvert + 3) == &allocsize->totface));
580 
581  for (int i = 0; i < 4; i++) {
582  if (!(htypes[i] & htype)) {
583  continue;
584  }
585  CustomData *dst = &bm_dst->vdata + i;
586  CustomData *src = &bm_src->vdata + i;
587  const int size = *(&allocsize->totvert + i);
588 
589  for (int l = 0; l < src->totlayer; l++) {
591  dst, src->layers[l].type, CD_CALLOC, NULL, 0, src->layers[l].name);
592  }
593  CustomData_bmesh_init_pool(dst, size, htypes[i]);
594  }
595 }
596 
598 {
599  BMesh *bm_new;
600  BMVert *v, *v_new, **vtable = NULL;
601  BMEdge *e, *e_new, **etable = NULL;
602  BMFace *f, *f_new, **ftable = NULL;
603  BMElem **eletable;
604  BMEditSelection *ese;
605  BMIter iter;
606  int i;
607  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm_old);
608 
609  /* allocate a bmesh */
610  bm_new = BM_mesh_create(&allocsize,
611  &((struct BMeshCreateParams){
612  .use_toolflags = bm_old->use_toolflags,
613  }));
614 
615  BM_mesh_copy_init_customdata(bm_new, bm_old, &allocsize);
616 
617  vtable = MEM_mallocN(sizeof(BMVert *) * bm_old->totvert, "BM_mesh_copy vtable");
618  etable = MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable");
619  ftable = MEM_mallocN(sizeof(BMFace *) * bm_old->totface, "BM_mesh_copy ftable");
620 
621  BM_ITER_MESH_INDEX (v, &iter, bm_old, BM_VERTS_OF_MESH, i) {
622  /* copy between meshes so can't use 'example' argument */
623  v_new = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD);
624  BM_elem_attrs_copy_ex(bm_old, bm_new, v, v_new, 0xff, 0x0);
625  v_new->head.hflag = v->head.hflag; /* low level! don't do this for normal api use */
626  vtable[i] = v_new;
627  BM_elem_index_set(v, i); /* set_inline */
628  BM_elem_index_set(v_new, i); /* set_inline */
629  }
630  bm_old->elem_index_dirty &= ~BM_VERT;
631  bm_new->elem_index_dirty &= ~BM_VERT;
632 
633  /* safety check */
634  BLI_assert(i == bm_old->totvert);
635 
636  BM_ITER_MESH_INDEX (e, &iter, bm_old, BM_EDGES_OF_MESH, i) {
637  e_new = BM_edge_create(bm_new,
638  vtable[BM_elem_index_get(e->v1)],
639  vtable[BM_elem_index_get(e->v2)],
640  e,
642 
643  BM_elem_attrs_copy_ex(bm_old, bm_new, e, e_new, 0xff, 0x0);
644  e_new->head.hflag = e->head.hflag; /* low level! don't do this for normal api use */
645  etable[i] = e_new;
646  BM_elem_index_set(e, i); /* set_inline */
647  BM_elem_index_set(e_new, i); /* set_inline */
648  }
649  bm_old->elem_index_dirty &= ~BM_EDGE;
650  bm_new->elem_index_dirty &= ~BM_EDGE;
651 
652  /* safety check */
653  BLI_assert(i == bm_old->totedge);
654 
655  BM_ITER_MESH_INDEX (f, &iter, bm_old, BM_FACES_OF_MESH, i) {
656  BM_elem_index_set(f, i); /* set_inline */
657 
658  f_new = bm_mesh_copy_new_face(bm_new, bm_old, vtable, etable, f);
659 
660  ftable[i] = f_new;
661 
662  if (f == bm_old->act_face) {
663  bm_new->act_face = f_new;
664  }
665  }
666  bm_old->elem_index_dirty &= ~BM_FACE;
667  bm_new->elem_index_dirty &= ~BM_FACE;
668 
669  /* low level! don't do this for normal api use */
670  bm_new->totvertsel = bm_old->totvertsel;
671  bm_new->totedgesel = bm_old->totedgesel;
672  bm_new->totfacesel = bm_old->totfacesel;
673 
674  /* safety check */
675  BLI_assert(i == bm_old->totface);
676 
677  /* copy over edit selection history */
678  for (ese = bm_old->selected.first; ese; ese = ese->next) {
679  BMElem *ele = NULL;
680 
681  switch (ese->htype) {
682  case BM_VERT:
683  eletable = (BMElem **)vtable;
684  break;
685  case BM_EDGE:
686  eletable = (BMElem **)etable;
687  break;
688  case BM_FACE:
689  eletable = (BMElem **)ftable;
690  break;
691  default:
692  eletable = NULL;
693  break;
694  }
695 
696  if (eletable) {
697  ele = eletable[BM_elem_index_get(ese->ele)];
698  if (ele) {
699  BM_select_history_store(bm_new, ele);
700  }
701  }
702  }
703 
704  MEM_freeN(etable);
705  MEM_freeN(vtable);
706  MEM_freeN(ftable);
707 
708  /* Copy various settings. */
709  bm_new->shapenr = bm_old->shapenr;
710  bm_new->selectmode = bm_old->selectmode;
711 
712  return bm_new;
713 }
714 
715 char BM_vert_flag_from_mflag(const char mflag)
716 {
717  return (((mflag & SELECT) ? BM_ELEM_SELECT : 0) | ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
718 }
719 char BM_edge_flag_from_mflag(const short mflag)
720 {
721  return (((mflag & SELECT) ? BM_ELEM_SELECT : 0) | ((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) |
722  ((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) |
723  ((mflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0) | /* invert */
724  ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
725 }
726 char BM_face_flag_from_mflag(const char mflag)
727 {
728  return (((mflag & ME_FACE_SEL) ? BM_ELEM_SELECT : 0) |
729  ((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0) | ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
730 }
731 
733 {
734  const char hflag = v->head.hflag;
735 
736  return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0));
737 }
738 
740 {
741  const char hflag = e->head.hflag;
742 
743  return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) |
744  ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) |
745  ((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) |
746  ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) |
747  (BM_edge_is_wire(e) ? ME_LOOSEEDGE : 0) | /* not typical */
748  ME_EDGERENDER);
749 }
751 {
752  const char hflag = f->head.hflag;
753 
754  return (((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) |
755  ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0));
756 }
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_merge(const struct CustomData *source, struct CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
@ CD_CALLOC
void CustomData_bmesh_free_block_data_exclude_by_type(struct CustomData *data, void *block, eCustomDataMask mask_exclude)
Definition: customdata.cc:3722
void CustomData_copy(const struct CustomData *source, struct CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
void * CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem, const char *name)
Definition: customdata.cc:2792
uint64_t eCustomDataMask
void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, char htype)
Definition: customdata.cc:3541
const CustomData_MeshMasks CD_MASK_BMESH
Definition: customdata.cc:2090
void CustomData_bmesh_copy_data_exclude_by_type(const struct CustomData *source, struct CustomData *dest, void *src_block, void **dest_block, eCustomDataMask mask_exclude)
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:22
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
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:521
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:24
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNLIKELY(x)
#define ELEM(...)
#define CD_MASK_NORMAL
@ ME_HIDE
@ ME_SMOOTH
@ ME_FACE_SEL
@ ME_EDGEDRAW
@ ME_SEAM
@ ME_EDGERENDER
@ ME_LOOSEEDGE
@ ME_SHARP
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
bool(* BMLoopFilterFunc)(const BMLoop *, void *user_data)
Definition: bmesh_class.h:506
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
@ 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
void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
static void bm_face_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const BMFace *f_src, BMFace *f_dst, eCustomDataMask mask_exclude)
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.
static void bm_vert_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const BMVert *v_src, BMVert *v_dst, eCustomDataMask mask_exclude)
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)
void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v)
static void bm_loop_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const BMLoop *l_src, BMLoop *l_dst, eCustomDataMask mask_exclude)
#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_array(BMesh *bm_dst, const Mesh *me_src_array[], const int me_src_array_len, const BMAllocTemplate *allocsize)
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.
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)
static void bm_edge_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const BMEdge *e_src, BMEdge *e_dst, eCustomDataMask mask_exclude)
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:41
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:464
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:395
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:123
eBMCreateFlag
Definition: bmesh_core.h:11
@ BM_CREATE_SKIP_CD
Definition: bmesh_core.h:20
@ BM_CREATE_NO_DOUBLE
Definition: bmesh_core.h:14
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:111
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
#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.cc:23
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
Definition: bmesh_mesh.cc:125
#define BMALLOC_TEMPLATE_FROM_BM(bm)
Definition: bmesh_mesh.h:180
char BM_mesh_cd_flag_from_bmesh(BMesh *bm)
void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag)
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)
@ _FLAG_MV
Definition: bmesh_private.h:58
@ _FLAG_MF
Definition: bmesh_private.h:57
@ _FLAG_OVERLAP
Definition: bmesh_private.h:59
#define BM_ELEM_API_FLAG_DISABLE(element, f)
Definition: bmesh_private.h:71
#define BM_ELEM_API_FLAG_TEST(element, f)
Definition: bmesh_private.h:76
#define BM_ELEM_API_FLAG_ENABLE(element, f)
Definition: bmesh_private.h:66
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1553
void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
Definition: bmesh_query.c:1141
BMVert * BM_edge_share_vert(BMEdge *e1, BMEdge *e2)
Definition: bmesh_query.c:1079
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
SyclQueue void void * src
int len
Definition: draw_manager.c:108
static float verts[][3]
uint nor
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static void error(const char *str)
Definition: meshlaplacian.c:51
unsigned __int64 uint64_t
Definition: stdint.h:90
BMHeader head
Definition: bmesh_class.h:111
struct BMEditSelection * next
Definition: bmesh_marking.h:10
short mat_nr
Definition: bmesh_class.h:281
int len
Definition: bmesh_class.h:267
BMHeader head
Definition: bmesh_class.h:255
float no[3]
Definition: bmesh_class.h:271
char htype
Definition: bmesh_class.h:64
char hflag
Definition: bmesh_class.h:66
void * data
Definition: bmesh_class.h:51
BMHeader head
Definition: bmesh_class.h:145
struct BMVert * v
Definition: bmesh_class.h:153
struct BMEdge * e
Definition: bmesh_class.h:164
struct BMLoop * radial_next
Definition: bmesh_class.h:204
struct BMLoop * next
Definition: bmesh_class.h:233
float co[3]
Definition: bmesh_class.h:87
float no[3]
Definition: bmesh_class.h:88
BMHeader head
Definition: bmesh_class.h:85
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
void * first
Definition: DNA_listBase.h:31
CustomData vdata
char cd_flag
CustomData pdata
CustomData edata
CustomData ldata