``` *     Before:               After:
*      +--------+           +--------+
*      |        |           |        |
*      |        |           |   f1   |
*     v1   f1   v2          v1======v2
*      |        |           |   f2   |
*      |        |           |        |
*      +--------+           +--------+
* ```
* * \note the input vertices can be part of the same edge. This will * result in a two edged face. This is desirable for advanced construction * tools and particularly essential for edge bevel. Because of this it is * up to the caller to decide what to do with the extra edge. * * \note If \a holes is NULL, then both faces will lose * all holes from the original face. Also, you cannot split between * a hole vert and a boundary vert; that case is handled by higher- * level wrapping functions (when holes are fully implemented, anyway). * * \note that holes represents which holes goes to the new face, and of * course this requires removing them from the existing face first, since * you cannot have linked list links inside multiple lists. * * \return A BMFace pointer */ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l, #ifdef USE_BMESH_HOLES ListBase *holes, #endif BMEdge *example, const short nodouble ) { #ifdef USE_BMESH_HOLES BMLoopList *lst, *lst2; #endif BMFace *f2; BMLoop *l_iter, *l_first; BMLoop *v1loop = NULL, *v2loop = NULL, *f1loop = NULL, *f2loop = NULL; BMEdge *e; int i, len, f1len, f2len, first_loop_f1; /* verify that v1 and v2 are in face */ len = f->len; for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < len; i++, l_iter = l_iter->next) { if (l_iter->v == v1) v1loop = l_iter; else if (l_iter->v == v2) v2loop = l_iter; } if (!v1loop || !v2loop) { return NULL; } /* allocate new edge between v1 and v2 */ e = BM_edge_create(bm, v1, v2, example, nodouble); f2 = bm_face_create__sfme(bm, f); f1loop = bm_loop_create(bm, v2, e, f, v2loop); f2loop = bm_loop_create(bm, v1, e, f2, v1loop); f1loop->prev = v2loop->prev; f2loop->prev = v1loop->prev; v2loop->prev->next = f1loop; v1loop->prev->next = f2loop; f1loop->next = v1loop; f2loop->next = v2loop; v1loop->prev = f1loop; v2loop->prev = f2loop; #ifdef USE_BMESH_HOLES lst = f->loops.first; lst2 = f2->loops.first; lst2->first = lst2->last = f2loop; lst->first = lst->last = f1loop; #else /* find which of the faces the original first loop is in */ l_iter = l_first = f1loop; first_loop_f1 = 0; do { if (l_iter == f->l_first) first_loop_f1 = 1; } while ((l_iter = l_iter->next) != l_first); if (first_loop_f1) { /* original first loop was in f1, find a suitable first loop for f2 * which is as similar as possible to f1. the order matters for tools * such as duplifaces. */ if (f->l_first->prev == f1loop) f2->l_first = f2loop->prev; else if (f->l_first->next == f1loop) f2->l_first = f2loop->next; else f2->l_first = f2loop; } else { /* original first loop was in f2, further do same as above */ f2->l_first = f->l_first; if (f->l_first->prev == f2loop) f->l_first = f1loop->prev; else if (f->l_first->next == f2loop) f->l_first = f1loop->next; else f->l_first = f1loop; } #endif /* validate both loop */ /* I don't know how many loops are supposed to be in each face at this point! FIXME */ /* go through all of f2's loops and make sure they point to it properly */ l_iter = l_first = BM_FACE_FIRST_LOOP(f2); f2len = 0; do { l_iter->f = f2; f2len++; } while ((l_iter = l_iter->next) != l_first); /* link up the new loops into the new edges radial */ bmesh_radial_append(e, f1loop); bmesh_radial_append(e, f2loop); f2->len = f2len; f1len = 0; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { f1len++; } while ((l_iter = l_iter->next) != l_first); f->len = f1len; if (r_l) *r_l = f2loop; #ifdef USE_BMESH_HOLES if (holes) { BLI_movelisttolist(&f2->loops, holes); } else { /* this code is not significant until holes actually work */ //printf("warning: call to split face euler without holes argument; holes will be tossed.\n"); for (lst = f->loops.last; lst != f->loops.first; lst = lst2) { lst2 = lst->prev; BLI_mempool_free(bm->looplistpool, lst); } } #endif BM_CHECK_ELEMENT(e); BM_CHECK_ELEMENT(f); BM_CHECK_ELEMENT(f2); return f2; } /** * \brief Split Edge Make Vert (SEMV) * * Takes \a e edge and splits it into two, creating a new vert. * \a tv should be one end of \a e : the newly created edge * will be attached to that end and is returned in \a r_e. * * \par Examples: *
``` *                     E
*     Before: OV-------------TV
*
*                 E       RE
*     After:  OV------NV-----TV
* ```
``` *     Before:         OE      KE
*                   ------- -------
*                   |     ||      |
*                  OV     KV      TV
*
*
*     After:              OE
*                   ---------------
*                   |             |
*                  OV             TV
* ```
``` *           A                   B