diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/bmesh/operators/bmo_bridge.c | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/bmesh/operators/bmo_bridge.c')
-rw-r--r-- | source/blender/bmesh/operators/bmo_bridge.c | 1117 |
1 files changed, 571 insertions, 546 deletions
diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c index 84b5f44a43f..39ccc0c631e 100644 --- a/source/blender/bmesh/operators/bmo_bridge.c +++ b/source/blender/bmesh/operators/bmo_bridge.c @@ -28,32 +28,33 @@ #include "intern/bmesh_operators_private.h" /* own include */ -#define EDGE_MARK 4 -#define EDGE_OUT 8 -#define FACE_OUT 16 +#define EDGE_MARK 4 +#define EDGE_OUT 8 +#define FACE_OUT 16 /* el_a and el_b _must_ be same size */ -static void bm_bridge_splice_loops(BMesh *bm, LinkData *el_a, LinkData *el_b, const float merge_factor) +static void bm_bridge_splice_loops(BMesh *bm, + LinkData *el_a, + LinkData *el_b, + const float merge_factor) { - BMOperator op_weld; - BMOpSlot *slot_targetmap; + BMOperator op_weld; + BMOpSlot *slot_targetmap; - BMO_op_init(bm, &op_weld, 0, "weld_verts"); + BMO_op_init(bm, &op_weld, 0, "weld_verts"); - slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap"); + slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap"); - do { - BMVert *v_a = el_a->data, *v_b = el_b->data; - BM_data_interp_from_verts(bm, v_a, v_b, v_b, merge_factor); - interp_v3_v3v3(v_b->co, v_a->co, v_b->co, merge_factor); - BLI_assert(v_a != v_b); - BMO_slot_map_elem_insert(&op_weld, slot_targetmap, v_a, v_b); - } while ((void) - (el_b = el_b->next), - (el_a = el_a->next)); + do { + BMVert *v_a = el_a->data, *v_b = el_b->data; + BM_data_interp_from_verts(bm, v_a, v_b, v_b, merge_factor); + interp_v3_v3v3(v_b->co, v_a->co, v_b->co, merge_factor); + BLI_assert(v_a != v_b); + BMO_slot_map_elem_insert(&op_weld, slot_targetmap, v_a, v_b); + } while ((void)(el_b = el_b->next), (el_a = el_a->next)); - BMO_op_exec(bm, &op_weld); - BMO_op_finish(bm, &op_weld); + BMO_op_exec(bm, &op_weld); + BMO_op_finish(bm, &op_weld); } /* get the 2 loops matching 2 verts. @@ -61,557 +62,581 @@ static void bm_bridge_splice_loops(BMesh *bm, LinkData *el_a, LinkData *el_b, co * if that fails just get any loop thats on the vert (the first one) */ static void bm_vert_loop_pair(BMesh *bm, BMVert *v1, BMVert *v2, BMLoop **l1, BMLoop **l2) { - BMEdge *e = BM_edge_exists(v1, v2); - BMLoop *l = e->l; - - if (l) { - if (l->v == v1) { - *l1 = l; - *l2 = l->next; - } - else { - *l2 = l; - *l1 = l->next; - } - } - else { - /* fallback to _any_ loop */ - *l1 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v1, 0); - *l2 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v2, 0); - } + BMEdge *e = BM_edge_exists(v1, v2); + BMLoop *l = e->l; + + if (l) { + if (l->v == v1) { + *l1 = l; + *l2 = l->next; + } + else { + *l2 = l; + *l1 = l->next; + } + } + else { + /* fallback to _any_ loop */ + *l1 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v1, 0); + *l2 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v2, 0); + } } /* el_b can have any offset */ -static float bm_edgeloop_offset_length( - LinkData *el_a, LinkData *el_b, - LinkData *el_b_first, const float len_max) +static float bm_edgeloop_offset_length(LinkData *el_a, + LinkData *el_b, + LinkData *el_b_first, + const float len_max) { - float len = 0.0f; - BLI_assert(el_a->prev == NULL); /* must be first */ - do { - len += len_v3v3(((BMVert *)el_a->data)->co, ((BMVert *)el_b->data)->co); - } while ((void) - (el_b = el_b->next ? el_b->next : el_b_first), - (el_a = el_a->next) && (len < len_max)); - return len; + float len = 0.0f; + BLI_assert(el_a->prev == NULL); /* must be first */ + do { + len += len_v3v3(((BMVert *)el_a->data)->co, ((BMVert *)el_b->data)->co); + } while ((void)(el_b = el_b->next ? el_b->next : el_b_first), + (el_a = el_a->next) && (len < len_max)); + return len; } -static void bm_bridge_best_rotation(struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b) +static void bm_bridge_best_rotation(struct BMEdgeLoopStore *el_store_a, + struct BMEdgeLoopStore *el_store_b) { - ListBase *lb_a = BM_edgeloop_verts_get(el_store_a); - ListBase *lb_b = BM_edgeloop_verts_get(el_store_b); - LinkData *el_a = lb_a->first; - LinkData *el_b = lb_b->first; - LinkData *el_b_first = el_b; - LinkData *el_b_best = NULL; - - float len_best = FLT_MAX; - - for (; el_b; el_b = el_b->next) { - const float len = bm_edgeloop_offset_length(el_a, el_b, el_b_first, len_best); - if (len < len_best) { - el_b_best = el_b; - len_best = len; - } - } - - if (el_b_best) { - BLI_listbase_rotate_first(lb_b, el_b_best); - } + ListBase *lb_a = BM_edgeloop_verts_get(el_store_a); + ListBase *lb_b = BM_edgeloop_verts_get(el_store_b); + LinkData *el_a = lb_a->first; + LinkData *el_b = lb_b->first; + LinkData *el_b_first = el_b; + LinkData *el_b_best = NULL; + + float len_best = FLT_MAX; + + for (; el_b; el_b = el_b->next) { + const float len = bm_edgeloop_offset_length(el_a, el_b, el_b_first, len_best); + if (len < len_best) { + el_b_best = el_b; + len_best = len; + } + } + + if (el_b_best) { + BLI_listbase_rotate_first(lb_b, el_b_best); + } } static void bm_face_edges_tag_out(BMesh *bm, BMFace *f) { - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BMO_edge_flag_enable(bm, l_iter->e, EDGE_OUT); - } while ((l_iter = l_iter->next) != l_first); + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BMO_edge_flag_enable(bm, l_iter->e, EDGE_OUT); + } while ((l_iter = l_iter->next) != l_first); } static bool bm_edge_test_cb(BMEdge *e, void *bm_v) { - return BMO_edge_flag_test((BMesh *)bm_v, e, EDGE_MARK); + return BMO_edge_flag_test((BMesh *)bm_v, e, EDGE_MARK); } -static void bridge_loop_pair( - BMesh *bm, - struct BMEdgeLoopStore *el_store_a, - struct BMEdgeLoopStore *el_store_b, - const bool use_merge, const float merge_factor, const int twist_offset) +static void bridge_loop_pair(BMesh *bm, + struct BMEdgeLoopStore *el_store_a, + struct BMEdgeLoopStore *el_store_b, + const bool use_merge, + const float merge_factor, + const int twist_offset) { - const float eps = 0.00001f; - LinkData *el_a_first, *el_b_first; - const bool is_closed = BM_edgeloop_is_closed(el_store_a) && BM_edgeloop_is_closed(el_store_b); - int el_store_a_len, el_store_b_len; - bool el_store_b_free = false; - float el_dir[3]; - float dot_a, dot_b; - const bool use_edgeout = true; - - el_store_a_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_a); - el_store_b_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_b); - - if (el_store_a_len < el_store_b_len) { - SWAP(int, el_store_a_len, el_store_b_len); - SWAP(struct BMEdgeLoopStore *, el_store_a, el_store_b); - } - - if (use_merge) { - BLI_assert((el_store_a_len == el_store_b_len)); - } - - if (el_store_a_len != el_store_b_len) { - BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false); - } - - sub_v3_v3v3(el_dir, BM_edgeloop_center_get(el_store_a), BM_edgeloop_center_get(el_store_b)); - - if (is_closed) { - /* if all loops are closed this will calculate twice for all loops */ - BM_edgeloop_calc_normal(bm, el_store_a); - BM_edgeloop_calc_normal(bm, el_store_b); - } - else { - ListBase *lb_a = BM_edgeloop_verts_get(el_store_a); - ListBase *lb_b = BM_edgeloop_verts_get(el_store_b); - - /* normalizing isn't strictly needed but without we may get very large values */ - float no[3]; - float dir_a_orig[3], dir_b_orig[3]; - float dir_a[3], dir_b[3]; - const float *test_a, *test_b; - - sub_v3_v3v3(dir_a_orig, - ((BMVert *)(((LinkData *)lb_a->first)->data))->co, - ((BMVert *)(((LinkData *)lb_a->last)->data))->co); - sub_v3_v3v3(dir_b_orig, - ((BMVert *)(((LinkData *)lb_b->first)->data))->co, - ((BMVert *)(((LinkData *)lb_b->last)->data))->co); - - /* make the directions point out from the normals, 'no' is used as a temp var */ - cross_v3_v3v3(no, dir_a_orig, el_dir); cross_v3_v3v3(dir_a, no, el_dir); - cross_v3_v3v3(no, dir_b_orig, el_dir); cross_v3_v3v3(dir_b, no, el_dir); - - if (LIKELY(!is_zero_v3(dir_a) && !is_zero_v3(dir_b))) { - test_a = dir_a; - test_b = dir_b; - } - else { - /** - * This is a corner case: - * - * <pre> - * (loop a) (loop b) - * +--------+ +--------+ - * </pre> - * - * When loops are aligned to the direction between the loops values of 'dir_a/b' is degenerate, - * in this case compare the original directions (before they were corrected by 'el_dir'), see: T43013 - */ - test_a = dir_a_orig; - test_b = dir_b_orig; - } - - if (dot_v3v3(test_a, test_b) < 0.0f) { - BM_edgeloop_flip(bm, el_store_b); - } - - normalize_v3_v3(no, el_dir); - BM_edgeloop_calc_normal_aligned(bm, el_store_a, no); - BM_edgeloop_calc_normal_aligned(bm, el_store_b, no); - } - - dot_a = dot_v3v3(BM_edgeloop_normal_get(el_store_a), el_dir); - dot_b = dot_v3v3(BM_edgeloop_normal_get(el_store_b), el_dir); - - if (UNLIKELY((len_squared_v3(el_dir) < eps) || - ((fabsf(dot_a) < eps) && (fabsf(dot_b) < eps)))) - { - /* in this case there is no depth between the two loops, - * eg: 2x 2d circles, one scaled smaller, - * in this case 'el_dir' cant be used, just ensure we have matching flipping. */ - if (dot_v3v3(BM_edgeloop_normal_get(el_store_a), - BM_edgeloop_normal_get(el_store_b)) < 0.0f) - { - BM_edgeloop_flip(bm, el_store_b); - } - } - else if ((dot_a < 0.0f) != (dot_b < 0.0f)) { - BM_edgeloop_flip(bm, el_store_b); - } - - /* we only care about flipping if we make faces */ - if (use_merge == false) { - float no[3]; - - add_v3_v3v3(no, BM_edgeloop_normal_get(el_store_a), BM_edgeloop_normal_get(el_store_b)); - - if (dot_v3v3(no, el_dir) < 0.0f) { - BM_edgeloop_flip(bm, el_store_a); - BM_edgeloop_flip(bm, el_store_b); - } - - /* vote on winding (so new face winding is based on existing connected faces) */ - if (bm->totface) { - struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b}; - int i; - int winding_votes[2] = {0, 0}; - int winding_dir = 1; - for (i = 0; i < 2; i++, winding_dir = -winding_dir) { - LinkData *el; - for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) { - LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el); - if (el_next) { - BMEdge *e = BM_edge_exists(el->data, el_next->data); - if (e && BM_edge_is_boundary(e)) { - winding_votes[i] += ((e->l->v == el->data) ? winding_dir : -winding_dir); - } - } - } - } - - if (winding_votes[0] || winding_votes[1]) { - bool flip[2] = {false, false}; - - /* for direction aligned loops we can't rely on the directly we have, - * use the winding defined by the connected faces (see T48356). */ - if (fabsf(dot_a) < eps) { - if (winding_votes[0] < 0) { - flip[0] = !flip[0]; - winding_votes[0] *= -1; - - } - } - if (fabsf(dot_b) < eps) { - if (winding_votes[1] < 0) { - flip[1] = !flip[1]; - winding_votes[1] *= -1; - } - } - - /* when both loops contradict the winding, flip them so surrounding geometry matches */ - if ((winding_votes[0] + winding_votes[1]) < 0) { - flip[0] = !flip[0]; - flip[1] = !flip[1]; - - /* valid but unused */ + const float eps = 0.00001f; + LinkData *el_a_first, *el_b_first; + const bool is_closed = BM_edgeloop_is_closed(el_store_a) && BM_edgeloop_is_closed(el_store_b); + int el_store_a_len, el_store_b_len; + bool el_store_b_free = false; + float el_dir[3]; + float dot_a, dot_b; + const bool use_edgeout = true; + + el_store_a_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_a); + el_store_b_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_b); + + if (el_store_a_len < el_store_b_len) { + SWAP(int, el_store_a_len, el_store_b_len); + SWAP(struct BMEdgeLoopStore *, el_store_a, el_store_b); + } + + if (use_merge) { + BLI_assert((el_store_a_len == el_store_b_len)); + } + + if (el_store_a_len != el_store_b_len) { + BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false); + } + + sub_v3_v3v3(el_dir, BM_edgeloop_center_get(el_store_a), BM_edgeloop_center_get(el_store_b)); + + if (is_closed) { + /* if all loops are closed this will calculate twice for all loops */ + BM_edgeloop_calc_normal(bm, el_store_a); + BM_edgeloop_calc_normal(bm, el_store_b); + } + else { + ListBase *lb_a = BM_edgeloop_verts_get(el_store_a); + ListBase *lb_b = BM_edgeloop_verts_get(el_store_b); + + /* normalizing isn't strictly needed but without we may get very large values */ + float no[3]; + float dir_a_orig[3], dir_b_orig[3]; + float dir_a[3], dir_b[3]; + const float *test_a, *test_b; + + sub_v3_v3v3(dir_a_orig, + ((BMVert *)(((LinkData *)lb_a->first)->data))->co, + ((BMVert *)(((LinkData *)lb_a->last)->data))->co); + sub_v3_v3v3(dir_b_orig, + ((BMVert *)(((LinkData *)lb_b->first)->data))->co, + ((BMVert *)(((LinkData *)lb_b->last)->data))->co); + + /* make the directions point out from the normals, 'no' is used as a temp var */ + cross_v3_v3v3(no, dir_a_orig, el_dir); + cross_v3_v3v3(dir_a, no, el_dir); + cross_v3_v3v3(no, dir_b_orig, el_dir); + cross_v3_v3v3(dir_b, no, el_dir); + + if (LIKELY(!is_zero_v3(dir_a) && !is_zero_v3(dir_b))) { + test_a = dir_a; + test_b = dir_b; + } + else { + /** + * This is a corner case: + * + * <pre> + * (loop a) (loop b) + * +--------+ +--------+ + * </pre> + * + * When loops are aligned to the direction between the loops values of 'dir_a/b' is degenerate, + * in this case compare the original directions (before they were corrected by 'el_dir'), see: T43013 + */ + test_a = dir_a_orig; + test_b = dir_b_orig; + } + + if (dot_v3v3(test_a, test_b) < 0.0f) { + BM_edgeloop_flip(bm, el_store_b); + } + + normalize_v3_v3(no, el_dir); + BM_edgeloop_calc_normal_aligned(bm, el_store_a, no); + BM_edgeloop_calc_normal_aligned(bm, el_store_b, no); + } + + dot_a = dot_v3v3(BM_edgeloop_normal_get(el_store_a), el_dir); + dot_b = dot_v3v3(BM_edgeloop_normal_get(el_store_b), el_dir); + + if (UNLIKELY((len_squared_v3(el_dir) < eps) || ((fabsf(dot_a) < eps) && (fabsf(dot_b) < eps)))) { + /* in this case there is no depth between the two loops, + * eg: 2x 2d circles, one scaled smaller, + * in this case 'el_dir' cant be used, just ensure we have matching flipping. */ + if (dot_v3v3(BM_edgeloop_normal_get(el_store_a), BM_edgeloop_normal_get(el_store_b)) < 0.0f) { + BM_edgeloop_flip(bm, el_store_b); + } + } + else if ((dot_a < 0.0f) != (dot_b < 0.0f)) { + BM_edgeloop_flip(bm, el_store_b); + } + + /* we only care about flipping if we make faces */ + if (use_merge == false) { + float no[3]; + + add_v3_v3v3(no, BM_edgeloop_normal_get(el_store_a), BM_edgeloop_normal_get(el_store_b)); + + if (dot_v3v3(no, el_dir) < 0.0f) { + BM_edgeloop_flip(bm, el_store_a); + BM_edgeloop_flip(bm, el_store_b); + } + + /* vote on winding (so new face winding is based on existing connected faces) */ + if (bm->totface) { + struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b}; + int i; + int winding_votes[2] = {0, 0}; + int winding_dir = 1; + for (i = 0; i < 2; i++, winding_dir = -winding_dir) { + LinkData *el; + for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) { + LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el); + if (el_next) { + BMEdge *e = BM_edge_exists(el->data, el_next->data); + if (e && BM_edge_is_boundary(e)) { + winding_votes[i] += ((e->l->v == el->data) ? winding_dir : -winding_dir); + } + } + } + } + + if (winding_votes[0] || winding_votes[1]) { + bool flip[2] = {false, false}; + + /* for direction aligned loops we can't rely on the directly we have, + * use the winding defined by the connected faces (see T48356). */ + if (fabsf(dot_a) < eps) { + if (winding_votes[0] < 0) { + flip[0] = !flip[0]; + winding_votes[0] *= -1; + } + } + if (fabsf(dot_b) < eps) { + if (winding_votes[1] < 0) { + flip[1] = !flip[1]; + winding_votes[1] *= -1; + } + } + + /* when both loops contradict the winding, flip them so surrounding geometry matches */ + if ((winding_votes[0] + winding_votes[1]) < 0) { + flip[0] = !flip[0]; + flip[1] = !flip[1]; + + /* valid but unused */ #if 0 - winding_votes[0] *= -1; - winding_votes[1] *= -1; + winding_votes[0] *= -1; + winding_votes[1] *= -1; #endif - } - - if (flip[0]) { - BM_edgeloop_flip(bm, el_store_a); - } - if (flip[1]) { - BM_edgeloop_flip(bm, el_store_b); - } - } - } - } - - if (el_store_a_len > el_store_b_len) { - el_store_b = BM_edgeloop_copy(el_store_b); - BM_edgeloop_expand(bm, el_store_b, el_store_a_len, false, NULL); - el_store_b_free = true; - } - - if (is_closed) { - bm_bridge_best_rotation(el_store_a, el_store_b); - - /* add twist */ - if (twist_offset != 0) { - const int len_b = BM_edgeloop_length_get(el_store_b); - ListBase *lb_b = BM_edgeloop_verts_get(el_store_b); - LinkData *el_b = BLI_rfindlink(lb_b, mod_i(twist_offset, len_b)); - BLI_listbase_rotate_first(lb_b, el_b); - } - } - - /* Assign after flipping is finalized */ - el_a_first = BM_edgeloop_verts_get(el_store_a)->first; - el_b_first = BM_edgeloop_verts_get(el_store_b)->first; - - - if (use_merge) { - bm_bridge_splice_loops(bm, el_a_first, el_b_first, merge_factor); - } - else { - LinkData *el_a = el_a_first; - LinkData *el_b = el_b_first; - - LinkData *el_a_next; - LinkData *el_b_next; - - - while (true) { - BMFace *f, *f_example; - BMLoop *l_iter; - BMVert *v_a, *v_b, *v_a_next, *v_b_next; - - BMLoop *l_a = NULL; - BMLoop *l_b = NULL; - BMLoop *l_a_next = NULL; - BMLoop *l_b_next = NULL; - - if (is_closed) { - el_a_next = BM_EDGELINK_NEXT(el_store_a, el_a); - el_b_next = BM_EDGELINK_NEXT(el_store_b, el_b); - } - else { - el_a_next = el_a->next; - el_b_next = el_b->next; - if (ELEM(NULL, el_a_next, el_b_next)) { - break; - } - } - - v_a = el_a->data; - v_b = el_b->data; - v_a_next = el_a_next->data; - v_b_next = el_b_next->data; - - /* get loop data - before making the face */ - if (v_b != v_b_next) { - bm_vert_loop_pair(bm, v_a, v_a_next, &l_a, &l_a_next); - bm_vert_loop_pair(bm, v_b, v_b_next, &l_b, &l_b_next); - } - else { - /* lazy, could be more clever here */ - bm_vert_loop_pair(bm, v_a, v_a_next, &l_a, &l_a_next); - l_b = l_b_next = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v_b, 0); - } - - if (l_a && l_a_next == NULL) { l_a_next = l_a; } - if (l_a_next && l_a == NULL) { l_a = l_a_next; } - if (l_b && l_b_next == NULL) { l_b_next = l_b; } - if (l_b_next && l_b == NULL) { l_b = l_b_next; } - f_example = l_a ? l_a->f : (l_b ? l_b->f : NULL); - - if (v_b != v_b_next) { - BMVert *v_arr[4] = {v_a, v_b, v_b_next, v_a_next}; - f = BM_face_exists(v_arr, 4); - if (f == NULL) { - /* copy if loop data if its is missing on one ring */ - f = BM_face_create_verts(bm, v_arr, 4, NULL, BM_CREATE_NOP, true); - - l_iter = BM_FACE_FIRST_LOOP(f); - if (l_b) { BM_elem_attrs_copy(bm, bm, l_b, l_iter); } l_iter = l_iter->next; - if (l_b_next) { BM_elem_attrs_copy(bm, bm, l_b_next, l_iter); } l_iter = l_iter->next; - if (l_a_next) { BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); } l_iter = l_iter->next; - if (l_a) { BM_elem_attrs_copy(bm, bm, l_a, l_iter); } - } - } - else { - BMVert *v_arr[3] = {v_a, v_b, v_a_next}; - f = BM_face_exists(v_arr, 3); - if (f == NULL) { - /* fan-fill a triangle */ - f = BM_face_create_verts(bm, v_arr, 3, NULL, BM_CREATE_NOP, true); - - l_iter = BM_FACE_FIRST_LOOP(f); - if (l_b) { BM_elem_attrs_copy(bm, bm, l_b, l_iter); } l_iter = l_iter->next; - if (l_a_next) { BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); } l_iter = l_iter->next; - if (l_a) { BM_elem_attrs_copy(bm, bm, l_a, l_iter); } - } - } - - if (f_example && (f_example != f)) { - BM_elem_attrs_copy(bm, bm, f_example, f); - } - BMO_face_flag_enable(bm, f, FACE_OUT); - BM_elem_flag_enable(f, BM_ELEM_TAG); - - /* tag all edges of the face, untag the loop edges after */ - if (use_edgeout) { - bm_face_edges_tag_out(bm, f); - } - - if (el_a_next == el_a_first) { - break; - } - - el_a = el_a_next; - el_b = el_b_next; - } - } - - if (el_store_a_len != el_store_b_len) { - struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b}; - int i; - - BMOperator op_sub; - /* when we have to bridge between different sized edge-loops, - * be clever and post-process for best results */ - - - /* triangulate inline */ - BMO_op_initf(bm, &op_sub, 0, - "triangulate faces=%hf", - BM_ELEM_TAG, true); - /* calc normals for input faces before executing */ - { - BMOIter siter; - BMFace *f; - BMO_ITER (f, &siter, op_sub.slots_in, "faces", BM_FACE) { - BM_face_normal_update(f); - } - } - BMO_op_exec(bm, &op_sub); - BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "faces.out", BM_FACE, FACE_OUT); - BMO_slot_buffer_hflag_enable(bm, op_sub.slots_out, "faces.out", BM_FACE, BM_ELEM_TAG, false); - BMO_op_finish(bm, &op_sub); - - - /* tag verts on each side so we can restrict rotation of edges to verts on the same side */ - for (i = 0; i < 2; i++) { - LinkData *el; - for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) { - BM_elem_flag_set((BMVert *)el->data, BM_ELEM_TAG, i); - } - } - - - BMO_op_initf(bm, &op_sub, 0, - "beautify_fill faces=%hf edges=ae use_restrict_tag=%b method=%i", - BM_ELEM_TAG, true, 1); - - if (use_edgeout) { - BMOIter siter; - BMFace *f; - BMO_ITER (f, &siter, op_sub.slots_in, "faces", BM_FACE) { - BMO_face_flag_enable(bm, f, FACE_OUT); - bm_face_edges_tag_out(bm, f); - } - } - - BMO_op_exec(bm, &op_sub); - /* there may also be tagged faces that didnt rotate, mark input */ - - if (use_edgeout) { - BMOIter siter; - BMFace *f; - BMO_ITER (f, &siter, op_sub.slots_out, "geom.out", BM_FACE) { - BMO_face_flag_enable(bm, f, FACE_OUT); - bm_face_edges_tag_out(bm, f); - } - } - else { - BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "geom.out", BM_FACE, FACE_OUT); - } - - BMO_op_finish(bm, &op_sub); - } - - if (use_edgeout && use_merge == false) { - /* we've enabled all face edges above, now disable all loop edges */ - struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b}; - int i; - for (i = 0; i < 2; i++) { - LinkData *el; - for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) { - LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el); - if (el_next) { - if (el->data != el_next->data) { - BMEdge *e = BM_edge_exists(el->data, el_next->data); - BMO_edge_flag_disable(bm, e, EDGE_OUT); - } - } - } - } - } - - if (el_store_b_free) { - BM_edgeloop_free(el_store_b); - } + } + + if (flip[0]) { + BM_edgeloop_flip(bm, el_store_a); + } + if (flip[1]) { + BM_edgeloop_flip(bm, el_store_b); + } + } + } + } + + if (el_store_a_len > el_store_b_len) { + el_store_b = BM_edgeloop_copy(el_store_b); + BM_edgeloop_expand(bm, el_store_b, el_store_a_len, false, NULL); + el_store_b_free = true; + } + + if (is_closed) { + bm_bridge_best_rotation(el_store_a, el_store_b); + + /* add twist */ + if (twist_offset != 0) { + const int len_b = BM_edgeloop_length_get(el_store_b); + ListBase *lb_b = BM_edgeloop_verts_get(el_store_b); + LinkData *el_b = BLI_rfindlink(lb_b, mod_i(twist_offset, len_b)); + BLI_listbase_rotate_first(lb_b, el_b); + } + } + + /* Assign after flipping is finalized */ + el_a_first = BM_edgeloop_verts_get(el_store_a)->first; + el_b_first = BM_edgeloop_verts_get(el_store_b)->first; + + if (use_merge) { + bm_bridge_splice_loops(bm, el_a_first, el_b_first, merge_factor); + } + else { + LinkData *el_a = el_a_first; + LinkData *el_b = el_b_first; + + LinkData *el_a_next; + LinkData *el_b_next; + + while (true) { + BMFace *f, *f_example; + BMLoop *l_iter; + BMVert *v_a, *v_b, *v_a_next, *v_b_next; + + BMLoop *l_a = NULL; + BMLoop *l_b = NULL; + BMLoop *l_a_next = NULL; + BMLoop *l_b_next = NULL; + + if (is_closed) { + el_a_next = BM_EDGELINK_NEXT(el_store_a, el_a); + el_b_next = BM_EDGELINK_NEXT(el_store_b, el_b); + } + else { + el_a_next = el_a->next; + el_b_next = el_b->next; + if (ELEM(NULL, el_a_next, el_b_next)) { + break; + } + } + + v_a = el_a->data; + v_b = el_b->data; + v_a_next = el_a_next->data; + v_b_next = el_b_next->data; + + /* get loop data - before making the face */ + if (v_b != v_b_next) { + bm_vert_loop_pair(bm, v_a, v_a_next, &l_a, &l_a_next); + bm_vert_loop_pair(bm, v_b, v_b_next, &l_b, &l_b_next); + } + else { + /* lazy, could be more clever here */ + bm_vert_loop_pair(bm, v_a, v_a_next, &l_a, &l_a_next); + l_b = l_b_next = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v_b, 0); + } + + if (l_a && l_a_next == NULL) { + l_a_next = l_a; + } + if (l_a_next && l_a == NULL) { + l_a = l_a_next; + } + if (l_b && l_b_next == NULL) { + l_b_next = l_b; + } + if (l_b_next && l_b == NULL) { + l_b = l_b_next; + } + f_example = l_a ? l_a->f : (l_b ? l_b->f : NULL); + + if (v_b != v_b_next) { + BMVert *v_arr[4] = {v_a, v_b, v_b_next, v_a_next}; + f = BM_face_exists(v_arr, 4); + if (f == NULL) { + /* copy if loop data if its is missing on one ring */ + f = BM_face_create_verts(bm, v_arr, 4, NULL, BM_CREATE_NOP, true); + + l_iter = BM_FACE_FIRST_LOOP(f); + if (l_b) { + BM_elem_attrs_copy(bm, bm, l_b, l_iter); + } + l_iter = l_iter->next; + if (l_b_next) { + BM_elem_attrs_copy(bm, bm, l_b_next, l_iter); + } + l_iter = l_iter->next; + if (l_a_next) { + BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); + } + l_iter = l_iter->next; + if (l_a) { + BM_elem_attrs_copy(bm, bm, l_a, l_iter); + } + } + } + else { + BMVert *v_arr[3] = {v_a, v_b, v_a_next}; + f = BM_face_exists(v_arr, 3); + if (f == NULL) { + /* fan-fill a triangle */ + f = BM_face_create_verts(bm, v_arr, 3, NULL, BM_CREATE_NOP, true); + + l_iter = BM_FACE_FIRST_LOOP(f); + if (l_b) { + BM_elem_attrs_copy(bm, bm, l_b, l_iter); + } + l_iter = l_iter->next; + if (l_a_next) { + BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); + } + l_iter = l_iter->next; + if (l_a) { + BM_elem_attrs_copy(bm, bm, l_a, l_iter); + } + } + } + + if (f_example && (f_example != f)) { + BM_elem_attrs_copy(bm, bm, f_example, f); + } + BMO_face_flag_enable(bm, f, FACE_OUT); + BM_elem_flag_enable(f, BM_ELEM_TAG); + + /* tag all edges of the face, untag the loop edges after */ + if (use_edgeout) { + bm_face_edges_tag_out(bm, f); + } + + if (el_a_next == el_a_first) { + break; + } + + el_a = el_a_next; + el_b = el_b_next; + } + } + + if (el_store_a_len != el_store_b_len) { + struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b}; + int i; + + BMOperator op_sub; + /* when we have to bridge between different sized edge-loops, + * be clever and post-process for best results */ + + /* triangulate inline */ + BMO_op_initf(bm, &op_sub, 0, "triangulate faces=%hf", BM_ELEM_TAG, true); + /* calc normals for input faces before executing */ + { + BMOIter siter; + BMFace *f; + BMO_ITER (f, &siter, op_sub.slots_in, "faces", BM_FACE) { + BM_face_normal_update(f); + } + } + BMO_op_exec(bm, &op_sub); + BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "faces.out", BM_FACE, FACE_OUT); + BMO_slot_buffer_hflag_enable(bm, op_sub.slots_out, "faces.out", BM_FACE, BM_ELEM_TAG, false); + BMO_op_finish(bm, &op_sub); + + /* tag verts on each side so we can restrict rotation of edges to verts on the same side */ + for (i = 0; i < 2; i++) { + LinkData *el; + for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) { + BM_elem_flag_set((BMVert *)el->data, BM_ELEM_TAG, i); + } + } + + BMO_op_initf(bm, + &op_sub, + 0, + "beautify_fill faces=%hf edges=ae use_restrict_tag=%b method=%i", + BM_ELEM_TAG, + true, + 1); + + if (use_edgeout) { + BMOIter siter; + BMFace *f; + BMO_ITER (f, &siter, op_sub.slots_in, "faces", BM_FACE) { + BMO_face_flag_enable(bm, f, FACE_OUT); + bm_face_edges_tag_out(bm, f); + } + } + + BMO_op_exec(bm, &op_sub); + /* there may also be tagged faces that didnt rotate, mark input */ + + if (use_edgeout) { + BMOIter siter; + BMFace *f; + BMO_ITER (f, &siter, op_sub.slots_out, "geom.out", BM_FACE) { + BMO_face_flag_enable(bm, f, FACE_OUT); + bm_face_edges_tag_out(bm, f); + } + } + else { + BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "geom.out", BM_FACE, FACE_OUT); + } + + BMO_op_finish(bm, &op_sub); + } + + if (use_edgeout && use_merge == false) { + /* we've enabled all face edges above, now disable all loop edges */ + struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b}; + int i; + for (i = 0; i < 2; i++) { + LinkData *el; + for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) { + LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el); + if (el_next) { + if (el->data != el_next->data) { + BMEdge *e = BM_edge_exists(el->data, el_next->data); + BMO_edge_flag_disable(bm, e, EDGE_OUT); + } + } + } + } + } + + if (el_store_b_free) { + BM_edgeloop_free(el_store_b); + } } void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) { - ListBase eloops = {NULL}; - LinkData *el_store; - - /* merge-bridge support */ - const bool use_pairs = BMO_slot_bool_get(op->slots_in, "use_pairs"); - const bool use_merge = BMO_slot_bool_get(op->slots_in, "use_merge"); - const float merge_factor = BMO_slot_float_get(op->slots_in, "merge_factor"); - const bool use_cyclic = BMO_slot_bool_get(op->slots_in, "use_cyclic") && (use_merge == false); - const int twist_offset = BMO_slot_int_get(op->slots_in, "twist_offset"); - int count; - bool changed = false; - - BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); - - count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, bm); - - BM_mesh_edgeloops_calc_center(bm, &eloops); - - if (count < 2) { - BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, - "Select at least two edge loops"); - goto cleanup; - } - - if (use_pairs && (count % 2)) { - BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, - "Select an even number of loops to bridge pairs"); - goto cleanup; - } - - if (use_merge) { - bool match = true; - const int eloop_len = BM_edgeloop_length_get(eloops.first); - for (el_store = eloops.first; el_store; el_store = el_store->next) { - if (eloop_len != BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store)) { - match = false; - break; - } - } - if (!match) { - BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, - "Selected loops must have equal edge counts"); - goto cleanup; - } - } - - if (count > 2) { - if (use_pairs) { - BM_mesh_edgeloops_calc_normal(bm, &eloops); - } - BM_mesh_edgeloops_calc_order(bm, &eloops, use_pairs); - } - - for (el_store = eloops.first; el_store; el_store = el_store->next) { - LinkData *el_store_next = el_store->next; - - if (el_store_next == NULL) { - if (use_cyclic && (count > 2)) { - el_store_next = eloops.first; - } - else { - break; - } - } - - bridge_loop_pair(bm, - (struct BMEdgeLoopStore *)el_store, - (struct BMEdgeLoopStore *)el_store_next, - use_merge, merge_factor, twist_offset); - if (use_pairs) { - el_store = el_store->next; - } - changed = true; - } + ListBase eloops = {NULL}; + LinkData *el_store; + + /* merge-bridge support */ + const bool use_pairs = BMO_slot_bool_get(op->slots_in, "use_pairs"); + const bool use_merge = BMO_slot_bool_get(op->slots_in, "use_merge"); + const float merge_factor = BMO_slot_float_get(op->slots_in, "merge_factor"); + const bool use_cyclic = BMO_slot_bool_get(op->slots_in, "use_cyclic") && (use_merge == false); + const int twist_offset = BMO_slot_int_get(op->slots_in, "twist_offset"); + int count; + bool changed = false; + + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); + + count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, bm); + + BM_mesh_edgeloops_calc_center(bm, &eloops); + + if (count < 2) { + BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Select at least two edge loops"); + goto cleanup; + } + + if (use_pairs && (count % 2)) { + BMO_error_raise( + bm, op, BMERR_INVALID_SELECTION, "Select an even number of loops to bridge pairs"); + goto cleanup; + } + + if (use_merge) { + bool match = true; + const int eloop_len = BM_edgeloop_length_get(eloops.first); + for (el_store = eloops.first; el_store; el_store = el_store->next) { + if (eloop_len != BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store)) { + match = false; + break; + } + } + if (!match) { + BMO_error_raise( + bm, op, BMERR_INVALID_SELECTION, "Selected loops must have equal edge counts"); + goto cleanup; + } + } + + if (count > 2) { + if (use_pairs) { + BM_mesh_edgeloops_calc_normal(bm, &eloops); + } + BM_mesh_edgeloops_calc_order(bm, &eloops, use_pairs); + } + + for (el_store = eloops.first; el_store; el_store = el_store->next) { + LinkData *el_store_next = el_store->next; + + if (el_store_next == NULL) { + if (use_cyclic && (count > 2)) { + el_store_next = eloops.first; + } + else { + break; + } + } + + bridge_loop_pair(bm, + (struct BMEdgeLoopStore *)el_store, + (struct BMEdgeLoopStore *)el_store_next, + use_merge, + merge_factor, + twist_offset); + if (use_pairs) { + el_store = el_store->next; + } + changed = true; + } cleanup: - BM_mesh_edgeloops_free(&eloops); - - if (changed) { - if (use_merge == false) { - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT); - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT); - } - } + BM_mesh_edgeloops_free(&eloops); + + if (changed) { + if (use_merge == false) { + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT); + } + } } |