Blender V4.3
bmesh_construct.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include "MEM_guardedalloc.h"
12
13#include "BLI_alloca.h"
14#include "BLI_listbase.h"
15#include "BLI_math_vector.h"
16#include "BLI_sort_utils.h"
17
18#include "BKE_customdata.hh"
19
20#include "DNA_mesh_types.h"
21
22#include "bmesh.hh"
24
25bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len)
26{
27 int i, i_prev = len - 1;
28 for (i = 0; i < len; i++) {
29 vert_arr[i] = BM_edge_share_vert(edge_arr[i_prev], edge_arr[i]);
30 if (vert_arr[i] == nullptr) {
31 return false;
32 }
33 i_prev = i;
34 }
35 return true;
36}
37
38bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
39{
40 int i, i_prev = len - 1;
41 for (i = 0; i < len; i++) {
42 edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
43 if (edge_arr[i_prev] == nullptr) {
44 return false;
45 }
46 i_prev = i;
47 }
48 return true;
49}
50
51void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len)
52{
53 int i, i_prev = len - 1;
54 for (i = 0; i < len; i++) {
55 edge_arr[i_prev] = BM_edge_create(
56 bm, vert_arr[i_prev], vert_arr[i], nullptr, BM_CREATE_NO_DOUBLE);
57 i_prev = i;
58 }
59}
60
62 BMVert *v1,
63 BMVert *v2,
64 BMVert *v3,
65 BMVert *v4,
66 const BMFace *f_example,
67 const eBMCreateFlag create_flag)
68{
69 BMVert *vtar[4] = {v1, v2, v3, v4};
70 return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true);
71}
72
73void BM_face_copy_shared(BMesh *bm, BMFace *f, BMLoopFilterFunc filter_fn, void *user_data)
74{
75 BMLoop *l_first;
76 BMLoop *l_iter;
77
78#ifndef NDEBUG
79 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
80 do {
82 } while ((l_iter = l_iter->next) != l_first);
83#endif
84
85 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
86 do {
87 BMLoop *l_other = l_iter->radial_next;
88
89 if (l_other && l_other != l_iter) {
90 BMLoop *l_src[2];
91 BMLoop *l_dst[2] = {l_iter, l_iter->next};
92 uint j;
93
94 if (l_other->v == l_iter->v) {
95 l_src[0] = l_other;
96 l_src[1] = l_other->next;
97 }
98 else {
99 l_src[0] = l_other->next;
100 l_src[1] = l_other;
101 }
102
103 for (j = 0; j < 2; j++) {
104 BLI_assert(l_dst[j]->v == l_src[j]->v);
105 if (BM_ELEM_API_FLAG_TEST(l_dst[j], _FLAG_OVERLAP) == 0) {
106 if ((filter_fn == nullptr) || filter_fn(l_src[j], user_data)) {
107 CustomData_bmesh_copy_block(bm->ldata, l_src[j]->head.data, &l_dst[j]->head.data);
109 }
110 }
111 }
112 }
113 } while ((l_iter = l_iter->next) != l_first);
114
115 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
116 do {
118 } while ((l_iter = l_iter->next) != l_first);
119}
120
129 BMVert *v2,
130 BMEdge **edges,
131 const int len,
132 BMEdge **edges_sort,
133 BMVert **verts_sort)
134{
135 BMEdge *e_iter, *e_first;
136 BMVert *v_iter;
137 int i;
138
139 /* all flags _must_ be cleared on exit! */
140 for (i = 0; i < len; i++) {
142 BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV);
144 }
145
146 /* find first edge */
147 i = 0;
148 v_iter = v1;
149 e_iter = e_first = v1->e;
150 do {
151 if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) && (BM_edge_other_vert(e_iter, v_iter) == v2)) {
152 i = 1;
153 break;
154 }
155 } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
156 if (i == 0) {
157 goto error;
158 }
159
160 i = 0;
161 do {
162 /* entering loop will always succeed */
163 if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) {
164 if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) {
165 /* vert is in loop multiple times */
166 goto error;
167 }
168
170 edges_sort[i] = e_iter;
171
173 verts_sort[i] = v_iter;
174
175 i += 1;
176
177 /* walk onto the next vertex */
178 v_iter = BM_edge_other_vert(e_iter, v_iter);
179 if (i == len) {
180 if (UNLIKELY(v_iter != verts_sort[0])) {
181 goto error;
182 }
183 break;
184 }
185
186 e_first = e_iter;
187 }
188 } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
189
190 if (i == len) {
191 return true;
192 }
193
194error:
195 for (i = 0; i < len; i++) {
197 BM_ELEM_API_FLAG_DISABLE(edges[i]->v1, _FLAG_MV);
199 }
200
201 return false;
202}
203
205 BMVert *v1,
206 BMVert *v2,
207 BMEdge **edges,
208 const int len,
209 const BMFace *f_example,
210 const eBMCreateFlag create_flag)
211{
212 BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
213 BMVert **verts_sort = BLI_array_alloca(verts_sort, len);
214
215 BLI_assert(len && v1 && v2 && edges && bm);
216
217 if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) {
218 return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
219 }
220
221 return nullptr;
222}
223
225 BMVert **vert_arr,
226 const int len,
227 const BMFace *f_example,
228 const eBMCreateFlag create_flag,
229 const bool calc_winding,
230 const bool create_edges)
231{
232 BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
233 uint winding[2] = {0, 0};
234 int i, i_prev = len - 1;
235 BMVert *v_winding[2] = {vert_arr[i_prev], vert_arr[0]};
236
237 BLI_assert(len > 2);
238
239 for (i = 0; i < len; i++) {
240 if (create_edges) {
241 edge_arr[i] = BM_edge_create(
242 bm, vert_arr[i_prev], vert_arr[i], nullptr, BM_CREATE_NO_DOUBLE);
243 }
244 else {
245 edge_arr[i] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
246 if (edge_arr[i] == nullptr) {
247 return nullptr;
248 }
249 }
250
251 if (calc_winding) {
252 /* the edge may exist already and be attached to a face
253 * in this case we can find the best winding to use for the new face */
254 if (edge_arr[i]->l) {
255 BMVert *test_v1, *test_v2;
256 /* we want to use the reverse winding to the existing order */
257 BM_edge_ordered_verts(edge_arr[i], &test_v2, &test_v1);
258 winding[(vert_arr[i_prev] == test_v2)]++;
259 BLI_assert(ELEM(vert_arr[i_prev], test_v2, test_v1));
260 }
261 }
262
263 i_prev = i;
264 }
265
266 /* --- */
267
268 if (calc_winding) {
269 if (winding[0] < winding[1]) {
270 winding[0] = 1;
271 winding[1] = 0;
272 }
273 else {
274 winding[0] = 0;
275 winding[1] = 1;
276 }
277 }
278 else {
279 winding[0] = 0;
280 winding[1] = 1;
281 }
282
283 /* --- */
284
285 /* create the face */
286 return BM_face_create_ngon(
287 bm, v_winding[winding[0]], v_winding[winding[1]], edge_arr, len, f_example, create_flag);
288}
289
291{
292 SortIntByFloat *vang = BLI_array_alloca(vang, len);
293 BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len);
294
295 float nor[3], cent[3];
296 int index_tangent = 0;
297 BM_verts_calc_normal_from_cloud_ex(vert_arr, len, nor, cent, &index_tangent);
298 const float *far = vert_arr[index_tangent]->co;
299
300 /* Now calculate every points angle around the normal (signed). */
301 for (int i = 0; i < len; i++) {
302 vang[i].sort_value = angle_signed_on_axis_v3v3v3_v3(far, cent, vert_arr[i]->co, nor);
303 vang[i].data = i;
304 vert_arr_map[i] = vert_arr[i];
305 }
306
307 /* sort by angle and magic! - we have our ngon */
308 qsort(vang, len, sizeof(*vang), BLI_sortutil_cmp_float);
309
310 /* --- */
311
312 for (int i = 0; i < len; i++) {
313 vert_arr[i] = vert_arr_map[vang[i].data];
314 }
315}
316
317/*************************************************************/
318
319void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMVert *src, BMVert *dst)
320{
321 BLI_assert(src != dst);
323 dst->head.hflag = (dst->head.hflag & BM_ELEM_SELECT) | (src->head.hflag & ~BM_ELEM_SELECT);
324 copy_v3_v3(dst->no, src->no);
325}
326void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMEdge *src, BMEdge *dst)
327{
328 BLI_assert(src != dst);
330 dst->head.hflag = (dst->head.hflag & BM_ELEM_SELECT) | (src->head.hflag & ~BM_ELEM_SELECT);
331}
332void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMFace *src, BMFace *dst)
333{
334 BLI_assert(src != dst);
336 dst->head.hflag = (dst->head.hflag & BM_ELEM_SELECT) | (src->head.hflag & ~BM_ELEM_SELECT);
337 copy_v3_v3(dst->no, src->no);
338 dst->mat_nr = src->mat_nr;
339}
340void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMLoop *src, BMLoop *dst)
341{
342 BLI_assert(src != dst);
344 dst->head.hflag = (dst->head.hflag & BM_ELEM_SELECT) | (src->head.hflag & ~BM_ELEM_SELECT);
345}
346
347void BM_elem_attrs_copy(BMesh *bm, const BMVert *src, BMVert *dst)
348{
349 BLI_assert(src != dst);
351 dst->head.hflag = (dst->head.hflag & BM_ELEM_SELECT) | (src->head.hflag & ~BM_ELEM_SELECT);
352 copy_v3_v3(dst->no, src->no);
353}
354void BM_elem_attrs_copy(BMesh *bm, const BMEdge *src, BMEdge *dst)
355{
356 BLI_assert(src != dst);
358 dst->head.hflag = (dst->head.hflag & BM_ELEM_SELECT) | (src->head.hflag & ~BM_ELEM_SELECT);
359}
360void BM_elem_attrs_copy(BMesh *bm, const BMFace *src, BMFace *dst)
361{
362 BLI_assert(src != dst);
364 dst->head.hflag = (dst->head.hflag & BM_ELEM_SELECT) | (src->head.hflag & ~BM_ELEM_SELECT);
365 copy_v3_v3(dst->no, src->no);
366 dst->mat_nr = src->mat_nr;
367}
368void BM_elem_attrs_copy(BMesh *bm, const BMLoop *src, BMLoop *dst)
369{
370 BLI_assert(src != dst);
372 dst->head.hflag = (dst->head.hflag & BM_ELEM_SELECT) | (src->head.hflag & ~BM_ELEM_SELECT);
373}
374
375void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v)
376{
377 BMHeader *ele_dst = static_cast<BMHeader *>(ele_dst_v);
378 const BMHeader *ele_src = static_cast<const BMHeader *>(ele_src_v);
379
380 BLI_assert(ele_src->htype == ele_dst->htype);
381
382 if ((ele_src->hflag & BM_ELEM_SELECT) != (ele_dst->hflag & BM_ELEM_SELECT)) {
383 BM_elem_select_set(bm_dst, (BMElem *)ele_dst, (ele_src->hflag & BM_ELEM_SELECT) != 0);
384 }
385}
386
387/* helper function for 'BM_mesh_copy' */
389 const BMCustomDataCopyMap &face_map,
390 const BMCustomDataCopyMap &loop_map,
391 BMVert **vtable,
392 BMEdge **etable,
393 BMFace *f)
394{
395 BMLoop **loops = BLI_array_alloca(loops, f->len);
397 BMEdge **edges = BLI_array_alloca(edges, f->len);
398
399 BMFace *f_new;
400 BMLoop *l_iter, *l_first;
401 int j;
402
403 j = 0;
404 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
405 do {
406 loops[j] = l_iter;
407 verts[j] = vtable[BM_elem_index_get(l_iter->v)];
408 edges[j] = etable[BM_elem_index_get(l_iter->e)];
409 j++;
410 } while ((l_iter = l_iter->next) != l_first);
411
412 f_new = BM_face_create(bm_new, verts, edges, f->len, nullptr, BM_CREATE_SKIP_CD);
413
414 if (UNLIKELY(f_new == nullptr)) {
415 return nullptr;
416 }
417
418 /* use totface in case adding some faces fails */
419 BM_elem_index_set(f_new, (bm_new->totface - 1)); /* set_inline */
420
421 CustomData_bmesh_copy_block(bm_new->pdata, face_map, f->head.data, &f_new->head.data);
422 copy_v3_v3(f_new->no, f->no);
423 f_new->mat_nr = f->mat_nr;
424 f_new->head.hflag = f->head.hflag; /* low level! don't do this for normal api use */
425
426 j = 0;
427 l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
428 do {
429 CustomData_bmesh_copy_block(bm_new->ldata, loop_map, loops[j]->head.data, &l_iter->head.data);
430 l_iter->head.hflag = loops[j]->head.hflag & ~BM_ELEM_SELECT;
431 j++;
432 } while ((l_iter = l_iter->next) != l_first);
433
434 return f_new;
435}
436
438 const Mesh *me_src_array[],
439 const int me_src_array_len,
440 const BMAllocTemplate *allocsize)
441
442{
443 if (allocsize == nullptr) {
444 allocsize = &bm_mesh_allocsize_default;
445 }
446
447 for (int i = 0; i < me_src_array_len; i++) {
448 const Mesh *me_src = me_src_array[i];
450 &me_src->vert_data, CD_MASK_BMESH.vmask);
452 &me_src->edge_data, CD_MASK_BMESH.emask);
454 &me_src->face_data, CD_MASK_BMESH.pmask);
457
458 if (i == 0) {
460 &mesh_vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
462 &mesh_edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
464 &mesh_pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
466 &mesh_ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
467 }
468 else {
473 }
474
475 MEM_SAFE_FREE(mesh_vdata.layers);
476 MEM_SAFE_FREE(mesh_edata.layers);
477 MEM_SAFE_FREE(mesh_pdata.layers);
478 MEM_SAFE_FREE(mesh_ldata.layers);
479 }
480
481 CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
482 CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
483 CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
484 CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
485}
486
488 const Mesh *me_src,
489 const BMAllocTemplate *allocsize)
490{
491 BM_mesh_copy_init_customdata_from_mesh_array(bm_dst, &me_src, 1, allocsize);
492}
493
494void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
495{
496 if (allocsize == nullptr) {
497 allocsize = &bm_mesh_allocsize_default;
498 }
499
501 &bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_SET_DEFAULT, 0);
503 &bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_SET_DEFAULT, 0);
505 &bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_SET_DEFAULT, 0);
507 &bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_SET_DEFAULT, 0);
508
509 CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
510 CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
511 CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
512 CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
513}
514
516 BMesh *bm_src,
517 const char htype,
518 const BMAllocTemplate *allocsize)
519{
520 if (allocsize == nullptr) {
521 allocsize = &bm_mesh_allocsize_default;
522 }
523
524 const char htypes[4] = {BM_VERT, BM_EDGE, BM_LOOP, BM_FACE};
525 BLI_assert(((&bm_dst->vdata + 1) == &bm_dst->edata) &&
526 ((&bm_dst->vdata + 2) == &bm_dst->ldata) && ((&bm_dst->vdata + 3) == &bm_dst->pdata));
527
528 BLI_assert(((&allocsize->totvert + 1) == &allocsize->totedge) &&
529 ((&allocsize->totvert + 2) == &allocsize->totloop) &&
530 ((&allocsize->totvert + 3) == &allocsize->totface));
531
532 for (int i = 0; i < 4; i++) {
533 if (!(htypes[i] & htype)) {
534 continue;
535 }
536 CustomData *dst = &bm_dst->vdata + i;
537 CustomData *src = &bm_src->vdata + i;
538 const int size = *(&allocsize->totvert + i);
539
540 for (int l = 0; l < src->totlayer; l++) {
542 dst, eCustomDataType(src->layers[l].type), CD_SET_DEFAULT, 0, src->layers[l].name);
543 }
544 CustomData_bmesh_init_pool(dst, size, htypes[i]);
545 }
546}
547
549{
550 BMesh *bm_new;
551 BMVert *v, *v_new, **vtable = nullptr;
552 BMEdge *e, *e_new, **etable = nullptr;
553 BMFace *f, *f_new, **ftable = nullptr;
554 BMElem **eletable;
555 BMIter iter;
556 int i;
557 const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm_old);
558
559 /* allocate a bmesh */
561 params.use_toolflags = bm_old->use_toolflags;
562 bm_new = BM_mesh_create(&allocsize, &params);
563
564 BM_mesh_copy_init_customdata(bm_new, bm_old, &allocsize);
565
567 bm_new->vdata);
569 bm_new->edata);
571 bm_new->pdata);
573 bm_new->ldata);
574
575 vtable = static_cast<BMVert **>(
576 MEM_mallocN(sizeof(BMVert *) * bm_old->totvert, "BM_mesh_copy vtable"));
577 etable = static_cast<BMEdge **>(
578 MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable"));
579 ftable = static_cast<BMFace **>(
580 MEM_mallocN(sizeof(BMFace *) * bm_old->totface, "BM_mesh_copy ftable"));
581
582 BM_ITER_MESH_INDEX (v, &iter, bm_old, BM_VERTS_OF_MESH, i) {
583 /* copy between meshes so can't use 'example' argument */
584 v_new = BM_vert_create(bm_new, v->co, nullptr, BM_CREATE_SKIP_CD);
585 CustomData_bmesh_copy_block(bm_new->vdata, vert_map, v->head.data, &v_new->head.data);
586 copy_v3_v3(v_new->no, v->no);
587 v_new->head.hflag = v->head.hflag; /* low level! don't do this for normal api use */
588 vtable[i] = v_new;
589 BM_elem_index_set(v, i); /* set_inline */
590 BM_elem_index_set(v_new, i); /* set_inline */
591 }
592 bm_old->elem_index_dirty &= ~BM_VERT;
593 bm_new->elem_index_dirty &= ~BM_VERT;
594
595 /* safety check */
596 BLI_assert(i == bm_old->totvert);
597
598 BM_ITER_MESH_INDEX (e, &iter, bm_old, BM_EDGES_OF_MESH, i) {
599 e_new = BM_edge_create(bm_new,
600 vtable[BM_elem_index_get(e->v1)],
601 vtable[BM_elem_index_get(e->v2)],
602 e,
604
605 CustomData_bmesh_copy_block(bm_new->edata, edge_map, e->head.data, &e_new->head.data);
606 e_new->head.hflag = e->head.hflag; /* low level! don't do this for normal api use */
607 etable[i] = e_new;
608 BM_elem_index_set(e, i); /* set_inline */
609 BM_elem_index_set(e_new, i); /* set_inline */
610 }
611 bm_old->elem_index_dirty &= ~BM_EDGE;
612 bm_new->elem_index_dirty &= ~BM_EDGE;
613
614 /* safety check */
615 BLI_assert(i == bm_old->totedge);
616
617 BM_ITER_MESH_INDEX (f, &iter, bm_old, BM_FACES_OF_MESH, i) {
618 BM_elem_index_set(f, i); /* set_inline */
619
620 f_new = bm_mesh_copy_new_face(bm_new, face_map, loop_map, vtable, etable, f);
621
622 ftable[i] = f_new;
623
624 if (f == bm_old->act_face) {
625 bm_new->act_face = f_new;
626 }
627 }
628 bm_old->elem_index_dirty &= ~BM_FACE;
629 bm_new->elem_index_dirty &= ~BM_FACE;
630
631 /* low level! don't do this for normal api use */
632 bm_new->totvertsel = bm_old->totvertsel;
633 bm_new->totedgesel = bm_old->totedgesel;
634 bm_new->totfacesel = bm_old->totfacesel;
635
636 /* safety check */
637 BLI_assert(i == bm_old->totface);
638
639 /* copy over edit selection history */
640 LISTBASE_FOREACH (BMEditSelection *, ese, &bm_old->selected) {
641 BMElem *ele = nullptr;
642
643 switch (ese->htype) {
644 case BM_VERT:
645 eletable = (BMElem **)vtable;
646 break;
647 case BM_EDGE:
648 eletable = (BMElem **)etable;
649 break;
650 case BM_FACE:
651 eletable = (BMElem **)ftable;
652 break;
653 default:
654 eletable = nullptr;
655 break;
656 }
657
658 if (eletable) {
659 ele = eletable[BM_elem_index_get(ese->ele)];
660 if (ele) {
661 BM_select_history_store(bm_new, ele);
662 }
663 }
664 }
665
666 MEM_freeN(etable);
667 MEM_freeN(vtable);
668 MEM_freeN(ftable);
669
670 /* Copy various settings. */
671 bm_new->shapenr = bm_old->shapenr;
672 bm_new->selectmode = bm_old->selectmode;
673
674 return bm_new;
675}
CustomData interface, see also DNA_customdata_types.h.
@ CD_SET_DEFAULT
void * CustomData_add_layer_named(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem, blender::StringRef name)
BMCustomDataCopyMap CustomData_bmesh_copy_map_calc(const CustomData &src, const CustomData &dst, eCustomDataMask mask_exclude=0)
void CustomData_bmesh_init_pool(CustomData *data, int totelem, char htype)
const CustomData_MeshMasks CD_MASK_BMESH
void CustomData_bmesh_copy_block(CustomData &data, void *src_block, void **dst_block)
void CustomData_init_layout_from(const CustomData *source, CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src, eCustomDataMask mask)
bool CustomData_merge_layout(const CustomData *source, CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
#define BLI_array_alloca(arr, realsize)
Definition BLI_alloca.h:25
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
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
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:25
unsigned int uint
#define UNLIKELY(x)
#define ELEM(...)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
@ BM_LOOP
bool(* BMLoopFilterFunc)(const BMLoop *, void *user_data)
@ BM_ELEM_SELECT
#define BM_FACE_FIRST_LOOP(p)
void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
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_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v)
void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMVert *src, BMVert *dst)
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)
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_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len)
static BMFace * bm_mesh_copy_new_face(BMesh *bm_new, const BMCustomDataCopyMap &face_map, const BMCustomDataCopyMap &loop_map, BMVert **vtable, BMEdge **etable, BMFace *f)
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.
void BM_mesh_copy_init_customdata_all_layers(BMesh *bm_dst, BMesh *bm_src, const char htype, const BMAllocTemplate *allocsize)
BMesh * BM_mesh_copy(BMesh *bm_old)
bool BM_edges_from_verts(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.
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)
BMFace * BM_face_create(BMesh *bm, BMVert *const *verts, BMEdge *const *edges, const int len, const BMFace *f_example, const eBMCreateFlag create_flag)
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.cc:43
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.
eBMCreateFlag
Definition bmesh_core.hh:23
@ BM_CREATE_SKIP_CD
Definition bmesh_core.hh:32
@ BM_CREATE_NO_DOUBLE
Definition bmesh_core.hh:26
#define BM_elem_index_get(ele)
#define BM_elem_index_set(ele, index)
#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:29
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const BMeshCreateParams *params)
BMesh Make Mesh.
#define BMALLOC_TEMPLATE_FROM_BM(bm)
#define BM_FACE
#define BM_EDGE
#define BM_VERT
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)
#define BM_ELEM_API_FLAG_TEST(element, f)
@ _FLAG_MV
@ _FLAG_MF
@ _FLAG_OVERLAP
#define BM_ELEM_API_FLAG_ENABLE(element, f)
BMVert * BM_edge_share_vert(BMEdge *e1, BMEdge *e2)
void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) 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()
int len
static float verts[][3]
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
static void error(const char *str)
Frequency::GEOMETRY nor[]
BMHeader head
short mat_nr
BMHeader head
float no[3]
void * data
BMHeader head
struct BMVert * v
struct BMEdge * e
struct BMLoop * radial_next
struct BMLoop * next
float co[3]
struct BMEdge * e
float no[3]
BMHeader head
int totvert
int totfacesel
int shapenr
char elem_index_dirty
CustomData vdata
int totedge
ListBase selected
CustomData edata
uint use_toolflags
int totvertsel
BMFace * act_face
short selectmode
int totedgesel
CustomData pdata
CustomData ldata
int totface
CustomDataLayer * layers
CustomData edge_data
CustomData corner_data
CustomData face_data
CustomData vert_data