2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Contributor(s): Joseph Eagar, Geoffrey Bantle, Campbell Barton
20 * ***** END GPL LICENSE BLOCK *****
23 /** \file blender/bmesh/intern/bmesh_newcore.c
28 #include "MEM_guardedalloc.h"
30 #include "BLI_math_vector.h"
32 #include "BKE_DerivedMesh.h"
34 #include "BLI_listbase.h"
35 #include "BLI_array.h"
38 #include "bmesh_private.h"
40 /* use so valgrinds memcheck alerts us when undefined index is used.
42 // #define USE_DEBUG_INDEX_MEMCHECK
44 #ifdef USE_DEBUG_INDEX_MEMCHECK
45 #define DEBUG_MEMCHECK_INDEX_INVALIDATE(ele) \
48 BM_elem_index_set(ele, undef_idx); /* set_ok_invalid */ \
53 BMVert *BM_vert_create(BMesh *bm, const float co[3], const struct BMVert *example)
55 BMVert *v = BLI_mempool_calloc(bm->vpool);
57 #ifdef USE_DEBUG_INDEX_MEMCHECK
58 DEBUG_MEMCHECK_INDEX_INVALIDATE(v)
60 BM_elem_index_set(v, -1); /* set_ok_invalid */
63 bm->elem_index_dirty |= BM_VERT; /* may add to middle of the pool */
67 v->head.htype = BM_VERT;
69 /* 'v->no' is handled by BM_elem_attrs_copy */
70 if (co) copy_v3_v3(v->co, co);
73 v->oflags = BLI_mempool_calloc(bm->toolflagpool);
75 CustomData_bmesh_set_default(&bm->vdata, &v->head.data);
78 BM_elem_attrs_copy(bm, bm, (BMVert *)example, v);
81 BM_CHECK_ELEMENT(bm, v);
89 * Finds out if two vertices already have an edge
90 * connecting them. Note that multiple edges may
91 * exist between any two vertices, and therefore
92 * This function only returns the first one found.
97 BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2)
102 BM_ITER(e, &iter, NULL, BM_EDGES_OF_VERT, v1) {
103 if (e->v1 == v2 || e->v2 == v2)
110 BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble)
114 if (nodouble && (e = BM_edge_exists(v1, v2)))
117 e = BLI_mempool_calloc(bm->epool);
119 #ifdef USE_DEBUG_INDEX_MEMCHECK
120 DEBUG_MEMCHECK_INDEX_INVALIDATE(e)
122 BM_elem_index_set(e, -1); /* set_ok_invalid */
125 bm->elem_index_dirty |= BM_EDGE; /* may add to middle of the pool */
129 e->head.htype = BM_EDGE;
132 e->oflags = BLI_mempool_calloc(bm->toolflagpool);
134 e->v1 = (BMVert *) v1;
135 e->v2 = (BMVert *) v2;
137 BM_elem_flag_enable(e, BM_ELEM_SMOOTH);
139 CustomData_bmesh_set_default(&bm->edata, &e->head.data);
141 bmesh_disk_append_edge(e, e->v1);
142 bmesh_disk_append_edge(e, e->v2);
145 BM_elem_attrs_copy(bm, bm, (BMEdge *)example, (BMEdge *)e);
147 BM_CHECK_ELEMENT(bm, e);
152 static BMLoop *bmesh_create_loop(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, const BMLoop *example)
156 l = BLI_mempool_calloc(bm->lpool);
157 l->next = l->prev = NULL;
161 l->radial_next = l->radial_prev = NULL;
163 l->head.htype = BM_LOOP;
168 CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data);
170 CustomData_bmesh_set_default(&bm->ldata, &l->head.data);
175 static BMLoop *bm_face_boundry_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte)
177 #ifdef USE_BMESH_HOLES
178 BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool);
180 BMLoop *l = bmesh_create_loop(bm, startv, starte, f, NULL);
182 bmesh_radial_append(starte, l);
184 #ifdef USE_BMESH_HOLES
185 lst->first = lst->last = l;
186 BLI_addtail(&f->loops, lst);
196 BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges)
198 BMEdge **edges = NULL;
199 BMVert **verts = NULL;
200 BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE);
201 BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE);
208 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
211 BMVert *v = BM_vert_create(bm, l_iter->v->co, l_iter->v);
212 BLI_array_append(verts, v);
215 BLI_array_append(verts, l_iter->v);
217 } while ((l_iter = l_iter->next) != l_first);
219 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
226 if (l_iter->e->v1 == verts[i]) {
228 v2 = verts[(i + 1) % f->len];
232 v1 = verts[(i + 1) % f->len];
235 e = BM_edge_create(bm, v1, v2, l_iter->e, FALSE);
236 BLI_array_append(edges, e);
239 BLI_array_append(edges, l_iter->e);
243 } while ((l_iter = l_iter->next) != l_first);
245 f2 = BM_face_create(bm, verts, edges, f->len, FALSE);
247 BM_elem_attrs_copy(bm, bm, f, f2);
249 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
250 l2 = BM_FACE_FIRST_LOOP(f2);
252 BM_elem_attrs_copy(bm, bm, l_iter, l2);
254 } while ((l_iter = l_iter->next) != l_first);
259 BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble)
262 BMLoop *l, *startl, *lastl;
266 /* just return NULL for no */
271 /* Check if face already exists */
272 overlap = BM_face_exists(bm, verts, len, &f);
277 BLI_assert(f == NULL);
281 f = BLI_mempool_calloc(bm->fpool);
283 #ifdef USE_DEBUG_INDEX_MEMCHECK
284 DEBUG_MEMCHECK_INDEX_INVALIDATE(f)
286 BM_elem_index_set(f, -1); /* set_ok_invalid */
289 bm->elem_index_dirty |= BM_FACE; /* may add to middle of the pool */
293 f->head.htype = BM_FACE;
295 startl = lastl = bm_face_boundry_add(bm, (BMFace *)f, verts[0], edges[0]);
297 startl->v = (BMVert *)verts[0];
298 startl->e = (BMEdge *)edges[0];
299 for (i = 1; i < len; i++) {
300 l = bmesh_create_loop(bm, verts[i], edges[i], (BMFace *)f, edges[i]->l);
303 bmesh_radial_append(edges[i], l);
311 f->oflags = BLI_mempool_calloc(bm->toolflagpool);
313 CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
315 startl->prev = lastl;
316 lastl->next = startl;
320 #ifdef USE_BMESH_HOLES
324 BM_CHECK_ELEMENT(bm, f);
329 int bmesh_check_element(BMesh *UNUSED(bm), void *element, const char htype)
331 BMHeader *head = element;
337 if (head->htype != htype)
343 if (v->e && v->e->head.htype != BM_EDGE) {
350 if (e->l && e->l->head.htype != BM_LOOP)
352 if (e->l && e->l->f->head.htype != BM_FACE)
354 if (e->v1_disk_link.prev == NULL ||
355 e->v2_disk_link.prev == NULL ||
356 e->v1_disk_link.next == NULL ||
357 e->v2_disk_link.next == NULL)
361 if (e->l && (e->l->radial_next == NULL || e->l->radial_prev == NULL))
363 if (e->l && e->l->f->len <= 0)
368 BMLoop *l = element, *l2;
371 if (l->f->head.htype != BM_FACE)
373 if (l->e->head.htype != BM_EDGE)
375 if (l->v->head.htype != BM_VERT)
377 if (!BM_vert_in_edge(l->e, l->v)) {
378 fprintf(stderr, "%s: fatal bmesh error (vert not in edge)! (bmesh internal error)\n", __func__);
382 if (l->radial_next == NULL || l->radial_prev == NULL)
387 /* validate boundary loop--invalid for hole loops, of course,
388 * but we won't be allowing those for a while ye */
392 if (i >= BM_NGON_MAX) {
397 } while ((l2 = l2->next) != l);
399 if (i != l->f->len || l2 != l)
402 if (!bmesh_radial_validate(bmesh_radial_length(l), l))
413 #ifdef USE_BMESH_HOLES
421 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
423 if (l_iter->f != f) {
424 fprintf(stderr, "%s: loop inside one face points to another! (bmesh internal error)\n", __func__);
432 if (!BM_vert_in_edge(l_iter->e, l_iter->v) || !BM_vert_in_edge(l_iter->e, l_iter->next->v)) {
436 if (!bmesh_radial_validate(bmesh_radial_length(l_iter), l_iter))
439 if (!bmesh_disk_count(l_iter->v) || !bmesh_disk_count(l_iter->next->v))
443 } while ((l_iter = l_iter->next) != l_first);
457 /* low level function, only free's,
458 * does not change adjust surrounding geometry */
459 static void bmesh_kill_only_vert(BMesh *bm, BMVert *v)
462 bm->elem_index_dirty |= BM_VERT;
464 BM_select_history_remove(bm, v);
466 CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
468 BLI_mempool_free(bm->toolflagpool, v->oflags);
469 BLI_mempool_free(bm->vpool, v);
472 static void bmesh_kill_only_edge(BMesh *bm, BMEdge *e)
475 bm->elem_index_dirty |= BM_EDGE;
477 BM_select_history_remove(bm, e);
480 CustomData_bmesh_free_block(&bm->edata, &e->head.data);
482 BLI_mempool_free(bm->toolflagpool, e->oflags);
483 BLI_mempool_free(bm->epool, e);
486 static void bmesh_kill_only_face(BMesh *bm, BMFace *f)
488 if (bm->act_face == f)
492 bm->elem_index_dirty |= BM_FACE;
494 BM_select_history_remove(bm, f);
497 CustomData_bmesh_free_block(&bm->pdata, &f->head.data);
499 BLI_mempool_free(bm->toolflagpool, f->oflags);
500 BLI_mempool_free(bm->fpool, f);
503 static void bmesh_kill_only_loop(BMesh *bm, BMLoop *l)
507 CustomData_bmesh_free_block(&bm->ldata, &l->head.data);
509 BLI_mempool_free(bm->lpool, l);
512 void BM_face_edges_kill(BMesh *bm, BMFace *f)
514 BMEdge **edges = NULL;
515 BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE);
520 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
522 BLI_array_append(edges, l_iter->e);
523 } while ((l_iter = l_iter->next) != l_first);
525 for (i = 0; i < BLI_array_count(edges); i++) {
526 BM_edge_kill(bm, edges[i]);
529 BLI_array_free(edges);
532 void BM_face_verts_kill(BMesh *bm, BMFace *f)
534 BMVert **verts = NULL;
535 BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE);
540 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
542 BLI_array_append(verts, l_iter->v);
543 } while ((l_iter = l_iter->next) != l_first);
545 for (i = 0; i < BLI_array_count(verts); i++) {
546 BM_vert_kill(bm, verts[i]);
549 BLI_array_free(verts);
552 void BM_face_kill(BMesh *bm, BMFace *f)
554 #ifdef USE_BMESH_HOLES
555 BMLoopList *ls, *ls_next;
558 BM_CHECK_ELEMENT(bm, f);
560 #ifdef USE_BMESH_HOLES
561 for (ls = f->loops.first; ls; ls = ls_next)
566 BMLoop *l_iter, *l_next, *l_first;
568 #ifdef USE_BMESH_HOLES
570 l_iter = l_first = ls->first;
572 l_iter = l_first = f->l_first;
576 l_next = l_iter->next;
578 bmesh_radial_remove_loop(l_iter, l_iter->e);
579 bmesh_kill_only_loop(bm, l_iter);
581 } while ((l_iter = l_next) != l_first);
583 #ifdef USE_BMESH_HOLES
584 BLI_mempool_free(bm->looplistpool, ls);
588 bmesh_kill_only_face(bm, f);
591 void BM_edge_kill(BMesh *bm, BMEdge *e)
594 bmesh_disk_remove_edge(e, e->v1);
595 bmesh_disk_remove_edge(e, e->v2);
598 BMLoop *l = e->l, *lnext, *startl = e->l;
601 lnext = l->radial_next;
602 if (lnext->f == l->f) {
603 BM_face_kill(bm, l->f);
607 BM_face_kill(bm, l->f);
612 } while (l != startl);
615 bmesh_kill_only_edge(bm, e);
618 void BM_vert_kill(BMesh *bm, BMVert *v)
625 nexte = bmesh_disk_nextedge(e, v);
631 bmesh_kill_only_vert(bm, v);
634 /********** private disk and radial cycle functions ********** */
641 * Changes the winding order of a face from CW to CCW or vice versa.
642 * This euler is a bit peculiar in compairson to others as it is its
645 * BMESH_TODO: reinsert validation code.
648 * 1 for success, 0 for failure.
651 static int bmesh_loop_length(BMLoop *l)
658 } while ((l = l->next) != l_first);
663 static int bmesh_loop_reverse_loop(BMesh *bm, BMFace *f
664 #ifdef USE_BMESH_HOLES
670 #ifdef USE_BMESH_HOLES
671 BMLoop *l_first = lst->first;
673 BMLoop *l_first = f->l_first;
676 BMLoop *l_iter, *oldprev, *oldnext;
677 BMEdge **edar = NULL;
679 BLI_array_staticdeclare(edar, BM_NGON_STACK_SIZE);
680 int i, j, edok, len = 0, do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS);
682 len = bmesh_loop_length(l_first);
684 for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) {
685 BMEdge *curedge = l_iter->e;
686 bmesh_radial_remove_loop(l_iter, curedge);
687 BLI_array_append(edar, curedge);
690 /* actually reverse the loop */
691 for (i = 0, l_iter = l_first; i < len; i++) {
692 oldnext = l_iter->next;
693 oldprev = l_iter->prev;
694 l_iter->next = oldprev;
695 l_iter->prev = oldnext;
702 md = CustomData_bmesh_get(&bm->ldata, l_iter->head.data, CD_MDISPS);
703 if (!md->totdisp || !md->disps)
706 sides = (int)sqrt(md->totdisp);
709 for (x = 0; x < sides; x++) {
710 for (y = 0; y < x; y++) {
711 swap_v3_v3(co[y * sides + x], co[sides * x + y]);
717 if (len == 2) { /* two edged face */
718 /* do some verification here! */
719 l_first->e = edar[1];
720 l_first->next->e = edar[0];
723 for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) {
725 for (j = 0; j < len; j++) {
726 edok = bmesh_verts_in_edge(l_iter->v, l_iter->next->v, edar[j]);
735 for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next)
736 bmesh_radial_append(l_iter->e, l_iter);
739 for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) {
740 BM_CHECK_ELEMENT(bm, l_iter);
741 BM_CHECK_ELEMENT(bm, l_iter->e);
742 BM_CHECK_ELEMENT(bm, l_iter->v);
743 BM_CHECK_ELEMENT(bm, l_iter->f);
746 BLI_array_free(edar);
748 BM_CHECK_ELEMENT(bm, f);
753 int bmesh_loop_reverse(BMesh *bm, BMFace *f)
755 #ifdef USE_BMESH_HOLES
756 return bmesh_loop_reverse_loop(bm, f, f->loops.first);
758 return bmesh_loop_reverse_loop(bm, f);
762 static void bmesh_systag_elements(BMesh *UNUSED(bm), void *veles, int tot, int flag)
764 BMHeader **eles = veles;
767 for (i = 0; i < tot; i++) {
768 BM_ELEM_API_FLAG_ENABLE((BMElemF *)eles[i], flag);
772 static void bmesh_clear_systag_elements(BMesh *UNUSED(bm), void *veles, int tot, int flag)
774 BMHeader **eles = veles;
777 for (i = 0; i < tot; i++) {
778 BM_ELEM_API_FLAG_DISABLE((BMElemF *)eles[i], flag);
782 #define FACE_MARK (1 << 10)
784 static int count_flagged_radial(BMesh *bm, BMLoop *l, int flag)
795 i += BM_ELEM_API_FLAG_TEST(l2->f, flag) ? 1 : 0;
796 l2 = bmesh_radial_nextloop(l2);
797 if (c >= BM_LOOP_RADIAL_MAX) {
807 BMO_error_raise(bm, bm->currentop, BMERR_MESH_ERROR, NULL);
811 static int UNUSED_FUNCTION(count_flagged_disk)(BMVert *v, int flag)
820 i += BM_ELEM_API_FLAG_TEST(e, flag) ? 1 : 0;
821 e = bmesh_disk_nextedge(e, v);
827 static int disk_is_flagged(BMVert *v, int flag)
841 if (bmesh_radial_length(l) == 1)
845 if (!BM_ELEM_API_FLAG_TEST(l->f, flag))
851 e = bmesh_disk_nextedge(e, v);
857 /* Midlevel Topology Manipulation Functions */
862 * Joins a collected group of faces into one. Only restriction on
863 * the input data is that the faces must be connected to each other.
865 * If a pair of faces share multiple edges, the pair of
866 * faces will be joined at every edge.
868 * Returns a pointer to the combined face.
870 BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface)
873 #ifdef USE_BMESH_HOLES
875 ListBase holes = {NULL, NULL};
879 BMEdge **edges = NULL;
880 BMEdge **deledges = NULL;
881 BMVert **delverts = NULL;
882 BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE);
883 BLI_array_staticdeclare(deledges, BM_NGON_STACK_SIZE);
884 BLI_array_staticdeclare(delverts, BM_NGON_STACK_SIZE);
885 BMVert *v1 = NULL, *v2 = NULL;
886 const char *err = NULL;
897 bmesh_systag_elements(bm, faces, totface, _FLAG_JF);
899 for (i = 0; i < totface; i++) {
901 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
903 int rlen = count_flagged_radial(bm, l_iter, _FLAG_JF);
906 err = "Input faces do not form a contiguous manifold region";
909 else if (rlen == 1) {
910 BLI_array_append(edges, l_iter->e);
914 v2 = BM_edge_other_vert(l_iter->e, l_iter->v);
918 else if (rlen == 2) {
921 d1 = disk_is_flagged(l_iter->e->v1, _FLAG_JF);
922 d2 = disk_is_flagged(l_iter->e->v2, _FLAG_JF);
924 if (!d1 && !d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_JF)) {
925 /* don't remove an edge it makes up the side of another face
926 * else this will remove the face as well - campbell */
927 if (BM_edge_face_count(l_iter->e) <= 2) {
928 BLI_array_append(deledges, l_iter->e);
929 BM_ELEM_API_FLAG_ENABLE(l_iter->e, _FLAG_JF);
933 if (d1 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v1, _FLAG_JF)) {
934 BLI_array_append(delverts, l_iter->e->v1);
935 BM_ELEM_API_FLAG_ENABLE(l_iter->e->v1, _FLAG_JF);
938 if (d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v2, _FLAG_JF)) {
939 BLI_array_append(delverts, l_iter->e->v2);
940 BM_ELEM_API_FLAG_ENABLE(l_iter->e->v2, _FLAG_JF);
944 } while ((l_iter = l_iter->next) != l_first);
946 #ifdef USE_BMESH_HOLES
947 for (lst = f->loops.first; lst; lst = lst->next) {
948 if (lst == f->loops.first) continue;
950 BLI_remlink(&f->loops, lst);
951 BLI_addtail(&holes, lst);
957 /* create region fac */
958 newf = BM_face_create_ngon(bm, v1, v2, edges, tote, FALSE);
959 if (!newf || BMO_error_occurred(bm)) {
960 if (!BMO_error_occurred(bm))
961 err = "Invalid boundary region to join faces";
965 /* copy over loop data */
966 l_iter = l_first = BM_FACE_FIRST_LOOP(newf);
968 BMLoop *l2 = l_iter->radial_next;
971 if (BM_ELEM_API_FLAG_TEST(l2->f, _FLAG_JF))
973 l2 = l2->radial_next;
974 } while (l2 != l_iter);
977 /* I think this is correct */
978 if (l2->v != l_iter->v) {
982 BM_elem_attrs_copy(bm, bm, l2, l_iter);
984 } while ((l_iter = l_iter->next) != l_first);
986 BM_elem_attrs_copy(bm, bm, faces[0], newf);
988 #ifdef USE_BMESH_HOLES
990 BLI_movelisttolist(&newf->loops, &holes);
993 /* update loop face pointer */
994 #ifdef USE_BMESH_HOLES
995 for (lst = newf->loops.first; lst; lst = lst->next)
998 #ifdef USE_BMESH_HOLES
999 l_iter = l_first = lst->first;
1001 l_iter = l_first = BM_FACE_FIRST_LOOP(newf);
1005 } while ((l_iter = l_iter->next) != l_first);
1008 bmesh_clear_systag_elements(bm, faces, totface, _FLAG_JF);
1009 BM_ELEM_API_FLAG_DISABLE(newf, _FLAG_JF);
1011 /* handle multires data */
1012 if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
1013 l_iter = l_first = BM_FACE_FIRST_LOOP(newf);
1015 for (i = 0; i < totface; i++) {
1016 BM_loop_interp_multires(bm, l_iter, faces[i]);
1018 } while ((l_iter = l_iter->next) != l_first);
1021 /* delete old geometr */
1022 for (i = 0; i < BLI_array_count(deledges); i++) {
1023 BM_edge_kill(bm, deledges[i]);
1026 for (i = 0; i < BLI_array_count(delverts); i++) {
1027 BM_vert_kill(bm, delverts[i]);
1030 BLI_array_free(edges);
1031 BLI_array_free(deledges);
1032 BLI_array_free(delverts);
1034 BM_CHECK_ELEMENT(bm, newf);
1037 bmesh_clear_systag_elements(bm, faces, totface, _FLAG_JF);
1038 BLI_array_free(edges);
1039 BLI_array_free(deledges);
1040 BLI_array_free(delverts);
1043 BMO_error_raise(bm, bm->currentop, BMERR_DISSOLVEFACES_FAILED, err);
1048 static BMFace *bmesh_addpolylist(BMesh *bm, BMFace *UNUSED(example))
1051 #ifdef USE_BMESH_HOLES
1055 f = BLI_mempool_calloc(bm->fpool);
1056 #ifdef USE_BMESH_HOLES
1057 lst = BLI_mempool_calloc(bm->looplistpool);
1060 f->head.htype = BM_FACE;
1061 #ifdef USE_BMESH_HOLES
1062 BLI_addtail(&f->loops, lst);
1065 #ifdef USE_DEBUG_INDEX_MEMCHECK
1066 DEBUG_MEMCHECK_INDEX_INVALIDATE(f)
1068 BM_elem_index_set(f, -1); /* set_ok_invalid */
1071 bm->elem_index_dirty |= BM_FACE; /* may add to middle of the pool */
1076 f->oflags = BLI_mempool_calloc(bm->toolflagpool);
1078 CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
1082 #ifdef USE_BMESH_HOLES
1086 return (BMFace *) f;
1092 * SPLIT FACE MAKE EDGE:
1094 * Takes as input two vertices in a single face. An edge is created which divides the original face
1095 * into two distinct regions. One of the regions is assigned to the original face and it is closed off.
1096 * The second region has a new face assigned to it.
1101 * ---------- ----------
1104 * v1 f1 v2 v1======v2
1107 * ---------- ----------
1109 * Note that the input vertices can be part of the same edge. This will
1110 * result in a two edged face. This is desirable for advanced construction
1111 * tools and particularly essential for edge bevel. Because of this it is
1112 * up to the caller to decide what to do with the extra edge.
1114 * If holes is NULL, then both faces will lose
1115 * all holes from the original face. Also, you cannot split between
1116 * a hole vert and a boundary vert; that case is handled by higher-
1117 * level wrapping functions (when holes are fully implemented, anyway).
1119 * Note that holes represents which holes goes to the new face, and of
1120 * course this requires removing them from the exitsing face first, since
1121 * you cannot have linked list links inside multiple lists.
1126 BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
1128 #ifdef USE_BMESH_HOLES
1134 #ifdef USE_BMESH_HOLES
1135 BMLoopList *lst, *lst2;
1139 BMLoop *l_iter, *l_first;
1140 BMLoop *v1loop = NULL, *v2loop = NULL, *f1loop = NULL, *f2loop = NULL;
1142 int i, len, f1len, f2len;
1144 /* verify that v1 and v2 are in face */
1146 for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < len; i++, l_iter = l_iter->next) {
1147 if (l_iter->v == v1) v1loop = l_iter;
1148 else if (l_iter->v == v2) v2loop = l_iter;
1151 if (!v1loop || !v2loop) {
1155 /* allocate new edge between v1 and v2 */
1156 e = BM_edge_create(bm, v1, v2, example, FALSE);
1158 f2 = bmesh_addpolylist(bm, f);
1159 f1loop = bmesh_create_loop(bm, v2, e, f, v2loop);
1160 f2loop = bmesh_create_loop(bm, v1, e, f2, v1loop);
1162 f1loop->prev = v2loop->prev;
1163 f2loop->prev = v1loop->prev;
1164 v2loop->prev->next = f1loop;
1165 v1loop->prev->next = f2loop;
1167 f1loop->next = v1loop;
1168 f2loop->next = v2loop;
1169 v1loop->prev = f1loop;
1170 v2loop->prev = f2loop;
1172 #ifdef USE_BMESH_HOLES
1173 lst = f->loops.first;
1174 lst2 = f2->loops.first;
1176 lst2->first = lst2->last = f2loop;
1177 lst->first = lst->last = f1loop;
1179 f2->l_first = f2loop;
1180 f->l_first = f1loop;
1183 /* validate both loop */
1184 /* I dont know how many loops are supposed to be in each face at this point! FIXME */
1186 /* go through all of f2's loops and make sure they point to it properly */
1187 l_iter = l_first = BM_FACE_FIRST_LOOP(f2);
1192 } while ((l_iter = l_iter->next) != l_first);
1194 /* link up the new loops into the new edges radia */
1195 bmesh_radial_append(e, f1loop);
1196 bmesh_radial_append(e, f2loop);
1201 l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1204 } while ((l_iter = l_iter->next) != l_first);
1208 if (rl) *rl = f2loop;
1210 #ifdef USE_BMESH_HOLES
1212 BLI_movelisttolist(&f2->loops, holes);
1215 /* this code is not significant until holes actually work */
1216 //printf("warning: call to split face euler without holes argument; holes will be tossed.\n");
1217 for (lst = f->loops.last; lst != f->loops.first; lst = lst2) {
1219 BLI_mempool_free(bm->looplistpool, lst);
1224 BM_CHECK_ELEMENT(bm, e);
1225 BM_CHECK_ELEMENT(bm, f);
1226 BM_CHECK_ELEMENT(bm, f2);
1234 * SPLIT EDGE MAKE VERT:
1235 * Takes a given edge and splits it into two, creating a new vert.
1238 * Before: OV---------TV
1239 * After: OV----NV---TV
1246 BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **re)
1251 int i, edok, valence1 = 0, valence2 = 0;
1253 if (bmesh_vert_in_edge(e, tv) == 0) {
1256 ov = bmesh_edge_getothervert(e, tv);
1258 /* count valence of v1 */
1259 valence1 = bmesh_disk_count(ov);
1261 /* count valence of v2 */
1262 valence2 = bmesh_disk_count(tv);
1264 nv = BM_vert_create(bm, tv->co, tv);
1265 ne = BM_edge_create(bm, nv, tv, e, FALSE);
1267 bmesh_disk_remove_edge(ne, tv);
1268 bmesh_disk_remove_edge(ne, nv);
1270 /* remove e from v2's disk cycle */
1271 bmesh_disk_remove_edge(e, tv);
1273 /* swap out tv for nv in e */
1274 bmesh_edge_swapverts(e, tv, nv);
1276 /* add e to nv's disk cycl */
1277 bmesh_disk_append_edge(e, nv);
1279 /* add ne to nv's disk cycl */
1280 bmesh_disk_append_edge(ne, nv);
1282 /* add ne to tv's disk cycl */
1283 bmesh_disk_append_edge(ne, tv);
1285 /* verify disk cycle */
1286 edok = bmesh_disk_validate(valence1, ov->e, ov);
1287 if (!edok) bmesh_error();
1288 edok = bmesh_disk_validate(valence2, tv->e, tv);
1289 if (!edok) bmesh_error();
1290 edok = bmesh_disk_validate(2, nv->e, nv);
1291 if (!edok) bmesh_error();
1293 /* Split the radial cycle if presen */
1298 int radlen = bmesh_radial_length(nextl);
1299 int first1 = 0, first2 = 0;
1301 /* Take the next loop. Remove it from radial. Split it. Append to appropriate radials */
1305 nextl = nextl != nextl->radial_next ? nextl->radial_next : NULL;
1306 bmesh_radial_remove_loop(l, NULL);
1308 nl = bmesh_create_loop(bm, NULL, NULL, l->f, l);
1310 nl->next = (l->next);
1311 nl->prev->next = nl;
1312 nl->next->prev = nl;
1315 /* assign the correct edge to the correct loo */
1316 if (bmesh_verts_in_edge(nl->v, nl->next->v, e)) {
1320 /* append l into ne's rad cycl */
1323 l->radial_next = l->radial_prev = NULL;
1328 l->radial_next = l->radial_prev = NULL;
1331 bmesh_radial_append(nl->e, nl);
1332 bmesh_radial_append(l->e, l);
1334 else if (bmesh_verts_in_edge(nl->v, nl->next->v, ne)) {
1338 /* append l into ne's rad cycl */
1341 l->radial_next = l->radial_prev = NULL;
1346 l->radial_next = l->radial_prev = NULL;
1349 bmesh_radial_append(nl->e, nl);
1350 bmesh_radial_append(l->e, l);
1355 /* verify length of radial cycl */
1356 edok = bmesh_radial_validate(radlen, e->l);
1357 if (!edok) bmesh_error();
1358 edok = bmesh_radial_validate(radlen, ne->l);
1359 if (!edok) bmesh_error();
1361 /* verify loop->v and loop->next->v pointers for */
1362 for (i = 0, l = e->l; i < radlen; i++, l = l->radial_next) {
1363 if (!(l->e == e)) bmesh_error();
1364 //if (!(l->radial_next == l)) bmesh_error();
1365 if (l->prev->e != ne && l->next->e != ne) {
1368 edok = bmesh_verts_in_edge(l->v, l->next->v, e);
1369 if (!edok) bmesh_error();
1370 if (l->v == l->next->v) bmesh_error();
1371 if (l->e == l->next->e) bmesh_error();
1373 /* verify loop cycle for kloop-> */
1374 BM_CHECK_ELEMENT(bm, l);
1375 BM_CHECK_ELEMENT(bm, l->v);
1376 BM_CHECK_ELEMENT(bm, l->e);
1377 BM_CHECK_ELEMENT(bm, l->f);
1379 /* verify loop->v and loop->next->v pointers for n */
1380 for (i = 0, l = ne->l; i < radlen; i++, l = l->radial_next) {
1381 if (!(l->e == ne)) bmesh_error();
1382 //if (!(l->radial_next == l)) bmesh_error();
1383 if (l->prev->e != e && l->next->e != e) bmesh_error();
1384 edok = bmesh_verts_in_edge(l->v, l->next->v, ne);
1385 if (!edok) bmesh_error();
1386 if (l->v == l->next->v) bmesh_error();
1387 if (l->e == l->next->e) bmesh_error();
1389 BM_CHECK_ELEMENT(bm, l);
1390 BM_CHECK_ELEMENT(bm, l->v);
1391 BM_CHECK_ELEMENT(bm, l->e);
1392 BM_CHECK_ELEMENT(bm, l->f);
1396 BM_CHECK_ELEMENT(bm, ne);
1397 BM_CHECK_ELEMENT(bm, nv);
1398 BM_CHECK_ELEMENT(bm, ov);
1399 BM_CHECK_ELEMENT(bm, e);
1400 BM_CHECK_ELEMENT(bm, tv);
1409 * JOIN EDGE KILL VERT:
1410 * Takes a an edge and pointer to one of its vertices and collapses
1411 * the edge on that vertex.
1426 * KV is a vertex that must have a valance of exactly two. Furthermore
1427 * both edges in KV's disk cycle (OE and KE) must be unique (no double
1430 * It should also be noted that this euler has the possibility of creating
1431 * faces with just 2 edges. It is up to the caller to decide what to do with
1435 * 1 for success, 0 for failure.
1437 int bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv)
1441 BMLoop *killoop, *l;
1442 int len, radlen = 0, halt = 0, i, valence1, valence2, edok;
1444 if (bmesh_vert_in_edge(ke, kv) == 0) {
1448 len = bmesh_disk_count(kv);
1451 oe = bmesh_disk_nextedge(ke, kv);
1452 tv = bmesh_edge_getothervert(ke, kv);
1453 ov = bmesh_edge_getothervert(oe, kv);
1454 halt = bmesh_verts_in_edge(kv, tv, oe); /* check for double edge */
1460 /* For verification later, count valence of ov and t */
1461 valence1 = bmesh_disk_count(ov);
1462 valence2 = bmesh_disk_count(tv);
1464 /* remove oe from kv's disk cycl */
1465 bmesh_disk_remove_edge(oe, kv);
1466 /* relink oe->kv to be oe->t */
1467 bmesh_edge_swapverts(oe, kv, tv);
1468 /* append oe to tv's disk cycl */
1469 bmesh_disk_append_edge(oe, tv);
1470 /* remove ke from tv's disk cycl */
1471 bmesh_disk_remove_edge(ke, tv);
1473 /* deal with radial cycle of k */
1474 radlen = bmesh_radial_length(ke->l);
1476 /* first step, fix the neighboring loops of all loops in ke's radial cycl */
1477 for (i = 0, killoop = ke->l; i < radlen; i++, killoop = bmesh_radial_nextloop(killoop)) {
1478 /* relink loops and fix vertex pointer */
1479 if (killoop->next->v == kv) {
1480 killoop->next->v = tv;
1483 killoop->next->prev = killoop->prev;
1484 killoop->prev->next = killoop->next;
1485 if (BM_FACE_FIRST_LOOP(killoop->f) == killoop) {
1486 BM_FACE_FIRST_LOOP(killoop->f) = killoop->next;
1488 killoop->next = NULL;
1489 killoop->prev = NULL;
1491 /* fix len attribute of fac */
1494 /* second step, remove all the hanging loops attached to k */
1495 radlen = bmesh_radial_length(ke->l);
1497 if (LIKELY(radlen)) {
1498 BMLoop **loops = NULL;
1499 BLI_array_fixedstack_declare(loops, BM_NGON_STACK_SIZE, radlen, __func__);
1503 /* this should be wrapped into a bme_free_radial function to be used by bmesh_KF as well.. */
1504 for (i = 0; i < radlen; i++) {
1506 killoop = bmesh_radial_nextloop(killoop);
1508 for (i = 0; i < radlen; i++) {
1510 BLI_mempool_free(bm->lpool, loops[i]);
1512 BLI_array_fixedstack_free(loops);
1515 /* Validate radial cycle of o */
1516 edok = bmesh_radial_validate(radlen, oe->l);
1522 /* deallocate edg */
1523 bmesh_kill_only_edge(bm, ke);
1525 /* deallocate verte */
1526 bmesh_kill_only_vert(bm, kv);
1528 /* Validate disk cycle lengths of ov, tv are unchange */
1529 edok = bmesh_disk_validate(valence1, ov->e, ov);
1530 if (!edok) bmesh_error();
1531 edok = bmesh_disk_validate(valence2, tv->e, tv);
1532 if (!edok) bmesh_error();
1534 /* Validate loop cycle of all faces attached to o */
1535 for (i = 0, l = oe->l; i < radlen; i++, l = bmesh_radial_nextloop(l)) {
1536 if (l->e != oe) bmesh_error();
1537 edok = bmesh_verts_in_edge(l->v, l->next->v, oe);
1538 if (!edok) bmesh_error();
1539 edok = bmesh_loop_validate(l->f);
1540 if (!edok) bmesh_error();
1542 BM_CHECK_ELEMENT(bm, l);
1543 BM_CHECK_ELEMENT(bm, l->v);
1544 BM_CHECK_ELEMENT(bm, l->e);
1545 BM_CHECK_ELEMENT(bm, l->f);
1548 BM_CHECK_ELEMENT(bm, ov);
1549 BM_CHECK_ELEMENT(bm, tv);
1550 BM_CHECK_ELEMENT(bm, oe);
1561 * JOIN FACE KILL EDGE:
1563 * Takes two faces joined by a single 2-manifold edge and fuses them togather.
1564 * The edge shared by the faces must not be connected to any other edges which have
1565 * Both faces in its radial cycle
1570 * ---------- ----------
1573 * v1========v2 = Ok! v1==V2==v3 == Wrong!
1576 * ---------- ----------
1578 * In the example A, faces f1 and f2 are joined by a single edge, and the euler can safely be used.
1579 * In example B however, f1 and f2 are joined by multiple edges and will produce an error. The caller
1580 * in this case should call bmesh_JEKV on the extra edges before attempting to fuse f1 and f2.
1582 * Also note that the order of arguments decides whether or not certain per-face attributes are present
1583 * in the resultant face. For instance vertex winding, material index, smooth flags, ect are inherited
1589 BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
1591 BMLoop *l_iter, *f1loop = NULL, *f2loop = NULL;
1592 int newlen = 0, i, f1len = 0, f2len = 0, radlen = 0, edok, shared;
1595 /* can't join a face to itsel */
1600 /* verify that e is in both f1 and f2 */
1603 BM_ITER(l_iter, &iter, bm, BM_LOOPS_OF_FACE, f1) {
1604 if (l_iter->e == e) {
1609 BM_ITER(l_iter, &iter, bm, BM_LOOPS_OF_FACE, f2) {
1610 if (l_iter->e == e) {
1615 if (!(f1loop && f2loop)) {
1619 /* validate that edge is 2-manifold edg */
1620 radlen = bmesh_radial_length(f1loop);
1625 /* validate direction of f2's loop cycle is compatible */
1626 if (f1loop->v == f2loop->v) {
1630 /* validate that for each face, each vertex has another edge in its disk cycle that is
1631 * not e, and not shared. */
1632 if ( bmesh_radial_find_face(f1loop->next->e, f2) ||
1633 bmesh_radial_find_face(f1loop->prev->e, f2) ||
1634 bmesh_radial_find_face(f2loop->next->e, f1) ||
1635 bmesh_radial_find_face(f2loop->prev->e, f1) )
1640 /* validate only one shared edg */
1641 shared = BM_face_share_edges(f1, f2);
1646 /* validate no internal join */
1647 for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) {
1648 BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
1650 for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) {
1651 BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
1654 for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) {
1655 if (l_iter != f1loop) {
1656 BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG);
1659 for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) {
1660 if (l_iter != f2loop) {
1661 /* as soon as a duplicate is found, bail out */
1662 if (BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
1668 /* join the two loop */
1669 f1loop->prev->next = f2loop->next;
1670 f2loop->next->prev = f1loop->prev;
1672 f1loop->next->prev = f2loop->prev;
1673 f2loop->prev->next = f1loop->next;
1675 /* if f1loop was baseloop, make f1loop->next the base. */
1676 if (BM_FACE_FIRST_LOOP(f1) == f1loop)
1677 BM_FACE_FIRST_LOOP(f1) = f1loop->next;
1679 /* increase length of f1 */
1680 f1->len += (f2->len - 2);
1682 /* make sure each loop points to the proper fac */
1684 for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < newlen; i++, l_iter = l_iter->next)
1687 /* remove edge from the disk cycle of its two vertices */
1688 bmesh_disk_remove_edge(f1loop->e, f1loop->e->v1);
1689 bmesh_disk_remove_edge(f1loop->e, f1loop->e->v2);
1691 /* deallocate edge and its two loops as well as f2 */
1692 BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags);
1693 BLI_mempool_free(bm->epool, f1loop->e);
1695 BLI_mempool_free(bm->lpool, f1loop);
1697 BLI_mempool_free(bm->lpool, f2loop);
1699 BLI_mempool_free(bm->toolflagpool, f2->oflags);
1700 BLI_mempool_free(bm->fpool, f2);
1702 /* account for both above */
1703 bm->elem_index_dirty |= BM_EDGE | BM_FACE;
1705 BM_CHECK_ELEMENT(bm, f1);
1707 /* validate the new loop cycle */
1708 edok = bmesh_loop_validate(f1);
1709 if (!edok) bmesh_error();
1717 * merges two verts into one (v into vtarget).
1719 static int bmesh_splicevert(BMesh *bm, BMVert *v, BMVert *vtarget)
1725 /* verts already spliced */
1730 /* retarget all the loops of v to vtarget */
1731 BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, v) {
1735 /* move all the edges from v's disk to vtarget's disk */
1738 bmesh_disk_remove_edge(e, v);
1739 bmesh_edge_swapverts(e, v, vtarget);
1740 bmesh_disk_append_edge(e, vtarget);
1744 BM_CHECK_ELEMENT(bm, v);
1745 BM_CHECK_ELEMENT(bm, vtarget);
1747 /* v is unused now, and can be killed */
1748 BM_vert_kill(bm, v);
1755 * cut all disjoint fans that meet at a vertex, making a unique
1756 * vertex for each region. returns an array of all resulting
1759 static int bmesh_cutvert(BMesh *bm, BMVert *v, BMVert ***vout, int *len)
1761 BMEdge **stack = NULL;
1762 BLI_array_declare(stack);
1763 BMVert **verts = NULL;
1765 BMIter eiter, liter;
1771 visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh_cutvert visithash");
1774 BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
1775 if (BLI_ghash_haskey(visithash, e)) {
1779 /* Prime the stack with this unvisited edge */
1780 BLI_array_append(stack, e);
1782 /* Considering only edges and faces incident on vertex v, walk
1783 * the edges & faces and assign an index to each connected set */
1784 while ((e = BLI_array_pop(stack))) {
1785 BLI_ghash_insert(visithash, e, SET_INT_IN_POINTER(maxindex));
1787 BM_ITER(l, &liter, bm, BM_LOOPS_OF_EDGE, e) {
1788 nl = (l->v == v) ? l->prev : l->next;
1789 if (!BLI_ghash_haskey(visithash, nl->e)) {
1790 BLI_array_append(stack, nl->e);
1798 /* Make enough verts to split v for each group */
1799 verts = MEM_callocN(sizeof(BMVert *) * maxindex, "bmesh_cutvert");
1801 for (i = 1; i < maxindex; i++) {
1802 verts[i] = BM_vert_create(bm, v->co, v);
1805 /* Replace v with the new verts in each group */
1806 BM_ITER(l, &liter, bm, BM_LOOPS_OF_VERT, v) {
1807 i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, l->e));
1812 /* Loops here should alway refer to an edge that has v as an
1813 * endpoint. For each appearance of this vert in a face, there
1814 * will actually be two iterations: one for the loop heading
1815 * towards vertex v, and another for the loop heading out from
1816 * vertex v. Only need to swap the vertex on one of those times,
1817 * on the outgoing loop. */
1823 BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
1824 i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, e));
1829 BLI_assert(e->v1 == v || e->v2 == v);
1830 bmesh_disk_remove_edge(e, v);
1831 bmesh_edge_swapverts(e, v, verts[i]);
1832 bmesh_disk_append_edge(e, verts[i]);
1835 BLI_ghash_free(visithash, NULL, NULL);
1836 BLI_array_free(stack);
1838 for (i = 0; i < maxindex; i++) {
1839 BM_CHECK_ELEMENT(bm, verts[i]);
1856 /* BMESH SPLICE EDGE
1858 * splice two unique edges which share the same two vertices into one edge.
1860 * edges must already have the same vertices
1862 static int UNUSED_FUNCTION(bmesh_spliceedge)(BMesh *bm, BMEdge *e, BMEdge *etarget)
1866 if (!BM_vert_in_edge(e, etarget->v1) || !BM_vert_in_edge(e, etarget->v2)) {
1867 /* not the same vertices can't splice */
1873 BLI_assert(BM_vert_in_edge(etarget, l->v));
1874 BLI_assert(BM_vert_in_edge(etarget, l->next->v));
1875 bmesh_radial_remove_loop(l, e);
1876 bmesh_radial_append(etarget, l);
1879 BLI_assert(bmesh_radial_length(e->l) == 0);
1881 BM_CHECK_ELEMENT(bm, e);
1882 BM_CHECK_ELEMENT(bm, etarget);
1884 BM_edge_kill(bm, e);
1892 * Cuts a single edge into two edge: the original edge and
1893 * a new edge that has only "cutl" in its radial.
1895 * Does nothing if cutl is already the only loop in the
1898 static int bmesh_cutedge(BMesh *bm, BMEdge *e, BMLoop *cutl)
1903 BLI_assert(cutl->e == e);
1906 radlen = bmesh_radial_length(e->l);
1908 /* no cut required */
1913 e->l = cutl->radial_next;
1916 ne = BM_edge_create(bm, e->v1, e->v2, e, FALSE);
1917 bmesh_radial_remove_loop(cutl, e);
1918 bmesh_radial_append(ne, cutl);
1921 BLI_assert(bmesh_radial_length(e->l) == radlen - 1);
1922 BLI_assert(bmesh_radial_length(ne->l) == 1);
1924 BM_CHECK_ELEMENT(bm, ne);
1925 BM_CHECK_ELEMENT(bm, e);
1931 * BMESH UNGLUE REGION MAKE VERT
1933 * Disconnects a face from its vertex fan at loop sl.
1935 static BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl)
1942 /* peel the face from the edge radials on both sides of the
1943 * loop vert, disconnecting the face from its fan */
1944 bmesh_cutedge(bm, sl->e, sl);
1945 bmesh_cutedge(bm, sl->prev->e, sl->prev);
1947 if (bmesh_disk_count(sv) == 2) {
1948 /* If there are still only two edges out of sv, then
1949 * this whole URMV was just a no-op, so exit now. */
1953 /* Update the disk start, so that v->e points to an edge
1954 * not touching the split loop. This is so that bmesh_cutvert
1955 * will leave the original sv on some *other* fan (not the
1956 * one-face fan that holds the unglue face). */
1957 while (sv->e == sl->e || sv->e == sl->prev->e) {
1958 sv->e = bmesh_disk_nextedge(sv->e, sv);
1961 /* Split all fans connected to the vert, duplicating it for
1963 bmesh_cutvert(bm, sv, &vtar, &len);
1965 /* There should have been at least two fans cut apart here,
1966 * otherwise the early exit would have kicked in. */
1967 BLI_assert(len >= 2);
1971 /* Desired result here is that a new vert should always be
1972 * created for the unglue face. This is so we can glue any
1973 * extras back into the original vert. */
1974 BLI_assert(nv != sv);
1975 BLI_assert(sv == vtar[0]);
1977 /* If there are more than two verts as a result, glue together
1978 * all the verts except the one this URMV intended to create */
1980 for (i = 0; i < len; i++) {
1981 if (vtar[i] == nv) {
1987 /* Swap the single vert that was needed for the
1988 * unglue into the last array slot */
1989 SWAP(BMVert *, vtar[i], vtar[len - 1]);
1991 /* And then glue the rest back together */
1992 for (i = 1; i < len - 1; i++) {
1993 bmesh_splicevert(bm, vtar[i], vtar[0]);
2004 * BMESH UNGLUE REGION MAKE VERT
2006 * Disconnects sf from the vertex fan at sv
2008 BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv)
2013 l_iter = l_first = BM_FACE_FIRST_LOOP(sf);
2015 if (l_iter->v == sv) {
2018 } while ((l_iter = l_iter->next) != l_first);
2020 if (l_iter->v != sv) {
2021 /* sv is not part of sf */
2025 return bmesh_urmv_loop(bm, l_iter);