diff options
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_mods.c')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mods.c | 644 |
1 files changed, 41 insertions, 603 deletions
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 13c43fabdb0..d3c847de64e 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -29,22 +29,14 @@ #include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "BLI_array.h" -#include "BLI_alloca.h" -#include "BLI_stackdefines.h" -#include "BLI_linklist_stack.h" -#include "BLI_sort_utils.h" #include "BKE_customdata.h" #include "bmesh.h" #include "intern/bmesh_private.h" -// #define DEBUG_PRINT - - /** * \brief Dissolve Vert * @@ -252,7 +244,8 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f_a, BMFace *f_b, BMEdge *e, const BLI_assert(l_a && l_b); if (l_a->v == l_b->v) { - bmesh_loop_reverse(bm, f_b); + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + bmesh_loop_reverse(bm, f_b, cd_loop_mdisp_offset, true); } return BM_faces_join(bm, faces, 2, do_del); @@ -282,7 +275,7 @@ BMFace *BM_face_split( BMLoop **r_l, BMEdge *example, const bool no_double) { - const bool has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS); + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); BMFace *f_new, *f_tmp; BLI_assert(l_a != l_b); @@ -300,7 +293,7 @@ BMFace *BM_face_split( } /* do we have a multires layer? */ - if (has_mdisp) { + if (cd_loop_mdisp_offset != -1) { f_tmp = BM_face_copy(bm, bm, f, false, false); } @@ -312,19 +305,17 @@ BMFace *BM_face_split( if (f_new) { /* handle multires update */ - if (has_mdisp) { - BMLoop *l_iter; - BMLoop *l_first; + if (cd_loop_mdisp_offset != -1) { + float f_dst_center[3]; + float f_src_center[3]; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_loop_interp_multires(bm, l_iter, f_tmp); - } while ((l_iter = l_iter->next) != l_first); + BM_face_calc_center_mean(f_tmp, f_src_center); - l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); - do { - BM_loop_interp_multires(bm, l_iter, f_tmp); - } while ((l_iter = l_iter->next) != l_first); + BM_face_calc_center_mean(f, f_dst_center); + BM_face_interp_multires_ex(bm, f, f_tmp, f_dst_center, f_src_center, cd_loop_mdisp_offset); + + BM_face_calc_center_mean(f_new, f_dst_center); + BM_face_interp_multires_ex(bm, f_new, f_tmp, f_dst_center, f_src_center, cd_loop_mdisp_offset); #if 0 /* BM_face_multires_bounds_smooth doesn't flip displacement correct */ @@ -334,7 +325,7 @@ BMFace *BM_face_split( } } - if (has_mdisp) { + if (cd_loop_mdisp_offset != -1) { BM_face_kill(bm, f_tmp); } @@ -427,549 +418,6 @@ BMFace *BM_face_split_n( return f_new; } - -/* -------------------------------------------------------------------- */ -/* Face Split Edge-Net */ - -/** \name BM_face_split_edgenet and helper functions. - * - * \note Don't use #BM_edge_is_wire or #BM_edge_is_boundary - * since we need to take flagged faces into account. - * Also take care accessing e->l directly. - * - * \{ */ - -/* Note: All these flags _must_ be cleared on exit */ - -/* face is apart of the edge-net (including the original face we're splitting) */ -#define FACE_NET _FLAG_WALK -/* edge is apart of the edge-net we're filling */ -#define EDGE_NET _FLAG_WALK -/* tag verts we've visit */ -#define VERT_VISIT _FLAG_WALK - -struct VertOrder { - float angle; - BMVert *v; -}; - -static unsigned int bm_edge_flagged_radial_count(BMEdge *e) -{ - unsigned int count = 0; - BMLoop *l; - - if ((l = e->l)) { - do { - if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) { - count++; - } - } while ((l = l->radial_next) != e->l); - } - return count; -} - -static BMLoop *bm_edge_flagged_radial_first(BMEdge *e) -{ - BMLoop *l; - - if ((l = e->l)) { - do { - if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) { - return l; - } - } while ((l = l->radial_next) != e->l); - } - return NULL; -} - -static bool bm_face_split_edgenet_find_loop_pair( - BMVert *v_init, const float face_normal[3], - BMEdge *e_pair[2]) -{ - /* Always find one boundary edge (to determine winding) - * and one wire (if available), otherwise another boundary. - */ - BMIter iter; - BMEdge *e; - - /* detect winding */ - BMLoop *l_walk; - bool swap; - - BLI_SMALLSTACK_DECLARE(edges_boundary, BMEdge *); - BLI_SMALLSTACK_DECLARE(edges_wire, BMEdge *); - int edges_boundary_len = 0; - int edges_wire_len = 0; - - BM_ITER_ELEM (e, &iter, v_init, BM_EDGES_OF_VERT) { - if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) { - const unsigned int count = bm_edge_flagged_radial_count(e); - if (count == 1) { - BLI_SMALLSTACK_PUSH(edges_boundary, e); - edges_boundary_len++; - } - else if (count == 0) { - BLI_SMALLSTACK_PUSH(edges_wire, e); - edges_wire_len++; - } - } - } - - /* first edge should always be boundary */ - if (edges_boundary_len == 0) { - return false; - } - e_pair[0] = BLI_SMALLSTACK_POP(edges_boundary); - - /* attempt one boundary and one wire, or 2 boundary */ - if (edges_wire_len == 0) { - if (edges_boundary_len >= 2) { - e_pair[1] = BLI_SMALLSTACK_POP(edges_boundary); - } - else { - /* one boundary and no wire */ - return false; - } - } - else { - e_pair[1] = BLI_SMALLSTACK_POP(edges_wire); - - if (edges_wire_len > 1) { - BMVert *v_prev = BM_edge_other_vert(e_pair[0], v_init); - BMVert *v_next; - float angle_best; - - v_next = BM_edge_other_vert(e_pair[1], v_init); - angle_best = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal); - - while ((e = BLI_SMALLSTACK_POP(edges_wire))) { - float angle_test; - v_next = BM_edge_other_vert(e, v_init); - angle_test = angle_on_axis_v3v3v3_v3(v_prev->co, v_init->co, v_next->co, face_normal); - if (angle_test < angle_best) { - angle_best = angle_test; - e_pair[1] = e; - } - } - } - } - - - /* flip based on winding */ - l_walk = bm_edge_flagged_radial_first(e_pair[0]); - swap = false; - if (face_normal == l_walk->f->no) { - swap = !swap; - } - if (l_walk->v != v_init) { - swap = !swap; - } - if (swap) { - SWAP(BMEdge *, e_pair[0], e_pair[1]); - } - - return true; -} - -static bool bm_face_split_edgenet_find_loop_walk( - BMVert *v_init, const float face_normal[3], - /* cache to avoid realloc every time */ - struct VertOrder *edge_order, const unsigned int edge_order_len, - BMEdge *e_pair[2]) -{ - /* fast-path for the common case (avoid push-pop). - * Also avoids tagging as visited since we know we - * can't reach these verts some other way */ -#define USE_FASTPATH_NOFORK - - BMVert *v; - BMVert *v_dst; - bool found = false; - - struct VertOrder *eo; - STACK_DECLARE(edge_order); - - /* store visited verts so we can clear the visit flag after execution */ - BLI_SMALLSTACK_DECLARE(vert_visit, BMVert *); - - /* likely this will stay very small - * all verts pushed into this stack _must_ have their previous edges set! */ - BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *); - BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *); - - STACK_INIT(edge_order, edge_order_len); - - /* start stepping */ - v = BM_edge_other_vert(e_pair[0], v_init); - v->e = e_pair[0]; - BLI_SMALLSTACK_PUSH(vert_stack, v); - - v_dst = BM_edge_other_vert(e_pair[1], v_init); - -#ifdef DEBUG_PRINT - printf("%s: vert (search) %d\n", __func__, BM_elem_index_get(v_init)); -#endif - - /* This loop will keep stepping over the best possible edge, - * in most cases it finds the direct route to close the face. - * - * In cases where paths can't be closed, - * alternatives are stored in the 'vert_stack'. - */ - while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) { - BMIter eiter; - BMEdge *e_next; - -#ifdef USE_FASTPATH_NOFORK -walk_nofork: -#else - BLI_SMALLSTACK_PUSH(vert_visit, v); - BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT); -#endif - - BLI_assert(STACK_SIZE(edge_order) == 0); - - /* check if we're done! */ - if (v == v_dst) { - found = true; - goto finally; - } - - BM_ITER_ELEM (e_next, &eiter, v, BM_EDGES_OF_VERT) { - if ((v->e != e_next) && - (BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) && - (bm_edge_flagged_radial_count(e_next) < 2)) - { - BMVert *v_next; - - v_next = BM_edge_other_vert(e_next, v); - -#ifdef DEBUG_PRINT - /* indent and print */ - { - BMVert *_v = v; - do { - printf(" "); - } while ((_v = BM_edge_other_vert(_v->e, _v)) != v_init); - printf("vert %d -> %d (add=%d)\n", - BM_elem_index_get(v), BM_elem_index_get(v_next), - BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT) == 0); - } -#endif - - if (!BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT)) { - eo = STACK_PUSH_RET_PTR(edge_order); - eo->v = v_next; - - v_next->e = e_next; - } - } - } - -#ifdef USE_FASTPATH_NOFORK - if (STACK_SIZE(edge_order) == 1) { - eo = STACK_POP_PTR(edge_order); - v = eo->v; - - goto walk_nofork; - } -#endif - - /* sort by angle if needed */ - if (STACK_SIZE(edge_order) > 1) { - unsigned int j; - BMVert *v_prev = BM_edge_other_vert(v->e, v); - - for (j = 0; j < STACK_SIZE(edge_order); j++) { - edge_order[j].angle = angle_signed_on_axis_v3v3v3_v3(v_prev->co, v->co, edge_order[j].v->co, face_normal); - } - qsort(edge_order, STACK_SIZE(edge_order), sizeof(struct VertOrder), BLI_sortutil_cmp_float_reverse); - -#ifdef USE_FASTPATH_NOFORK - /* only tag forks */ - BLI_SMALLSTACK_PUSH(vert_visit, v); - BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT); -#endif - } - - while ((eo = STACK_POP_PTR(edge_order))) { - BLI_SMALLSTACK_PUSH(vert_stack_next, eo->v); - } - - if (!BLI_SMALLSTACK_IS_EMPTY(vert_stack_next)) { - BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next); - } - } - - -finally: - /* clear flag for next execution */ - while ((v = BLI_SMALLSTACK_POP(vert_visit))) { - BM_ELEM_API_FLAG_DISABLE(v, VERT_VISIT); - } - - return found; - -#undef USE_FASTPATH_NOFORK -} - -static bool bm_face_split_edgenet_find_loop( - BMVert *v_init, const float face_normal[3], - /* cache to avoid realloc every time */ - struct VertOrder *edge_order, const unsigned int edge_order_len, - BMVert **r_face_verts, int *r_face_verts_len) -{ - BMEdge *e_pair[2]; - BMVert *v; - - if (!bm_face_split_edgenet_find_loop_pair(v_init, face_normal, e_pair)) { - return false; - } - - BLI_assert((bm_edge_flagged_radial_count(e_pair[0]) == 1) || - (bm_edge_flagged_radial_count(e_pair[1]) == 1)); - - if (bm_face_split_edgenet_find_loop_walk(v_init, face_normal, edge_order, edge_order_len, e_pair)) { - unsigned int i = 0; - - r_face_verts[i++] = v_init; - v = BM_edge_other_vert(e_pair[1], v_init); - do { - r_face_verts[i++] = v; - } while ((v = BM_edge_other_vert(v->e, v)) != v_init); - *r_face_verts_len = i; - return (i > 2) ? true : false; - } - else { - return false; - } -} - -/** - * Splits a face into many smaller faces defined by an edge-net. - * handle customdata and degenerate cases. - * - * - isolated holes or unsupported face configurations, will be ignored. - * - customdata calculations aren't efficient - * (need to calculate weights for each vert). - */ -bool BM_face_split_edgenet( - BMesh *bm, - BMFace *f, BMEdge **edge_net, const int edge_net_len, - BMFace ***r_face_arr, int *r_face_arr_len) -{ - /* re-use for new face verts */ - BMVert **face_verts; - int face_verts_len; - - BMFace **face_arr = NULL; - BLI_array_declare(face_arr); - - BMVert **vert_queue; - STACK_DECLARE(vert_queue); - int i; - - struct VertOrder *edge_order; - const unsigned int edge_order_len = edge_net_len + 2; - - BMVert *v; - - BMLoop *l_iter, *l_first; - - - if (!edge_net_len) { - if (r_face_arr) { - *r_face_arr = NULL; - *r_face_arr_len = 0; - } - return false; - } - - /* over-alloc (probably 2-4 is only used in most cases), for the biggest-fan */ - edge_order = BLI_array_alloca(edge_order, edge_order_len); - - /* use later */ - face_verts = BLI_array_alloca(face_verts, edge_net_len + f->len); - - vert_queue = BLI_array_alloca(vert_queue, edge_net_len + f->len); - STACK_INIT(vert_queue, f->len + edge_net_len); - - BLI_assert(BM_ELEM_API_FLAG_TEST(f, FACE_NET) == 0); - BM_ELEM_API_FLAG_ENABLE(f, FACE_NET); - -#ifdef DEBUG - for (i = 0; i < edge_net_len; i++) { - BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET) == 0); - BLI_assert(BM_edge_in_face(edge_net[i], f) == false); - } - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter->e, EDGE_NET) == 0); - } while ((l_iter = l_iter->next) != l_first); -#endif - - - for (i = 0; i < edge_net_len; i++) { - BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET); - } - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET); - } while ((l_iter = l_iter->next) != l_first); - - - /* any vert can be used to begin with */ - STACK_PUSH(vert_queue, l_first->v); - - while ((v = STACK_POP(vert_queue))) { - if (bm_face_split_edgenet_find_loop(v, f->no, edge_order, edge_order_len, face_verts, &face_verts_len)) { - BMFace *f_new; - - f_new = BM_face_create_verts(bm, face_verts, face_verts_len, f, BM_CREATE_NOP, false); - - for (i = 0; i < edge_net_len; i++) { - BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET)); - } - - if (f_new) { - bool l_prev_is_boundary; - BLI_array_append(face_arr, f_new); - copy_v3_v3(f_new->no, f->no); - - BM_ELEM_API_FLAG_ENABLE(f_new, FACE_NET); - - /* add new verts to keep finding loops for - * (verts between boundary and manifold edges) */ - l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); - l_prev_is_boundary = (bm_edge_flagged_radial_count(l_iter->prev->e) == 1); - do { - bool l_iter_is_boundary = (bm_edge_flagged_radial_count(l_iter->e) == 1); - if (l_prev_is_boundary != l_iter_is_boundary) { - STACK_PUSH(vert_queue, l_iter->v); - } - l_prev_is_boundary = l_iter_is_boundary; - } while ((l_iter = l_iter->next) != l_first); - } - } - } - - - if (CustomData_has_math(&bm->ldata)) { - /* reuse VERT_VISIT here to tag vert's already interpolated */ - BMIter iter; - BMLoop *l_other; - - /* see: #BM_loop_interp_from_face for similar logic */ - void **blocks = BLI_array_alloca(blocks, f->len); - float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f->len); - float *w = BLI_array_alloca(w, f->len); - float axis_mat[3][3]; - float co[2]; - - /* interior loops */ - axis_dominant_v3_to_m3(axis_mat, f->no); - - - /* first simply copy from existing face */ - i = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_ITER_ELEM (l_other, &iter, l_iter->v, BM_LOOPS_OF_VERT) { - if ((l_other->f != f) && BM_ELEM_API_FLAG_TEST(l_other->f, FACE_NET)) { - CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, - l_iter->head.data, &l_other->head.data); - } - } - /* tag not to interpolate */ - BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_VISIT); - - - mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); - blocks[i] = l_iter->head.data; - - } while (i++, (l_iter = l_iter->next) != l_first); - - - for (i = 0; i < edge_net_len; i++) { - BM_ITER_ELEM (v, &iter, edge_net[i], BM_VERTS_OF_EDGE) { - if (!BM_ELEM_API_FLAG_TEST(v, VERT_VISIT)) { - BMIter liter; - - BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT); - - /* interpolate this loop, then copy to the rest */ - l_first = NULL; - - BM_ITER_ELEM (l_iter, &liter, v, BM_LOOPS_OF_VERT) { - if (BM_ELEM_API_FLAG_TEST(l_iter->f, FACE_NET)) { - if (l_first == NULL) { - mul_v2_m3v3(co, axis_mat, v->co); - interp_weights_poly_v2(w, cos_2d, f->len, co); - CustomData_bmesh_interp( - &bm->ldata, (const void **)blocks, - w, NULL, f->len, l_iter->head.data); - l_first = l_iter; - } - else { - CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, - l_first->head.data, &l_iter->head.data); - } - } - } - } - } - } - } - - - - /* cleanup */ - for (i = 0; i < edge_net_len; i++) { - BM_ELEM_API_FLAG_DISABLE(edge_net[i], EDGE_NET); - /* from interp only */ - BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_VISIT); - BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_VISIT); - } - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_ELEM_API_FLAG_DISABLE(l_iter->e, EDGE_NET); - /* from interp only */ - BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_VISIT); - } while ((l_iter = l_iter->next) != l_first); - - if (BLI_array_count(face_arr)) { - bmesh_face_swap_data(f, face_arr[0]); - BM_face_kill(bm, face_arr[0]); - face_arr[0] = f; - } - else { - BM_ELEM_API_FLAG_DISABLE(f, FACE_NET); - } - - for (i = 0; i < BLI_array_count(face_arr); i++) { - BM_ELEM_API_FLAG_DISABLE(face_arr[i], FACE_NET); - } - - if (r_face_arr) { - *r_face_arr = face_arr; - *r_face_arr_len = BLI_array_count(face_arr); - } - else { - if (face_arr) { - MEM_freeN(face_arr); - } - } - - return true; -} - -#undef FACE_NET -#undef VERT_VISIT -#undef EDGE_NET - -/** \} */ - - /** * \brief Vert Collapse Faces * @@ -1068,32 +516,8 @@ BMEdge *BM_vert_collapse_faces( /* single face or no faces */ /* same as BM_vert_collapse_edge() however we already * have vars to perform this operation so don't call. */ - e_new = bmesh_jekv(bm, e_kill, v_kill, do_del, true); + e_new = bmesh_jekv(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */ - - if (e_new && kill_degenerate_faces) { - BMFace **bad_faces = NULL; - BLI_array_staticdeclare(bad_faces, BM_DEFAULT_ITER_STACK_SIZE); - - BMIter fiter; - BMFace *f; - BMVert *verts[2] = {e_new->v1, e_new->v2}; - int i; - - for (i = 0; i < 2; i++) { - /* cant kill data we loop on, build a list and remove those */ - BLI_array_empty(bad_faces); - BM_ITER_ELEM (f, &fiter, verts[i], BM_FACES_OF_VERT) { - if (UNLIKELY(f->len < 3)) { - BLI_array_append(bad_faces, f); - } - } - while ((f = BLI_array_pop(bad_faces))) { - BM_face_kill(bm, f); - } - } - BLI_array_free(bad_faces); - } } return e_new; @@ -1143,6 +567,16 @@ BMEdge *BM_vert_collapse_edge( #undef DO_V_INTERP /** + * Collapse and edge into a single vertex. + */ +BMVert *BM_edge_collapse( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool kill_degenerate_faces) +{ + return bmesh_jvke(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); +} + +/** * \brief Edge Split * * <pre> @@ -1167,7 +601,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) BMFace **oldfaces = NULL; BMEdge *e_dummy; BLI_array_staticdeclare(oldfaces, 32); - const bool do_mdisp = (e->l && CustomData_has_layer(&bm->ldata, CD_MDISPS)); + const int cd_loop_mdisp_offset = BM_edge_is_wire(e) ? -1 : CustomData_get_offset(&bm->ldata, CD_MDISPS); BLI_assert(BM_vert_in_edge(e, v) == true); @@ -1177,7 +611,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) } /* do we have a multi-res layer? */ - if (do_mdisp) { + if (cd_loop_mdisp_offset != -1) { BMLoop *l; int i; @@ -1212,14 +646,18 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) BM_data_interp_face_vert_edge(bm, v_other, v, v_new, e, fac); BM_data_interp_from_verts(bm, v, v_other, v_new, fac); - if (do_mdisp) { + if (cd_loop_mdisp_offset != -1) { int i, j; /* interpolate new/changed loop data from copied old faces */ - for (j = 0; j < 2; j++) { - for (i = 0; i < BLI_array_count(oldfaces); i++) { + for (i = 0; i < BLI_array_count(oldfaces); i++) { + float f_center_old[3]; + + BM_face_calc_center_mean(oldfaces[i], f_center_old); + + for (j = 0; j < 2; j++) { BMEdge *e1 = j ? *r_e : e; - BMLoop *l, *l2; + BMLoop *l; l = e1->l; @@ -1227,16 +665,16 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) BMESH_ASSERT(0); break; } - + do { /* check this is an old face */ if (BM_ELEM_API_FLAG_TEST(l->f, _FLAG_OVERLAP)) { - BMLoop *l2_first; + float f_center[3]; - l2 = l2_first = BM_FACE_FIRST_LOOP(l->f); - do { - BM_loop_interp_multires(bm, l2, oldfaces[i]); - } while ((l2 = l2->next) != l2_first); + BM_face_calc_center_mean(l->f, f_center); + BM_face_interp_multires_ex( + bm, l->f, oldfaces[i], + f_center, f_center_old, cd_loop_mdisp_offset); } l = l->radial_next; } while (l != e1->l); |