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/intern | |
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/intern')
48 files changed, 21007 insertions, 20613 deletions
diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.c b/source/blender/bmesh/intern/bmesh_callback_generic.c index 07a23cd0471..27e808895cd 100644 --- a/source/blender/bmesh/intern/bmesh_callback_generic.c +++ b/source/blender/bmesh/intern/bmesh_callback_generic.c @@ -28,29 +28,28 @@ bool BM_elem_cb_check_hflag_ex(BMElem *ele, void *user_data) { - const uint hflag_pair = POINTER_AS_INT(user_data); - const char hflag_p = (hflag_pair & 0xff); - const char hflag_n = (hflag_pair >> 8); + const uint hflag_pair = POINTER_AS_INT(user_data); + const char hflag_p = (hflag_pair & 0xff); + const char hflag_n = (hflag_pair >> 8); - return ((BM_elem_flag_test(ele, hflag_p) != 0) && - (BM_elem_flag_test(ele, hflag_n) == 0)); + return ((BM_elem_flag_test(ele, hflag_p) != 0) && (BM_elem_flag_test(ele, hflag_n) == 0)); } bool BM_elem_cb_check_hflag_enabled(BMElem *ele, void *user_data) { - const char hflag = POINTER_AS_INT(user_data); + const char hflag = POINTER_AS_INT(user_data); - return (BM_elem_flag_test(ele, hflag) != 0); + return (BM_elem_flag_test(ele, hflag) != 0); } bool BM_elem_cb_check_hflag_disabled(BMElem *ele, void *user_data) { - const char hflag = POINTER_AS_INT(user_data); + const char hflag = POINTER_AS_INT(user_data); - return (BM_elem_flag_test(ele, hflag) == 0); + return (BM_elem_flag_test(ele, hflag) == 0); } bool BM_elem_cb_check_elem_not_equal(BMElem *ele, void *user_data) { - return (ele != user_data); + return (ele != user_data); } diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.h b/source/blender/bmesh/intern/bmesh_callback_generic.h index d17e7a68ac8..5191bd31873 100644 --- a/source/blender/bmesh/intern/bmesh_callback_generic.h +++ b/source/blender/bmesh/intern/bmesh_callback_generic.h @@ -27,15 +27,13 @@ bool BM_elem_cb_check_hflag_ex(BMElem *, void *user_data); bool BM_elem_cb_check_elem_not_equal(BMElem *ele, void *user_data); #define BM_elem_cb_check_hflag_ex_simple(type, hflag_p, hflag_n) \ - (bool (*)(type, void *))BM_elem_cb_check_hflag_ex, \ - POINTER_FROM_UINT(((hflag_p) | (hflag_n << 8))) + (bool (*)(type, void *)) BM_elem_cb_check_hflag_ex, \ + POINTER_FROM_UINT(((hflag_p) | (hflag_n << 8))) #define BM_elem_cb_check_hflag_enabled_simple(type, hflag_p) \ - (bool (*)(type, void *))BM_elem_cb_check_hflag_enabled, \ - POINTER_FROM_UINT((hflag_p)) + (bool (*)(type, void *)) BM_elem_cb_check_hflag_enabled, POINTER_FROM_UINT((hflag_p)) #define BM_elem_cb_check_hflag_disabled_simple(type, hflag_n) \ - (bool (*)(type, void *))BM_elem_cb_check_hflag_disabled, \ - POINTER_FROM_UINT(hflag_n) + (bool (*)(type, void *)) BM_elem_cb_check_hflag_disabled, POINTER_FROM_UINT(hflag_n) #endif /* __BMESH_CALLBACK_GENERIC_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index c24a5b21b6c..0528a550be4 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -38,7 +38,6 @@ #define SELECT 1 - /** * Fill in a vertex array from an edge array. * @@ -46,15 +45,15 @@ */ bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len) { - int i, i_prev = len - 1; - for (i = 0; i < len; i++) { - vert_arr[i] = BM_edge_share_vert(edge_arr[i_prev], edge_arr[i]); - if (vert_arr[i] == NULL) { - return false; - } - i_prev = i; - } - return true; + int i, i_prev = len - 1; + for (i = 0; i < len; i++) { + vert_arr[i] = BM_edge_share_vert(edge_arr[i_prev], edge_arr[i]); + if (vert_arr[i] == NULL) { + return false; + } + i_prev = i; + } + return true; } /** @@ -64,15 +63,15 @@ bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len) */ bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len) { - int i, i_prev = len - 1; - for (i = 0; i < len; i++) { - edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]); - if (edge_arr[i_prev] == NULL) { - return false; - } - i_prev = i; - } - return true; + int i, i_prev = len - 1; + for (i = 0; i < len; i++) { + edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]); + if (edge_arr[i_prev] == NULL) { + return false; + } + i_prev = i; + } + return true; } /** @@ -81,17 +80,20 @@ bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len) */ void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len) { - int i, i_prev = len - 1; - for (i = 0; i < len; i++) { - edge_arr[i_prev] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE); - i_prev = i; - } + int i, i_prev = len - 1; + for (i = 0; i < len; i++) { + edge_arr[i_prev] = BM_edge_create( + bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE); + i_prev = i; + } } /* prototypes */ -static void bm_loop_attrs_copy( - BMesh *source_mesh, BMesh *target_mesh, - const BMLoop *source_loop, BMLoop *target_loop, uint64_t cd_mask); +static void bm_loop_attrs_copy(BMesh *source_mesh, + BMesh *target_mesh, + const BMLoop *source_loop, + BMLoop *target_loop, + uint64_t cd_mask); /** * \brief Make Quad/Triangle @@ -107,13 +109,16 @@ static void bm_loop_attrs_copy( * of the vertices in the vertex array. */ -BMFace *BM_face_create_quad_tri( - BMesh *bm, - BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - const BMFace *f_example, const eBMCreateFlag create_flag) +BMFace *BM_face_create_quad_tri(BMesh *bm, + BMVert *v1, + BMVert *v2, + BMVert *v3, + BMVert *v4, + const BMFace *f_example, + const eBMCreateFlag create_flag) { - BMVert *vtar[4] = {v1, v2, v3, v4}; - return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true); + BMVert *vtar[4] = {v1, v2, v3, v4}; + return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true); } /** @@ -125,55 +130,52 @@ BMFace *BM_face_create_quad_tri( * this is done since the face may not be completely surrounded by faces, * this way: a quad with 2 connected quads on either side will still get all 4 loops updated */ -void BM_face_copy_shared( - BMesh *bm, BMFace *f, - BMLoopFilterFunc filter_fn, void *user_data) +void BM_face_copy_shared(BMesh *bm, BMFace *f, BMLoopFilterFunc filter_fn, void *user_data) { - BMLoop *l_first; - BMLoop *l_iter; + BMLoop *l_first; + BMLoop *l_iter; #ifdef DEBUG - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter, _FLAG_OVERLAP) == 0); - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter, _FLAG_OVERLAP) == 0); + } while ((l_iter = l_iter->next) != l_first); #endif - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BMLoop *l_other = l_iter->radial_next; - - if (l_other && l_other != l_iter) { - BMLoop *l_src[2]; - BMLoop *l_dst[2] = {l_iter, l_iter->next}; - uint j; - - if (l_other->v == l_iter->v) { - l_src[0] = l_other; - l_src[1] = l_other->next; - } - else { - l_src[0] = l_other->next; - l_src[1] = l_other; - } - - for (j = 0; j < 2; j++) { - BLI_assert(l_dst[j]->v == l_src[j]->v); - if (BM_ELEM_API_FLAG_TEST(l_dst[j], _FLAG_OVERLAP) == 0) { - if ((filter_fn == NULL) || filter_fn(l_src[j], user_data)) { - bm_loop_attrs_copy(bm, bm, l_src[j], l_dst[j], 0x0); - BM_ELEM_API_FLAG_ENABLE(l_dst[j], _FLAG_OVERLAP); - } - } - } - } - } while ((l_iter = l_iter->next) != l_first); - - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_ELEM_API_FLAG_DISABLE(l_iter, _FLAG_OVERLAP); - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BMLoop *l_other = l_iter->radial_next; + + if (l_other && l_other != l_iter) { + BMLoop *l_src[2]; + BMLoop *l_dst[2] = {l_iter, l_iter->next}; + uint j; + + if (l_other->v == l_iter->v) { + l_src[0] = l_other; + l_src[1] = l_other->next; + } + else { + l_src[0] = l_other->next; + l_src[1] = l_other; + } + + for (j = 0; j < 2; j++) { + BLI_assert(l_dst[j]->v == l_src[j]->v); + if (BM_ELEM_API_FLAG_TEST(l_dst[j], _FLAG_OVERLAP) == 0) { + if ((filter_fn == NULL) || filter_fn(l_src[j], user_data)) { + bm_loop_attrs_copy(bm, bm, l_src[j], l_dst[j], 0x0); + BM_ELEM_API_FLAG_ENABLE(l_dst[j], _FLAG_OVERLAP); + } + } + } + } + } while ((l_iter = l_iter->next) != l_first); + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BM_ELEM_API_FLAG_DISABLE(l_iter, _FLAG_OVERLAP); + } while ((l_iter = l_iter->next) != l_first); } /** @@ -183,80 +185,80 @@ void BM_face_copy_shared( * * All arrays must be \a len long. */ -static bool bm_edges_sort_winding( - BMVert *v1, BMVert *v2, - BMEdge **edges, const int len, - BMEdge **edges_sort, BMVert **verts_sort) +static bool bm_edges_sort_winding(BMVert *v1, + BMVert *v2, + BMEdge **edges, + const int len, + BMEdge **edges_sort, + BMVert **verts_sort) { - BMEdge *e_iter, *e_first; - BMVert *v_iter; - int i; - - /* all flags _must_ be cleared on exit! */ - for (i = 0; i < len; i++) { - BM_ELEM_API_FLAG_ENABLE(edges[i], _FLAG_MF); - BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV); - BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV); - } - - /* find first edge */ - i = 0; - v_iter = v1; - e_iter = e_first = v1->e; - do { - if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) && - (BM_edge_other_vert(e_iter, v_iter) == v2)) - { - i = 1; - break; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first); - if (i == 0) { - goto error; - } - - i = 0; - do { - /* entering loop will always succeed */ - if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) { - if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) { - /* vert is in loop multiple times */ - goto error; - } - - BM_ELEM_API_FLAG_DISABLE(e_iter, _FLAG_MF); - edges_sort[i] = e_iter; - - BM_ELEM_API_FLAG_DISABLE(v_iter, _FLAG_MV); - verts_sort[i] = v_iter; - - i += 1; - - /* walk onto the next vertex */ - v_iter = BM_edge_other_vert(e_iter, v_iter); - if (i == len) { - if (UNLIKELY(v_iter != verts_sort[0])) { - goto error; - } - break; - } - - e_first = e_iter; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first); - - if (i == len) { - return true; - } + BMEdge *e_iter, *e_first; + BMVert *v_iter; + int i; + + /* all flags _must_ be cleared on exit! */ + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_ENABLE(edges[i], _FLAG_MF); + BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV); + BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV); + } + + /* find first edge */ + i = 0; + v_iter = v1; + e_iter = e_first = v1->e; + do { + if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) && (BM_edge_other_vert(e_iter, v_iter) == v2)) { + i = 1; + break; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first); + if (i == 0) { + goto error; + } + + i = 0; + do { + /* entering loop will always succeed */ + if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) { + if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) { + /* vert is in loop multiple times */ + goto error; + } + + BM_ELEM_API_FLAG_DISABLE(e_iter, _FLAG_MF); + edges_sort[i] = e_iter; + + BM_ELEM_API_FLAG_DISABLE(v_iter, _FLAG_MV); + verts_sort[i] = v_iter; + + i += 1; + + /* walk onto the next vertex */ + v_iter = BM_edge_other_vert(e_iter, v_iter); + if (i == len) { + if (UNLIKELY(v_iter != verts_sort[0])) { + goto error; + } + break; + } + + e_first = e_iter; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first); + + if (i == len) { + return true; + } error: - for (i = 0; i < len; i++) { - BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF); - BM_ELEM_API_FLAG_DISABLE(edges[i]->v1, _FLAG_MV); - BM_ELEM_API_FLAG_DISABLE(edges[i]->v2, _FLAG_MV); - } + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF); + BM_ELEM_API_FLAG_DISABLE(edges[i]->v1, _FLAG_MV); + BM_ELEM_API_FLAG_DISABLE(edges[i]->v2, _FLAG_MV); + } - return false; + return false; } /** @@ -273,20 +275,24 @@ error: * #BM_face_create should be considered over this function as it * avoids some unnecessary work. */ -BMFace *BM_face_create_ngon( - BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag) +BMFace *BM_face_create_ngon(BMesh *bm, + BMVert *v1, + BMVert *v2, + BMEdge **edges, + const int len, + const BMFace *f_example, + const eBMCreateFlag create_flag) { - BMEdge **edges_sort = BLI_array_alloca(edges_sort, len); - BMVert **verts_sort = BLI_array_alloca(verts_sort, len); + BMEdge **edges_sort = BLI_array_alloca(edges_sort, len); + BMVert **verts_sort = BLI_array_alloca(verts_sort, len); - BLI_assert(len && v1 && v2 && edges && bm); + BLI_assert(len && v1 && v2 && edges && bm); - if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) { - return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag); - } + if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) { + return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag); + } - return NULL; + return NULL; } /** @@ -297,70 +303,69 @@ BMFace *BM_face_create_ngon( * - Optionally create edges between vertices. * - Uses verts so no need to find edges (handy when you only have verts) */ -BMFace *BM_face_create_ngon_verts( - BMesh *bm, BMVert **vert_arr, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, - const bool calc_winding, const bool create_edges) +BMFace *BM_face_create_ngon_verts(BMesh *bm, + BMVert **vert_arr, + const int len, + const BMFace *f_example, + const eBMCreateFlag create_flag, + const bool calc_winding, + const bool create_edges) { - BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); - uint winding[2] = {0, 0}; - int i, i_prev = len - 1; - BMVert *v_winding[2] = {vert_arr[i_prev], vert_arr[0]}; - - BLI_assert(len > 2); - - for (i = 0; i < len; i++) { - if (create_edges) { - edge_arr[i] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE); - } - else { - edge_arr[i] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]); - if (edge_arr[i] == NULL) { - return NULL; - } - } - - if (calc_winding) { - /* the edge may exist already and be attached to a face - * in this case we can find the best winding to use for the new face */ - if (edge_arr[i]->l) { - BMVert *test_v1, *test_v2; - /* we want to use the reverse winding to the existing order */ - BM_edge_ordered_verts(edge_arr[i], &test_v2, &test_v1); - winding[(vert_arr[i_prev] == test_v2)]++; - BLI_assert(vert_arr[i_prev] == test_v2 || vert_arr[i_prev] == test_v1); - } - } - - i_prev = i; - } - - /* --- */ - - if (calc_winding) { - if (winding[0] < winding[1]) { - winding[0] = 1; - winding[1] = 0; - } - else { - winding[0] = 0; - winding[1] = 1; - } - } - else { - winding[0] = 0; - winding[1] = 1; - } - - /* --- */ - - /* create the face */ - return BM_face_create_ngon( - bm, - v_winding[winding[0]], - v_winding[winding[1]], - edge_arr, len, - f_example, create_flag); + BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); + uint winding[2] = {0, 0}; + int i, i_prev = len - 1; + BMVert *v_winding[2] = {vert_arr[i_prev], vert_arr[0]}; + + BLI_assert(len > 2); + + for (i = 0; i < len; i++) { + if (create_edges) { + edge_arr[i] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE); + } + else { + edge_arr[i] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]); + if (edge_arr[i] == NULL) { + return NULL; + } + } + + if (calc_winding) { + /* the edge may exist already and be attached to a face + * in this case we can find the best winding to use for the new face */ + if (edge_arr[i]->l) { + BMVert *test_v1, *test_v2; + /* we want to use the reverse winding to the existing order */ + BM_edge_ordered_verts(edge_arr[i], &test_v2, &test_v1); + winding[(vert_arr[i_prev] == test_v2)]++; + BLI_assert(vert_arr[i_prev] == test_v2 || vert_arr[i_prev] == test_v1); + } + } + + i_prev = i; + } + + /* --- */ + + if (calc_winding) { + if (winding[0] < winding[1]) { + winding[0] = 1; + winding[1] = 0; + } + else { + winding[0] = 0; + winding[1] = 1; + } + } + else { + winding[0] = 0; + winding[1] = 1; + } + + /* --- */ + + /* create the face */ + return BM_face_create_ngon( + bm, v_winding[winding[0]], v_winding[winding[1]], edge_arr, len, f_example, create_flag); } /** @@ -381,158 +386,166 @@ BMFace *BM_face_create_ngon_verts( */ void BM_verts_sort_radial_plane(BMVert **vert_arr, int len) { - struct SortIntByFloat *vang = BLI_array_alloca(vang, len); - BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len); - - float totv_inv = 1.0f / (float)len; - int i = 0; + struct SortIntByFloat *vang = BLI_array_alloca(vang, len); + BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len); - float cent[3], nor[3]; + float totv_inv = 1.0f / (float)len; + int i = 0; - const float *far = NULL, *far_cross = NULL; + float cent[3], nor[3]; - float far_vec[3]; - float far_cross_vec[3]; - float sign_vec[3]; /* work out if we are pos/neg angle */ + const float *far = NULL, *far_cross = NULL; - float far_dist_sq, far_dist_max_sq; - float far_cross_dist, far_cross_best = 0.0f; + float far_vec[3]; + float far_cross_vec[3]; + float sign_vec[3]; /* work out if we are pos/neg angle */ - /* get the center point and collect vector array since we loop over these a lot */ - zero_v3(cent); - for (i = 0; i < len; i++) { - madd_v3_v3fl(cent, vert_arr[i]->co, totv_inv); - } + float far_dist_sq, far_dist_max_sq; + float far_cross_dist, far_cross_best = 0.0f; + /* get the center point and collect vector array since we loop over these a lot */ + zero_v3(cent); + for (i = 0; i < len; i++) { + madd_v3_v3fl(cent, vert_arr[i]->co, totv_inv); + } - /* find the far point from cent */ - far_dist_max_sq = 0.0f; - for (i = 0; i < len; i++) { - far_dist_sq = len_squared_v3v3(vert_arr[i]->co, cent); - if (far_dist_sq > far_dist_max_sq || far == NULL) { - far = vert_arr[i]->co; - far_dist_max_sq = far_dist_sq; - } - } + /* find the far point from cent */ + far_dist_max_sq = 0.0f; + for (i = 0; i < len; i++) { + far_dist_sq = len_squared_v3v3(vert_arr[i]->co, cent); + if (far_dist_sq > far_dist_max_sq || far == NULL) { + far = vert_arr[i]->co; + far_dist_max_sq = far_dist_sq; + } + } - sub_v3_v3v3(far_vec, far, cent); - // far_dist = len_v3(far_vec); /* real dist */ /* UNUSED */ + sub_v3_v3v3(far_vec, far, cent); + // far_dist = len_v3(far_vec); /* real dist */ /* UNUSED */ - /* --- */ + /* --- */ - /* find a point 90deg about to compare with */ - far_cross_best = 0.0f; - for (i = 0; i < len; i++) { + /* find a point 90deg about to compare with */ + far_cross_best = 0.0f; + for (i = 0; i < len; i++) { - if (far == vert_arr[i]->co) { - continue; - } + if (far == vert_arr[i]->co) { + continue; + } - sub_v3_v3v3(far_cross_vec, vert_arr[i]->co, cent); - far_cross_dist = normalize_v3(far_cross_vec); + sub_v3_v3v3(far_cross_vec, vert_arr[i]->co, cent); + far_cross_dist = normalize_v3(far_cross_vec); - /* more of a weight then a distance */ - far_cross_dist = (/* first we want to have a value close to zero mapped to 1 */ - 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) * + /* more of a weight then a distance */ + far_cross_dist = (/* first we want to have a value close to zero mapped to 1 */ + 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) * - /* second we multiply by the distance - * so points close to the center are not preferred */ - far_cross_dist); + /* second we multiply by the distance + * so points close to the center are not preferred */ + far_cross_dist); - if (far_cross_dist > far_cross_best || far_cross == NULL) { - far_cross = vert_arr[i]->co; - far_cross_best = far_cross_dist; - } - } + if (far_cross_dist > far_cross_best || far_cross == NULL) { + far_cross = vert_arr[i]->co; + far_cross_best = far_cross_dist; + } + } - sub_v3_v3v3(far_cross_vec, far_cross, cent); + sub_v3_v3v3(far_cross_vec, far_cross, cent); - /* --- */ + /* --- */ - /* now we have 2 vectors we can have a cross product */ - cross_v3_v3v3(nor, far_vec, far_cross_vec); - normalize_v3(nor); - cross_v3_v3v3(sign_vec, far_vec, nor); /* this vector should match 'far_cross_vec' closely */ + /* now we have 2 vectors we can have a cross product */ + cross_v3_v3v3(nor, far_vec, far_cross_vec); + normalize_v3(nor); + cross_v3_v3v3(sign_vec, far_vec, nor); /* this vector should match 'far_cross_vec' closely */ - /* --- */ + /* --- */ - /* now calculate every points angle around the normal (signed) */ - for (i = 0; i < len; i++) { - vang[i].sort_value = angle_signed_on_axis_v3v3v3_v3(far, cent, vert_arr[i]->co, nor); - vang[i].data = i; - vert_arr_map[i] = vert_arr[i]; - } + /* now calculate every points angle around the normal (signed) */ + for (i = 0; i < len; i++) { + vang[i].sort_value = angle_signed_on_axis_v3v3v3_v3(far, cent, vert_arr[i]->co, nor); + vang[i].data = i; + vert_arr_map[i] = vert_arr[i]; + } - /* sort by angle and magic! - we have our ngon */ - qsort(vang, len, sizeof(*vang), BLI_sortutil_cmp_float); + /* sort by angle and magic! - we have our ngon */ + qsort(vang, len, sizeof(*vang), BLI_sortutil_cmp_float); - /* --- */ + /* --- */ - for (i = 0; i < len; i++) { - vert_arr[i] = vert_arr_map[vang[i].data]; - } + for (i = 0; i < len; i++) { + vert_arr[i] = vert_arr_map[vang[i].data]; + } } /*************************************************************/ - -static void bm_vert_attrs_copy( - BMesh *source_mesh, BMesh *target_mesh, - const BMVert *source_vertex, BMVert *target_vertex, uint64_t cd_mask) +static void bm_vert_attrs_copy(BMesh *source_mesh, + BMesh *target_mesh, + const BMVert *source_vertex, + BMVert *target_vertex, + uint64_t cd_mask) { - if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) { - BLI_assert(!"BMVert: source and targer match"); - return; - } - if ((cd_mask & CD_MASK_NORMAL) == 0) { - copy_v3_v3(target_vertex->no, source_vertex->no); - } - CustomData_bmesh_free_block_data(&target_mesh->vdata, target_vertex->head.data); - CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata, - source_vertex->head.data, &target_vertex->head.data); + if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) { + BLI_assert(!"BMVert: source and targer match"); + return; + } + if ((cd_mask & CD_MASK_NORMAL) == 0) { + copy_v3_v3(target_vertex->no, source_vertex->no); + } + CustomData_bmesh_free_block_data(&target_mesh->vdata, target_vertex->head.data); + CustomData_bmesh_copy_data(&source_mesh->vdata, + &target_mesh->vdata, + source_vertex->head.data, + &target_vertex->head.data); } -static void bm_edge_attrs_copy( - BMesh *source_mesh, BMesh *target_mesh, - const BMEdge *source_edge, BMEdge *target_edge, uint64_t UNUSED(cd_mask)) +static void bm_edge_attrs_copy(BMesh *source_mesh, + BMesh *target_mesh, + const BMEdge *source_edge, + BMEdge *target_edge, + uint64_t UNUSED(cd_mask)) { - if ((source_mesh == target_mesh) && (source_edge == target_edge)) { - BLI_assert(!"BMEdge: source and targer match"); - return; - } - CustomData_bmesh_free_block_data(&target_mesh->edata, target_edge->head.data); - CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata, - source_edge->head.data, &target_edge->head.data); + if ((source_mesh == target_mesh) && (source_edge == target_edge)) { + BLI_assert(!"BMEdge: source and targer match"); + return; + } + CustomData_bmesh_free_block_data(&target_mesh->edata, target_edge->head.data); + CustomData_bmesh_copy_data( + &source_mesh->edata, &target_mesh->edata, source_edge->head.data, &target_edge->head.data); } -static void bm_loop_attrs_copy( - BMesh *source_mesh, BMesh *target_mesh, - const BMLoop *source_loop, BMLoop *target_loop, uint64_t UNUSED(cd_mask)) +static void bm_loop_attrs_copy(BMesh *source_mesh, + BMesh *target_mesh, + const BMLoop *source_loop, + BMLoop *target_loop, + uint64_t UNUSED(cd_mask)) { - if ((source_mesh == target_mesh) && (source_loop == target_loop)) { - BLI_assert(!"BMLoop: source and targer match"); - return; - } - CustomData_bmesh_free_block_data(&target_mesh->ldata, target_loop->head.data); - CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata, - source_loop->head.data, &target_loop->head.data); + if ((source_mesh == target_mesh) && (source_loop == target_loop)) { + BLI_assert(!"BMLoop: source and targer match"); + return; + } + CustomData_bmesh_free_block_data(&target_mesh->ldata, target_loop->head.data); + CustomData_bmesh_copy_data( + &source_mesh->ldata, &target_mesh->ldata, source_loop->head.data, &target_loop->head.data); } -static void bm_face_attrs_copy( - BMesh *source_mesh, BMesh *target_mesh, - const BMFace *source_face, BMFace *target_face, uint64_t cd_mask) +static void bm_face_attrs_copy(BMesh *source_mesh, + BMesh *target_mesh, + const BMFace *source_face, + BMFace *target_face, + uint64_t cd_mask) { - if ((source_mesh == target_mesh) && (source_face == target_face)) { - BLI_assert(!"BMFace: source and targer match"); - return; - } - if ((cd_mask & CD_MASK_NORMAL) == 0) { - copy_v3_v3(target_face->no, source_face->no); - } - CustomData_bmesh_free_block_data(&target_mesh->pdata, target_face->head.data); - CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata, - source_face->head.data, &target_face->head.data); - target_face->mat_nr = source_face->mat_nr; + if ((source_mesh == target_mesh) && (source_face == target_face)) { + BLI_assert(!"BMFace: source and targer match"); + return; + } + if ((cd_mask & CD_MASK_NORMAL) == 0) { + copy_v3_v3(target_face->no, source_face->no); + } + CustomData_bmesh_free_block_data(&target_mesh->pdata, target_face->head.data); + CustomData_bmesh_copy_data( + &source_mesh->pdata, &target_mesh->pdata, source_face->head.data, &target_face->head.data); + target_face->mat_nr = source_face->mat_nr; } /* BMESH_TODO: Special handling for hide flags? */ @@ -542,304 +555,293 @@ static void bm_face_attrs_copy( * Copies attributes, e.g. customdata, header flags, etc, from one element * to another of the same type. */ -void BM_elem_attrs_copy_ex( - BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, - const char hflag_mask, const uint64_t cd_mask) +void BM_elem_attrs_copy_ex(BMesh *bm_src, + BMesh *bm_dst, + const void *ele_src_v, + void *ele_dst_v, + const char hflag_mask, + const uint64_t cd_mask) { - const BMHeader *ele_src = ele_src_v; - BMHeader *ele_dst = ele_dst_v; - - BLI_assert(ele_src->htype == ele_dst->htype); - BLI_assert(ele_src != ele_dst); - - /* Only support normal layer at the moment. */ - BLI_assert((cd_mask & ~CD_MASK_NORMAL) == 0); - - if ((hflag_mask & BM_ELEM_SELECT) == 0) { - /* First we copy select */ - if (BM_elem_flag_test((BMElem *)ele_src, BM_ELEM_SELECT)) { - BM_elem_select_set(bm_dst, (BMElem *)ele_dst, true); - } - } - - /* Now we copy flags */ - if (hflag_mask == 0) { - ele_dst->hflag = ele_src->hflag; - } - else if (hflag_mask == 0xff) { - /* pass */ - } - else { - ele_dst->hflag = ((ele_dst->hflag & hflag_mask) | (ele_src->hflag & ~hflag_mask)); - } - - /* Copy specific attributes */ - switch (ele_dst->htype) { - case BM_VERT: - bm_vert_attrs_copy(bm_src, bm_dst, (const BMVert *)ele_src, (BMVert *)ele_dst, cd_mask); - break; - case BM_EDGE: - bm_edge_attrs_copy(bm_src, bm_dst, (const BMEdge *)ele_src, (BMEdge *)ele_dst, cd_mask); - break; - case BM_LOOP: - bm_loop_attrs_copy(bm_src, bm_dst, (const BMLoop *)ele_src, (BMLoop *)ele_dst, cd_mask); - break; - case BM_FACE: - bm_face_attrs_copy(bm_src, bm_dst, (const BMFace *)ele_src, (BMFace *)ele_dst, cd_mask); - break; - default: - BLI_assert(0); - break; - } + const BMHeader *ele_src = ele_src_v; + BMHeader *ele_dst = ele_dst_v; + + BLI_assert(ele_src->htype == ele_dst->htype); + BLI_assert(ele_src != ele_dst); + + /* Only support normal layer at the moment. */ + BLI_assert((cd_mask & ~CD_MASK_NORMAL) == 0); + + if ((hflag_mask & BM_ELEM_SELECT) == 0) { + /* First we copy select */ + if (BM_elem_flag_test((BMElem *)ele_src, BM_ELEM_SELECT)) { + BM_elem_select_set(bm_dst, (BMElem *)ele_dst, true); + } + } + + /* Now we copy flags */ + if (hflag_mask == 0) { + ele_dst->hflag = ele_src->hflag; + } + else if (hflag_mask == 0xff) { + /* pass */ + } + else { + ele_dst->hflag = ((ele_dst->hflag & hflag_mask) | (ele_src->hflag & ~hflag_mask)); + } + + /* Copy specific attributes */ + switch (ele_dst->htype) { + case BM_VERT: + bm_vert_attrs_copy(bm_src, bm_dst, (const BMVert *)ele_src, (BMVert *)ele_dst, cd_mask); + break; + case BM_EDGE: + bm_edge_attrs_copy(bm_src, bm_dst, (const BMEdge *)ele_src, (BMEdge *)ele_dst, cd_mask); + break; + case BM_LOOP: + bm_loop_attrs_copy(bm_src, bm_dst, (const BMLoop *)ele_src, (BMLoop *)ele_dst, cd_mask); + break; + case BM_FACE: + bm_face_attrs_copy(bm_src, bm_dst, (const BMFace *)ele_src, (BMFace *)ele_dst, cd_mask); + break; + default: + BLI_assert(0); + break; + } } void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst) { - /* BMESH_TODO, default 'use_flags' to false */ - BM_elem_attrs_copy_ex(bm_src, bm_dst, ele_src, ele_dst, BM_ELEM_SELECT, 0x0); + /* BMESH_TODO, default 'use_flags' to false */ + BM_elem_attrs_copy_ex(bm_src, bm_dst, ele_src, ele_dst, BM_ELEM_SELECT, 0x0); } void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v) { - BMHeader *ele_dst = ele_dst_v; - const BMHeader *ele_src = ele_src_v; + BMHeader *ele_dst = ele_dst_v; + const BMHeader *ele_src = ele_src_v; - BLI_assert(ele_src->htype == ele_dst->htype); + BLI_assert(ele_src->htype == ele_dst->htype); - if ((ele_src->hflag & BM_ELEM_SELECT) != (ele_dst->hflag & BM_ELEM_SELECT)) { - BM_elem_select_set(bm_dst, (BMElem *)ele_dst, (ele_src->hflag & BM_ELEM_SELECT) != 0); - } + if ((ele_src->hflag & BM_ELEM_SELECT) != (ele_dst->hflag & BM_ELEM_SELECT)) { + BM_elem_select_set(bm_dst, (BMElem *)ele_dst, (ele_src->hflag & BM_ELEM_SELECT) != 0); + } } /* helper function for 'BM_mesh_copy' */ static BMFace *bm_mesh_copy_new_face( - BMesh *bm_new, BMesh *bm_old, - BMVert **vtable, BMEdge **etable, - BMFace *f) + BMesh *bm_new, BMesh *bm_old, BMVert **vtable, BMEdge **etable, BMFace *f) { - BMLoop **loops = BLI_array_alloca(loops, f->len); - BMVert **verts = BLI_array_alloca(verts, f->len); - BMEdge **edges = BLI_array_alloca(edges, f->len); - - BMFace *f_new; - BMLoop *l_iter, *l_first; - int j; - - j = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - loops[j] = l_iter; - verts[j] = vtable[BM_elem_index_get(l_iter->v)]; - edges[j] = etable[BM_elem_index_get(l_iter->e)]; - j++; - } while ((l_iter = l_iter->next) != l_first); - - f_new = BM_face_create(bm_new, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD); - - if (UNLIKELY(f_new == NULL)) { - return NULL; - } - - /* use totface in case adding some faces fails */ - BM_elem_index_set(f_new, (bm_new->totface - 1)); /* set_inline */ - - BM_elem_attrs_copy_ex(bm_old, bm_new, f, f_new, 0xff, 0x0); - f_new->head.hflag = f->head.hflag; /* low level! don't do this for normal api use */ - - j = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); - do { - BM_elem_attrs_copy(bm_old, bm_new, loops[j], l_iter); - j++; - } while ((l_iter = l_iter->next) != l_first); - - return f_new; + BMLoop **loops = BLI_array_alloca(loops, f->len); + BMVert **verts = BLI_array_alloca(verts, f->len); + BMEdge **edges = BLI_array_alloca(edges, f->len); + + BMFace *f_new; + BMLoop *l_iter, *l_first; + int j; + + j = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + loops[j] = l_iter; + verts[j] = vtable[BM_elem_index_get(l_iter->v)]; + edges[j] = etable[BM_elem_index_get(l_iter->e)]; + j++; + } while ((l_iter = l_iter->next) != l_first); + + f_new = BM_face_create(bm_new, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD); + + if (UNLIKELY(f_new == NULL)) { + return NULL; + } + + /* use totface in case adding some faces fails */ + BM_elem_index_set(f_new, (bm_new->totface - 1)); /* set_inline */ + + BM_elem_attrs_copy_ex(bm_old, bm_new, f, f_new, 0xff, 0x0); + f_new->head.hflag = f->head.hflag; /* low level! don't do this for normal api use */ + + j = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); + do { + BM_elem_attrs_copy(bm_old, bm_new, loops[j], l_iter); + j++; + } while ((l_iter = l_iter->next) != l_first); + + return f_new; } void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize) { - if (allocsize == NULL) { - allocsize = &bm_mesh_allocsize_default; - } - - CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0); - CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0); - CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0); - CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0); - - CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT); - CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE); - CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP); - CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE); + if (allocsize == NULL) { + allocsize = &bm_mesh_allocsize_default; + } + + CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0); + CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0); + CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0); + CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0); + + CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT); + CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE); + CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP); + CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE); } - BMesh *BM_mesh_copy(BMesh *bm_old) { - BMesh *bm_new; - BMVert *v, *v_new, **vtable = NULL; - BMEdge *e, *e_new, **etable = NULL; - BMFace *f, *f_new, **ftable = NULL; - BMElem **eletable; - BMEditSelection *ese; - BMIter iter; - int i; - const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm_old); - - /* allocate a bmesh */ - bm_new = BM_mesh_create( - &allocsize, - &((struct BMeshCreateParams){.use_toolflags = bm_old->use_toolflags,})); - - BM_mesh_copy_init_customdata(bm_new, bm_old, &allocsize); - - vtable = MEM_mallocN(sizeof(BMVert *) * bm_old->totvert, "BM_mesh_copy vtable"); - etable = MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable"); - ftable = MEM_mallocN(sizeof(BMFace *) * bm_old->totface, "BM_mesh_copy ftable"); - - BM_ITER_MESH_INDEX (v, &iter, bm_old, BM_VERTS_OF_MESH, i) { - /* copy between meshes so cant use 'example' argument */ - v_new = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD); - BM_elem_attrs_copy_ex(bm_old, bm_new, v, v_new, 0xff, 0x0); - v_new->head.hflag = v->head.hflag; /* low level! don't do this for normal api use */ - vtable[i] = v_new; - BM_elem_index_set(v, i); /* set_inline */ - BM_elem_index_set(v_new, i); /* set_inline */ - } - bm_old->elem_index_dirty &= ~BM_VERT; - bm_new->elem_index_dirty &= ~BM_VERT; - - /* safety check */ - BLI_assert(i == bm_old->totvert); - - BM_ITER_MESH_INDEX (e, &iter, bm_old, BM_EDGES_OF_MESH, i) { - e_new = BM_edge_create(bm_new, - vtable[BM_elem_index_get(e->v1)], - vtable[BM_elem_index_get(e->v2)], - e, BM_CREATE_SKIP_CD); - - BM_elem_attrs_copy_ex(bm_old, bm_new, e, e_new, 0xff, 0x0); - e_new->head.hflag = e->head.hflag; /* low level! don't do this for normal api use */ - etable[i] = e_new; - BM_elem_index_set(e, i); /* set_inline */ - BM_elem_index_set(e_new, i); /* set_inline */ - } - bm_old->elem_index_dirty &= ~BM_EDGE; - bm_new->elem_index_dirty &= ~BM_EDGE; - - /* safety check */ - BLI_assert(i == bm_old->totedge); - - BM_ITER_MESH_INDEX (f, &iter, bm_old, BM_FACES_OF_MESH, i) { - BM_elem_index_set(f, i); /* set_inline */ - - f_new = bm_mesh_copy_new_face(bm_new, bm_old, vtable, etable, f); - - ftable[i] = f_new; - - if (f == bm_old->act_face) { - bm_new->act_face = f_new; - } - } - bm_old->elem_index_dirty &= ~BM_FACE; - bm_new->elem_index_dirty &= ~BM_FACE; - - - /* low level! don't do this for normal api use */ - bm_new->totvertsel = bm_old->totvertsel; - bm_new->totedgesel = bm_old->totedgesel; - bm_new->totfacesel = bm_old->totfacesel; - - /* safety check */ - BLI_assert(i == bm_old->totface); - - /* copy over edit selection history */ - for (ese = bm_old->selected.first; ese; ese = ese->next) { - BMElem *ele = NULL; - - switch (ese->htype) { - case BM_VERT: - eletable = (BMElem **)vtable; - break; - case BM_EDGE: - eletable = (BMElem **)etable; - break; - case BM_FACE: - eletable = (BMElem **)ftable; - break; - default: - eletable = NULL; - break; - } - - if (eletable) { - ele = eletable[BM_elem_index_get(ese->ele)]; - if (ele) { - BM_select_history_store(bm_new, ele); - } - } - } - - MEM_freeN(etable); - MEM_freeN(vtable); - MEM_freeN(ftable); - - return bm_new; + BMesh *bm_new; + BMVert *v, *v_new, **vtable = NULL; + BMEdge *e, *e_new, **etable = NULL; + BMFace *f, *f_new, **ftable = NULL; + BMElem **eletable; + BMEditSelection *ese; + BMIter iter; + int i; + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm_old); + + /* allocate a bmesh */ + bm_new = BM_mesh_create(&allocsize, + &((struct BMeshCreateParams){ + .use_toolflags = bm_old->use_toolflags, + })); + + BM_mesh_copy_init_customdata(bm_new, bm_old, &allocsize); + + vtable = MEM_mallocN(sizeof(BMVert *) * bm_old->totvert, "BM_mesh_copy vtable"); + etable = MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable"); + ftable = MEM_mallocN(sizeof(BMFace *) * bm_old->totface, "BM_mesh_copy ftable"); + + BM_ITER_MESH_INDEX (v, &iter, bm_old, BM_VERTS_OF_MESH, i) { + /* copy between meshes so cant use 'example' argument */ + v_new = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD); + BM_elem_attrs_copy_ex(bm_old, bm_new, v, v_new, 0xff, 0x0); + v_new->head.hflag = v->head.hflag; /* low level! don't do this for normal api use */ + vtable[i] = v_new; + BM_elem_index_set(v, i); /* set_inline */ + BM_elem_index_set(v_new, i); /* set_inline */ + } + bm_old->elem_index_dirty &= ~BM_VERT; + bm_new->elem_index_dirty &= ~BM_VERT; + + /* safety check */ + BLI_assert(i == bm_old->totvert); + + BM_ITER_MESH_INDEX (e, &iter, bm_old, BM_EDGES_OF_MESH, i) { + e_new = BM_edge_create(bm_new, + vtable[BM_elem_index_get(e->v1)], + vtable[BM_elem_index_get(e->v2)], + e, + BM_CREATE_SKIP_CD); + + BM_elem_attrs_copy_ex(bm_old, bm_new, e, e_new, 0xff, 0x0); + e_new->head.hflag = e->head.hflag; /* low level! don't do this for normal api use */ + etable[i] = e_new; + BM_elem_index_set(e, i); /* set_inline */ + BM_elem_index_set(e_new, i); /* set_inline */ + } + bm_old->elem_index_dirty &= ~BM_EDGE; + bm_new->elem_index_dirty &= ~BM_EDGE; + + /* safety check */ + BLI_assert(i == bm_old->totedge); + + BM_ITER_MESH_INDEX (f, &iter, bm_old, BM_FACES_OF_MESH, i) { + BM_elem_index_set(f, i); /* set_inline */ + + f_new = bm_mesh_copy_new_face(bm_new, bm_old, vtable, etable, f); + + ftable[i] = f_new; + + if (f == bm_old->act_face) { + bm_new->act_face = f_new; + } + } + bm_old->elem_index_dirty &= ~BM_FACE; + bm_new->elem_index_dirty &= ~BM_FACE; + + /* low level! don't do this for normal api use */ + bm_new->totvertsel = bm_old->totvertsel; + bm_new->totedgesel = bm_old->totedgesel; + bm_new->totfacesel = bm_old->totfacesel; + + /* safety check */ + BLI_assert(i == bm_old->totface); + + /* copy over edit selection history */ + for (ese = bm_old->selected.first; ese; ese = ese->next) { + BMElem *ele = NULL; + + switch (ese->htype) { + case BM_VERT: + eletable = (BMElem **)vtable; + break; + case BM_EDGE: + eletable = (BMElem **)etable; + break; + case BM_FACE: + eletable = (BMElem **)ftable; + break; + default: + eletable = NULL; + break; + } + + if (eletable) { + ele = eletable[BM_elem_index_get(ese->ele)]; + if (ele) { + BM_select_history_store(bm_new, ele); + } + } + } + + MEM_freeN(etable); + MEM_freeN(vtable); + MEM_freeN(ftable); + + return bm_new; } /* ME -> BM */ -char BM_vert_flag_from_mflag(const char meflag) +char BM_vert_flag_from_mflag(const char meflag) { - return ( ((meflag & SELECT) ? BM_ELEM_SELECT : 0) | - ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0) - ); + return (((meflag & SELECT) ? BM_ELEM_SELECT : 0) | ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0)); } char BM_edge_flag_from_mflag(const short meflag) { - return ( ((meflag & SELECT) ? BM_ELEM_SELECT : 0) | - ((meflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | - ((meflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) | - ((meflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0) | /* invert */ - ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0) - ); + return (((meflag & SELECT) ? BM_ELEM_SELECT : 0) | ((meflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | + ((meflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) | + ((meflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0) | /* invert */ + ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0)); } -char BM_face_flag_from_mflag(const char meflag) +char BM_face_flag_from_mflag(const char meflag) { - return ( ((meflag & ME_FACE_SEL) ? BM_ELEM_SELECT : 0) | - ((meflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0) | - ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0) - ); + return (((meflag & ME_FACE_SEL) ? BM_ELEM_SELECT : 0) | + ((meflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0) | ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0)); } /* BM -> ME */ -char BM_vert_flag_to_mflag(BMVert *eve) +char BM_vert_flag_to_mflag(BMVert *eve) { - const char hflag = eve->head.hflag; + const char hflag = eve->head.hflag; - return ( ((hflag & BM_ELEM_SELECT) ? SELECT : 0) | - ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) - ); + return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0)); } short BM_edge_flag_to_mflag(BMEdge *eed) { - const char hflag = eed->head.hflag; - - return ( ((hflag & BM_ELEM_SELECT) ? SELECT : 0) | - ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) | - ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) | - ((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) | - ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) | - ((BM_edge_is_wire(eed)) ? ME_LOOSEEDGE : 0) | /* not typical */ - ME_EDGERENDER - ); + const char hflag = eed->head.hflag; + + return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) | + ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) | + ((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) | + ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) | + ((BM_edge_is_wire(eed)) ? ME_LOOSEEDGE : 0) | /* not typical */ + ME_EDGERENDER); } -char BM_face_flag_to_mflag(BMFace *efa) +char BM_face_flag_to_mflag(BMFace *efa) { - const char hflag = efa->head.hflag; + const char hflag = efa->head.hflag; - return ( ((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) | - ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0) | - ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) - ); + return (((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) | + ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0)); } diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h index 0dfa0a81b91..0b285979369 100644 --- a/source/blender/bmesh/intern/bmesh_construct.h +++ b/source/blender/bmesh/intern/bmesh_construct.h @@ -29,38 +29,52 @@ bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len); void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len); /* sort before creation */ -void BM_verts_sort_radial_plane(BMVert **vert_arr, int len); +void BM_verts_sort_radial_plane(BMVert **vert_arr, int len); -BMFace *BM_face_create_quad_tri( - BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - const BMFace *f_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create_quad_tri(BMesh *bm, + BMVert *v1, + BMVert *v2, + BMVert *v3, + BMVert *v4, + const BMFace *f_example, + const eBMCreateFlag create_flag); -void BM_face_copy_shared( - BMesh *bm, BMFace *f, - BMLoopFilterFunc filter_fn, void *user_data); +void BM_face_copy_shared(BMesh *bm, BMFace *f, BMLoopFilterFunc filter_fn, void *user_data); -BMFace *BM_face_create_ngon( - BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag); -BMFace *BM_face_create_ngon_verts( - BMesh *bm, BMVert **vert_arr, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, - const bool calc_winding, const bool create_edges); +BMFace *BM_face_create_ngon(BMesh *bm, + BMVert *v1, + BMVert *v2, + BMEdge **edges, + const int len, + const BMFace *f_example, + const eBMCreateFlag create_flag); +BMFace *BM_face_create_ngon_verts(BMesh *bm, + BMVert **vert_arr, + const int len, + const BMFace *f_example, + const eBMCreateFlag create_flag, + const bool calc_winding, + const bool create_edges); -void BM_elem_attrs_copy_ex( - BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, - const char hflag_mask, const uint64_t cd_mask); +void BM_elem_attrs_copy_ex(BMesh *bm_src, + BMesh *bm_dst, + const void *ele_src_v, + void *ele_dst_v, + const char hflag_mask, + const uint64_t cd_mask); void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v); void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v); -void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const struct BMAllocTemplate *allocsize); +void BM_mesh_copy_init_customdata(BMesh *bm_dst, + BMesh *bm_src, + const struct BMAllocTemplate *allocsize); BMesh *BM_mesh_copy(BMesh *bm_old); -char BM_face_flag_from_mflag(const char mflag); -char BM_edge_flag_from_mflag(const short mflag); -char BM_vert_flag_from_mflag(const char mflag); -char BM_face_flag_to_mflag(BMFace *f); +char BM_face_flag_from_mflag(const char mflag); +char BM_edge_flag_from_mflag(const short mflag); +char BM_vert_flag_from_mflag(const char mflag); +char BM_face_flag_to_mflag(BMFace *f); short BM_edge_flag_to_mflag(BMEdge *e); -char BM_vert_flag_to_mflag(BMVert *v); +char BM_vert_flag_to_mflag(BMVert *v); #endif /* __BMESH_CONSTRUCT_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 58b83cd0586..5dcf6acad57 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -43,96 +43,97 @@ // #define USE_DEBUG_INDEX_MEMCHECK #ifdef USE_DEBUG_INDEX_MEMCHECK -#define DEBUG_MEMCHECK_INDEX_INVALIDATE(ele) \ - { \ - int undef_idx; \ - BM_elem_index_set(ele, undef_idx); /* set_ok_invalid */ \ - } (void)0 +# define DEBUG_MEMCHECK_INDEX_INVALIDATE(ele) \ + { \ + int undef_idx; \ + BM_elem_index_set(ele, undef_idx); /* set_ok_invalid */ \ + } \ + (void)0 #endif /** * \brief Main function for creating a new vertex. */ -BMVert *BM_vert_create( - BMesh *bm, const float co[3], - const BMVert *v_example, const eBMCreateFlag create_flag) +BMVert *BM_vert_create(BMesh *bm, + const float co[3], + const BMVert *v_example, + const eBMCreateFlag create_flag) { - BMVert *v = BLI_mempool_alloc(bm->vpool); + BMVert *v = BLI_mempool_alloc(bm->vpool); - BLI_assert((v_example == NULL) || (v_example->head.htype == BM_VERT)); - BLI_assert(!(create_flag & 1)); + BLI_assert((v_example == NULL) || (v_example->head.htype == BM_VERT)); + BLI_assert(!(create_flag & 1)); - /* --- assign all members --- */ - v->head.data = NULL; + /* --- assign all members --- */ + v->head.data = NULL; #ifdef USE_DEBUG_INDEX_MEMCHECK - DEBUG_MEMCHECK_INDEX_INVALIDATE(v) + DEBUG_MEMCHECK_INDEX_INVALIDATE(v) #else - BM_elem_index_set(v, -1); /* set_ok_invalid */ + BM_elem_index_set(v, -1); /* set_ok_invalid */ #endif - v->head.htype = BM_VERT; - v->head.hflag = 0; - v->head.api_flag = 0; - - /* allocate flags */ - if (bm->use_toolflags) { - ((BMVert_OFlag *)v)->oflags = bm->vtoolflagpool ? BLI_mempool_calloc(bm->vtoolflagpool) : NULL; - } - - /* 'v->no' is handled by BM_elem_attrs_copy */ - if (co) { - copy_v3_v3(v->co, co); - } - else { - zero_v3(v->co); - } - /* 'v->no' set below */ - - v->e = NULL; - /* --- done --- */ - - - /* disallow this flag for verts - its meaningless */ - BLI_assert((create_flag & BM_CREATE_NO_DOUBLE) == 0); - - /* may add to middle of the pool */ - bm->elem_index_dirty |= BM_VERT; - bm->elem_table_dirty |= BM_VERT; - - bm->totvert++; - - if (!(create_flag & BM_CREATE_SKIP_CD)) { - if (v_example) { - int *keyi; - - /* handles 'v->no' too */ - BM_elem_attrs_copy(bm, bm, v_example, v); - - /* exception: don't copy the original shapekey index */ - keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); - if (keyi) { - *keyi = ORIGINDEX_NONE; - } - } - else { - CustomData_bmesh_set_default(&bm->vdata, &v->head.data); - zero_v3(v->no); - } - } - else { - if (v_example) { - copy_v3_v3(v->no, v_example->no); - } - else { - zero_v3(v->no); - } - } - - BM_CHECK_ELEMENT(v); - - return v; + v->head.htype = BM_VERT; + v->head.hflag = 0; + v->head.api_flag = 0; + + /* allocate flags */ + if (bm->use_toolflags) { + ((BMVert_OFlag *)v)->oflags = bm->vtoolflagpool ? BLI_mempool_calloc(bm->vtoolflagpool) : NULL; + } + + /* 'v->no' is handled by BM_elem_attrs_copy */ + if (co) { + copy_v3_v3(v->co, co); + } + else { + zero_v3(v->co); + } + /* 'v->no' set below */ + + v->e = NULL; + /* --- done --- */ + + /* disallow this flag for verts - its meaningless */ + BLI_assert((create_flag & BM_CREATE_NO_DOUBLE) == 0); + + /* may add to middle of the pool */ + bm->elem_index_dirty |= BM_VERT; + bm->elem_table_dirty |= BM_VERT; + + bm->totvert++; + + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (v_example) { + int *keyi; + + /* handles 'v->no' too */ + BM_elem_attrs_copy(bm, bm, v_example, v); + + /* exception: don't copy the original shapekey index */ + keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); + if (keyi) { + *keyi = ORIGINDEX_NONE; + } + } + else { + CustomData_bmesh_set_default(&bm->vdata, &v->head.data); + zero_v3(v->no); + } + } + else { + if (v_example) { + copy_v3_v3(v->no, v_example->no); + } + else { + zero_v3(v->no); + } + } + + BM_CHECK_ELEMENT(v); + + return v; } /** @@ -142,70 +143,67 @@ BMVert *BM_vert_create( * so unless you need a unique edge or know the edge won't exist, you should call with \a no_double = true */ BMEdge *BM_edge_create( - BMesh *bm, BMVert *v1, BMVert *v2, - const BMEdge *e_example, const eBMCreateFlag create_flag) + BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag) { - BMEdge *e; + BMEdge *e; - BLI_assert(v1 != v2); - BLI_assert(v1->head.htype == BM_VERT && v2->head.htype == BM_VERT); - BLI_assert((e_example == NULL) || (e_example->head.htype == BM_EDGE)); - BLI_assert(!(create_flag & 1)); + BLI_assert(v1 != v2); + BLI_assert(v1->head.htype == BM_VERT && v2->head.htype == BM_VERT); + BLI_assert((e_example == NULL) || (e_example->head.htype == BM_EDGE)); + BLI_assert(!(create_flag & 1)); - if ((create_flag & BM_CREATE_NO_DOUBLE) && (e = BM_edge_exists(v1, v2))) { - return e; - } + if ((create_flag & BM_CREATE_NO_DOUBLE) && (e = BM_edge_exists(v1, v2))) { + return e; + } - e = BLI_mempool_alloc(bm->epool); + e = BLI_mempool_alloc(bm->epool); - - /* --- assign all members --- */ - e->head.data = NULL; + /* --- assign all members --- */ + e->head.data = NULL; #ifdef USE_DEBUG_INDEX_MEMCHECK - DEBUG_MEMCHECK_INDEX_INVALIDATE(e) + DEBUG_MEMCHECK_INDEX_INVALIDATE(e) #else - BM_elem_index_set(e, -1); /* set_ok_invalid */ + BM_elem_index_set(e, -1); /* set_ok_invalid */ #endif - e->head.htype = BM_EDGE; - e->head.hflag = BM_ELEM_SMOOTH | BM_ELEM_DRAW; - e->head.api_flag = 0; - - /* allocate flags */ - if (bm->use_toolflags) { - ((BMEdge_OFlag *)e)->oflags = bm->etoolflagpool ? BLI_mempool_calloc(bm->etoolflagpool) : NULL; - } + e->head.htype = BM_EDGE; + e->head.hflag = BM_ELEM_SMOOTH | BM_ELEM_DRAW; + e->head.api_flag = 0; - e->v1 = v1; - e->v2 = v2; - e->l = NULL; + /* allocate flags */ + if (bm->use_toolflags) { + ((BMEdge_OFlag *)e)->oflags = bm->etoolflagpool ? BLI_mempool_calloc(bm->etoolflagpool) : NULL; + } - memset(&e->v1_disk_link, 0, sizeof(BMDiskLink) * 2); - /* --- done --- */ + e->v1 = v1; + e->v2 = v2; + e->l = NULL; + memset(&e->v1_disk_link, 0, sizeof(BMDiskLink) * 2); + /* --- done --- */ - bmesh_disk_edge_append(e, e->v1); - bmesh_disk_edge_append(e, e->v2); + bmesh_disk_edge_append(e, e->v1); + bmesh_disk_edge_append(e, e->v2); - /* may add to middle of the pool */ - bm->elem_index_dirty |= BM_EDGE; - bm->elem_table_dirty |= BM_EDGE; + /* may add to middle of the pool */ + bm->elem_index_dirty |= BM_EDGE; + bm->elem_table_dirty |= BM_EDGE; - bm->totedge++; + bm->totedge++; - if (!(create_flag & BM_CREATE_SKIP_CD)) { - if (e_example) { - BM_elem_attrs_copy(bm, bm, e_example, e); - } - else { - CustomData_bmesh_set_default(&bm->edata, &e->head.data); - } - } + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (e_example) { + BM_elem_attrs_copy(bm, bm, e_example, e); + } + else { + CustomData_bmesh_set_default(&bm->edata, &e->head.data); + } + } - BM_CHECK_ELEMENT(e); + BM_CHECK_ELEMENT(e); - return e; + return e; } /** @@ -213,150 +211,151 @@ BMEdge *BM_edge_create( * since this is a low level API and we shouldn't attempt to be clever and guess whats intended. * In cases where copying adjacent loop-data is useful, see #BM_face_copy_shared. */ -static BMLoop *bm_loop_create( - BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, - const BMLoop *l_example, const eBMCreateFlag create_flag) +static BMLoop *bm_loop_create(BMesh *bm, + BMVert *v, + BMEdge *e, + BMFace *f, + const BMLoop *l_example, + const eBMCreateFlag create_flag) { - BMLoop *l = NULL; + BMLoop *l = NULL; - l = BLI_mempool_alloc(bm->lpool); + l = BLI_mempool_alloc(bm->lpool); - BLI_assert((l_example == NULL) || (l_example->head.htype == BM_LOOP)); - BLI_assert(!(create_flag & 1)); + BLI_assert((l_example == NULL) || (l_example->head.htype == BM_LOOP)); + BLI_assert(!(create_flag & 1)); #ifndef NDEBUG - if (l_example) { - /* ensure passing a loop is either sharing the same vertex, or entirely disconnected - * use to catch mistake passing in loop offset-by-one. */ - BLI_assert((v == l_example->v) || !ELEM(v, l_example->prev->v, l_example->next->v)); - } + if (l_example) { + /* ensure passing a loop is either sharing the same vertex, or entirely disconnected + * use to catch mistake passing in loop offset-by-one. */ + BLI_assert((v == l_example->v) || !ELEM(v, l_example->prev->v, l_example->next->v)); + } #endif - /* --- assign all members --- */ - l->head.data = NULL; + /* --- assign all members --- */ + l->head.data = NULL; #ifdef USE_DEBUG_INDEX_MEMCHECK - DEBUG_MEMCHECK_INDEX_INVALIDATE(l) + DEBUG_MEMCHECK_INDEX_INVALIDATE(l) #else - BM_elem_index_set(l, -1); /* set_ok_invalid */ + BM_elem_index_set(l, -1); /* set_ok_invalid */ #endif - l->head.htype = BM_LOOP; - l->head.hflag = 0; - l->head.api_flag = 0; - - l->v = v; - l->e = e; - l->f = f; - - l->radial_next = NULL; - l->radial_prev = NULL; - l->next = NULL; - l->prev = NULL; - /* --- done --- */ - - /* may add to middle of the pool */ - bm->elem_index_dirty |= BM_LOOP; - - bm->totloop++; - - if (!(create_flag & BM_CREATE_SKIP_CD)) { - if (l_example) { - /* no need to copy attrs, just handle customdata */ - // BM_elem_attrs_copy(bm, bm, l_example, l); - CustomData_bmesh_free_block_data(&bm->ldata, l->head.data); - CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_example->head.data, &l->head.data); - } - else { - CustomData_bmesh_set_default(&bm->ldata, &l->head.data); - } - } - - return l; + l->head.htype = BM_LOOP; + l->head.hflag = 0; + l->head.api_flag = 0; + + l->v = v; + l->e = e; + l->f = f; + + l->radial_next = NULL; + l->radial_prev = NULL; + l->next = NULL; + l->prev = NULL; + /* --- done --- */ + + /* may add to middle of the pool */ + bm->elem_index_dirty |= BM_LOOP; + + bm->totloop++; + + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (l_example) { + /* no need to copy attrs, just handle customdata */ + // BM_elem_attrs_copy(bm, bm, l_example, l); + CustomData_bmesh_free_block_data(&bm->ldata, l->head.data); + CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_example->head.data, &l->head.data); + } + else { + CustomData_bmesh_set_default(&bm->ldata, &l->head.data); + } + } + + return l; } static BMLoop *bm_face_boundary_add( - BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, - const eBMCreateFlag create_flag) + BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, const eBMCreateFlag create_flag) { #ifdef USE_BMESH_HOLES - BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool); + BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool); #endif - BMLoop *l = bm_loop_create(bm, startv, starte, f, NULL /* starte->l */, create_flag); + BMLoop *l = bm_loop_create(bm, startv, starte, f, NULL /* starte->l */, create_flag); - bmesh_radial_loop_append(starte, l); + bmesh_radial_loop_append(starte, l); #ifdef USE_BMESH_HOLES - lst->first = lst->last = l; - BLI_addtail(&f->loops, lst); + lst->first = lst->last = l; + BLI_addtail(&f->loops, lst); #else - f->l_first = l; + f->l_first = l; #endif - return l; + return l; } BMFace *BM_face_copy( - BMesh *bm_dst, BMesh *bm_src, BMFace *f, - const bool copy_verts, const bool copy_edges) + BMesh *bm_dst, BMesh *bm_src, BMFace *f, const bool copy_verts, const bool copy_edges) { - BMVert **verts = BLI_array_alloca(verts, f->len); - BMEdge **edges = BLI_array_alloca(edges, f->len); - BMLoop *l_iter; - BMLoop *l_first; - BMLoop *l_copy; - BMFace *f_copy; - int i; - - BLI_assert((bm_dst == bm_src) || (copy_verts && copy_edges)); - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - i = 0; - do { - if (copy_verts) { - verts[i] = BM_vert_create(bm_dst, l_iter->v->co, l_iter->v, BM_CREATE_NOP); - } - else { - verts[i] = l_iter->v; - } - i++; - } while ((l_iter = l_iter->next) != l_first); - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - i = 0; - do { - if (copy_edges) { - BMVert *v1, *v2; - - if (l_iter->e->v1 == verts[i]) { - v1 = verts[i]; - v2 = verts[(i + 1) % f->len]; - } - else { - v2 = verts[i]; - v1 = verts[(i + 1) % f->len]; - } - - edges[i] = BM_edge_create(bm_dst, v1, v2, l_iter->e, BM_CREATE_NOP); - } - else { - edges[i] = l_iter->e; - } - i++; - } while ((l_iter = l_iter->next) != l_first); - - f_copy = BM_face_create(bm_dst, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD); - - BM_elem_attrs_copy(bm_src, bm_dst, f, f_copy); - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - l_copy = BM_FACE_FIRST_LOOP(f_copy); - do { - BM_elem_attrs_copy(bm_src, bm_dst, l_iter, l_copy); - l_copy = l_copy->next; - } while ((l_iter = l_iter->next) != l_first); - - return f_copy; + BMVert **verts = BLI_array_alloca(verts, f->len); + BMEdge **edges = BLI_array_alloca(edges, f->len); + BMLoop *l_iter; + BMLoop *l_first; + BMLoop *l_copy; + BMFace *f_copy; + int i; + + BLI_assert((bm_dst == bm_src) || (copy_verts && copy_edges)); + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + i = 0; + do { + if (copy_verts) { + verts[i] = BM_vert_create(bm_dst, l_iter->v->co, l_iter->v, BM_CREATE_NOP); + } + else { + verts[i] = l_iter->v; + } + i++; + } while ((l_iter = l_iter->next) != l_first); + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + i = 0; + do { + if (copy_edges) { + BMVert *v1, *v2; + + if (l_iter->e->v1 == verts[i]) { + v1 = verts[i]; + v2 = verts[(i + 1) % f->len]; + } + else { + v2 = verts[i]; + v1 = verts[(i + 1) % f->len]; + } + + edges[i] = BM_edge_create(bm_dst, v1, v2, l_iter->e, BM_CREATE_NOP); + } + else { + edges[i] = l_iter->e; + } + i++; + } while ((l_iter = l_iter->next) != l_first); + + f_copy = BM_face_create(bm_dst, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD); + + BM_elem_attrs_copy(bm_src, bm_dst, f, f_copy); + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + l_copy = BM_FACE_FIRST_LOOP(f_copy); + do { + BM_elem_attrs_copy(bm_src, bm_dst, l_iter, l_copy); + l_copy = l_copy->next; + } while ((l_iter = l_iter->next) != l_first); + + return f_copy; } /** @@ -367,51 +366,49 @@ BMFace *BM_face_copy( */ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) { - BMFace *f; + BMFace *f; - f = BLI_mempool_alloc(bm->fpool); + f = BLI_mempool_alloc(bm->fpool); - - /* --- assign all members --- */ - f->head.data = NULL; + /* --- assign all members --- */ + f->head.data = NULL; #ifdef USE_DEBUG_INDEX_MEMCHECK - DEBUG_MEMCHECK_INDEX_INVALIDATE(f) + DEBUG_MEMCHECK_INDEX_INVALIDATE(f) #else - BM_elem_index_set(f, -1); /* set_ok_invalid */ + BM_elem_index_set(f, -1); /* set_ok_invalid */ #endif - f->head.htype = BM_FACE; - f->head.hflag = 0; - f->head.api_flag = 0; + f->head.htype = BM_FACE; + f->head.hflag = 0; + f->head.api_flag = 0; - /* allocate flags */ - if (bm->use_toolflags) { - ((BMFace_OFlag *)f)->oflags = bm->ftoolflagpool ? BLI_mempool_calloc(bm->ftoolflagpool) : NULL; - } + /* allocate flags */ + if (bm->use_toolflags) { + ((BMFace_OFlag *)f)->oflags = bm->ftoolflagpool ? BLI_mempool_calloc(bm->ftoolflagpool) : NULL; + } #ifdef USE_BMESH_HOLES - BLI_listbase_clear(&f->loops); + BLI_listbase_clear(&f->loops); #else - f->l_first = NULL; + f->l_first = NULL; #endif - f->len = 0; - /* caller must initialize */ - // zero_v3(f->no); - f->mat_nr = 0; - /* --- done --- */ - + f->len = 0; + /* caller must initialize */ + // zero_v3(f->no); + f->mat_nr = 0; + /* --- done --- */ - /* may add to middle of the pool */ - bm->elem_index_dirty |= BM_FACE; - bm->elem_table_dirty |= BM_FACE; + /* may add to middle of the pool */ + bm->elem_index_dirty |= BM_FACE; + bm->elem_table_dirty |= BM_FACE; - bm->totface++; + bm->totface++; #ifdef USE_BMESH_HOLES - f->totbounds = 0; + f->totbounds = 0; #endif - return f; + return f; } /** @@ -423,91 +420,97 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) * \param len: Length of the face * \param create_flag: Options for creating the face */ -BMFace *BM_face_create( - BMesh *bm, BMVert **verts, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag) +BMFace *BM_face_create(BMesh *bm, + BMVert **verts, + BMEdge **edges, + const int len, + const BMFace *f_example, + const eBMCreateFlag create_flag) { - BMFace *f = NULL; - BMLoop *l, *startl, *lastl; - int i; - - BLI_assert((f_example == NULL) || (f_example->head.htype == BM_FACE)); - BLI_assert(!(create_flag & 1)); - - if (len == 0) { - /* just return NULL for now */ - return NULL; - } - - if (create_flag & BM_CREATE_NO_DOUBLE) { - /* Check if face already exists */ - f = BM_face_exists(verts, len); - if (f != NULL) { - return f; - } - } - - f = bm_face_create__internal(bm); - - startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0], create_flag); - - for (i = 1; i < len; i++) { - l = bm_loop_create(bm, verts[i], edges[i], f, NULL /* edges[i]->l */, create_flag); - - bmesh_radial_loop_append(edges[i], l); - - l->prev = lastl; - lastl->next = l; - lastl = l; - } - - startl->prev = lastl; - lastl->next = startl; - - f->len = len; - - if (!(create_flag & BM_CREATE_SKIP_CD)) { - if (f_example) { - BM_elem_attrs_copy(bm, bm, f_example, f); - } - else { - CustomData_bmesh_set_default(&bm->pdata, &f->head.data); - zero_v3(f->no); - } - } - else { - if (f_example) { - copy_v3_v3(f->no, f_example->no); - } - else { - zero_v3(f->no); - } - } - - BM_CHECK_ELEMENT(f); - - return f; + BMFace *f = NULL; + BMLoop *l, *startl, *lastl; + int i; + + BLI_assert((f_example == NULL) || (f_example->head.htype == BM_FACE)); + BLI_assert(!(create_flag & 1)); + + if (len == 0) { + /* just return NULL for now */ + return NULL; + } + + if (create_flag & BM_CREATE_NO_DOUBLE) { + /* Check if face already exists */ + f = BM_face_exists(verts, len); + if (f != NULL) { + return f; + } + } + + f = bm_face_create__internal(bm); + + startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0], create_flag); + + for (i = 1; i < len; i++) { + l = bm_loop_create(bm, verts[i], edges[i], f, NULL /* edges[i]->l */, create_flag); + + bmesh_radial_loop_append(edges[i], l); + + l->prev = lastl; + lastl->next = l; + lastl = l; + } + + startl->prev = lastl; + lastl->next = startl; + + f->len = len; + + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (f_example) { + BM_elem_attrs_copy(bm, bm, f_example, f); + } + else { + CustomData_bmesh_set_default(&bm->pdata, &f->head.data); + zero_v3(f->no); + } + } + else { + if (f_example) { + copy_v3_v3(f->no, f_example->no); + } + else { + zero_v3(f->no); + } + } + + BM_CHECK_ELEMENT(f); + + return f; } /** * Wrapper for #BM_face_create when you don't have an edge array */ -BMFace *BM_face_create_verts( - BMesh *bm, BMVert **vert_arr, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges) +BMFace *BM_face_create_verts(BMesh *bm, + BMVert **vert_arr, + const int len, + const BMFace *f_example, + const eBMCreateFlag create_flag, + const bool create_edges) { - BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); - - if (create_edges) { - BM_edges_from_verts_ensure(bm, edge_arr, vert_arr, len); - } - else { - if (BM_edges_from_verts(edge_arr, vert_arr, len) == false) { - return NULL; - } - } - - return BM_face_create(bm, vert_arr, edge_arr, len, f_example, create_flag); + BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); + + if (create_edges) { + BM_edges_from_verts_ensure(bm, edge_arr, vert_arr, len); + } + else { + if (BM_edges_from_verts(edge_arr, vert_arr, len) == false) { + return NULL; + } + } + + return BM_face_create(bm, vert_arr, edge_arr, len, f_example, create_flag); } #ifndef NDEBUG @@ -520,221 +523,217 @@ BMFace *BM_face_create_verts( */ int bmesh_elem_check(void *element, const char htype) { - BMHeader *head = element; - enum { - IS_NULL = (1 << 0), - IS_WRONG_TYPE = (1 << 1), - - IS_VERT_WRONG_EDGE_TYPE = (1 << 2), - - IS_EDGE_NULL_DISK_LINK = (1 << 3), - IS_EDGE_WRONG_LOOP_TYPE = (1 << 4), - IS_EDGE_WRONG_FACE_TYPE = (1 << 5), - IS_EDGE_NULL_RADIAL_LINK = (1 << 6), - IS_EDGE_ZERO_FACE_LENGTH = (1 << 7), - - IS_LOOP_WRONG_FACE_TYPE = (1 << 8), - IS_LOOP_WRONG_EDGE_TYPE = (1 << 9), - IS_LOOP_WRONG_VERT_TYPE = (1 << 10), - IS_LOOP_VERT_NOT_IN_EDGE = (1 << 11), - IS_LOOP_NULL_CYCLE_LINK = (1 << 12), - IS_LOOP_ZERO_FACE_LENGTH = (1 << 13), - IS_LOOP_WRONG_FACE_LENGTH = (1 << 14), - IS_LOOP_WRONG_RADIAL_LENGTH = (1 << 15), - - IS_FACE_NULL_LOOP = (1 << 16), - IS_FACE_WRONG_LOOP_FACE = (1 << 17), - IS_FACE_NULL_EDGE = (1 << 18), - IS_FACE_NULL_VERT = (1 << 19), - IS_FACE_LOOP_VERT_NOT_IN_EDGE = (1 << 20), - IS_FACE_LOOP_WRONG_RADIAL_LENGTH = (1 << 21), - IS_FACE_LOOP_WRONG_DISK_LENGTH = (1 << 22), - IS_FACE_LOOP_DUPE_LOOP = (1 << 23), - IS_FACE_LOOP_DUPE_VERT = (1 << 24), - IS_FACE_LOOP_DUPE_EDGE = (1 << 25), - IS_FACE_WRONG_LENGTH = (1 << 26), - } err = 0; - - if (!element) { - return IS_NULL; - } - - if (head->htype != htype) { - return IS_WRONG_TYPE; - } - - switch (htype) { - case BM_VERT: - { - BMVert *v = element; - if (v->e && v->e->head.htype != BM_EDGE) { - err |= IS_VERT_WRONG_EDGE_TYPE; - } - break; - } - case BM_EDGE: - { - BMEdge *e = element; - if (e->v1_disk_link.prev == NULL || - e->v2_disk_link.prev == NULL || - e->v1_disk_link.next == NULL || - e->v2_disk_link.next == NULL) - { - err |= IS_EDGE_NULL_DISK_LINK; - } - - if (e->l && e->l->head.htype != BM_LOOP) { - err |= IS_EDGE_WRONG_LOOP_TYPE; - } - if (e->l && e->l->f->head.htype != BM_FACE) { - err |= IS_EDGE_WRONG_FACE_TYPE; - } - if (e->l && (e->l->radial_next == NULL || e->l->radial_prev == NULL)) { - err |= IS_EDGE_NULL_RADIAL_LINK; - } - if (e->l && e->l->f->len <= 0) { - err |= IS_EDGE_ZERO_FACE_LENGTH; - } - break; - } - case BM_LOOP: - { - BMLoop *l = element, *l2; - int i; - - if (l->f->head.htype != BM_FACE) { - err |= IS_LOOP_WRONG_FACE_TYPE; - } - if (l->e->head.htype != BM_EDGE) { - err |= IS_LOOP_WRONG_EDGE_TYPE; - } - if (l->v->head.htype != BM_VERT) { - err |= IS_LOOP_WRONG_VERT_TYPE; - } - if (!BM_vert_in_edge(l->e, l->v)) { - fprintf(stderr, "%s: fatal bmesh error (vert not in edge)! (bmesh internal error)\n", __func__); - err |= IS_LOOP_VERT_NOT_IN_EDGE; - } - - if (l->radial_next == NULL || l->radial_prev == NULL) { - err |= IS_LOOP_NULL_CYCLE_LINK; - } - if (l->f->len <= 0) { - err |= IS_LOOP_ZERO_FACE_LENGTH; - } - - /* validate boundary loop -- invalid for hole loops, of course, - * but we won't be allowing those for a while yet */ - l2 = l; - i = 0; - do { - if (i >= BM_NGON_MAX) { - break; - } - - i++; - } while ((l2 = l2->next) != l); - - if (i != l->f->len || l2 != l) { - err |= IS_LOOP_WRONG_FACE_LENGTH; - } - - if (!bmesh_radial_validate(bmesh_radial_length(l), l)) { - err |= IS_LOOP_WRONG_RADIAL_LENGTH; - } - - break; - } - case BM_FACE: - { - BMFace *f = element; - BMLoop *l_iter; - BMLoop *l_first; - int len = 0; - -#ifdef USE_BMESH_HOLES - if (!f->loops.first) -#else - if (!f->l_first) -#endif - { - err |= IS_FACE_NULL_LOOP; - } - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (l_iter->f != f) { - fprintf(stderr, "%s: loop inside one face points to another! (bmesh internal error)\n", __func__); - err |= IS_FACE_WRONG_LOOP_FACE; - } - - if (!l_iter->e) { - err |= IS_FACE_NULL_EDGE; - } - if (!l_iter->v) { - err |= IS_FACE_NULL_VERT; - } - if (l_iter->e && l_iter->v) { - if (!BM_vert_in_edge(l_iter->e, l_iter->v) || - !BM_vert_in_edge(l_iter->e, l_iter->next->v)) - { - err |= IS_FACE_LOOP_VERT_NOT_IN_EDGE; - } - - if (!bmesh_radial_validate(bmesh_radial_length(l_iter), l_iter)) { - err |= IS_FACE_LOOP_WRONG_RADIAL_LENGTH; - } - - if (bmesh_disk_count_at_most(l_iter->v, 2) < 2) { - err |= IS_FACE_LOOP_WRONG_DISK_LENGTH; - } - } - - /* check for duplicates */ - if (BM_ELEM_API_FLAG_TEST(l_iter, _FLAG_ELEM_CHECK)) { - err |= IS_FACE_LOOP_DUPE_LOOP; - } - BM_ELEM_API_FLAG_ENABLE(l_iter, _FLAG_ELEM_CHECK); - if (l_iter->v) { - if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_ELEM_CHECK)) { - err |= IS_FACE_LOOP_DUPE_VERT; - } - BM_ELEM_API_FLAG_ENABLE(l_iter->v, _FLAG_ELEM_CHECK); - } - if (l_iter->e) { - if (BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_ELEM_CHECK)) { - err |= IS_FACE_LOOP_DUPE_EDGE; - } - BM_ELEM_API_FLAG_ENABLE(l_iter->e, _FLAG_ELEM_CHECK); - } - - len++; - } while ((l_iter = l_iter->next) != l_first); - - /* cleanup duplicates flag */ - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_ELEM_API_FLAG_DISABLE(l_iter, _FLAG_ELEM_CHECK); - if (l_iter->v) { - BM_ELEM_API_FLAG_DISABLE(l_iter->v, _FLAG_ELEM_CHECK); - } - if (l_iter->e) { - BM_ELEM_API_FLAG_DISABLE(l_iter->e, _FLAG_ELEM_CHECK); - } - } while ((l_iter = l_iter->next) != l_first); - - if (len != f->len) { - err |= IS_FACE_WRONG_LENGTH; - } - break; - } - default: - BLI_assert(0); - break; - } - - BMESH_ASSERT(err == 0); - - return err; + BMHeader *head = element; + enum { + IS_NULL = (1 << 0), + IS_WRONG_TYPE = (1 << 1), + + IS_VERT_WRONG_EDGE_TYPE = (1 << 2), + + IS_EDGE_NULL_DISK_LINK = (1 << 3), + IS_EDGE_WRONG_LOOP_TYPE = (1 << 4), + IS_EDGE_WRONG_FACE_TYPE = (1 << 5), + IS_EDGE_NULL_RADIAL_LINK = (1 << 6), + IS_EDGE_ZERO_FACE_LENGTH = (1 << 7), + + IS_LOOP_WRONG_FACE_TYPE = (1 << 8), + IS_LOOP_WRONG_EDGE_TYPE = (1 << 9), + IS_LOOP_WRONG_VERT_TYPE = (1 << 10), + IS_LOOP_VERT_NOT_IN_EDGE = (1 << 11), + IS_LOOP_NULL_CYCLE_LINK = (1 << 12), + IS_LOOP_ZERO_FACE_LENGTH = (1 << 13), + IS_LOOP_WRONG_FACE_LENGTH = (1 << 14), + IS_LOOP_WRONG_RADIAL_LENGTH = (1 << 15), + + IS_FACE_NULL_LOOP = (1 << 16), + IS_FACE_WRONG_LOOP_FACE = (1 << 17), + IS_FACE_NULL_EDGE = (1 << 18), + IS_FACE_NULL_VERT = (1 << 19), + IS_FACE_LOOP_VERT_NOT_IN_EDGE = (1 << 20), + IS_FACE_LOOP_WRONG_RADIAL_LENGTH = (1 << 21), + IS_FACE_LOOP_WRONG_DISK_LENGTH = (1 << 22), + IS_FACE_LOOP_DUPE_LOOP = (1 << 23), + IS_FACE_LOOP_DUPE_VERT = (1 << 24), + IS_FACE_LOOP_DUPE_EDGE = (1 << 25), + IS_FACE_WRONG_LENGTH = (1 << 26), + } err = 0; + + if (!element) { + return IS_NULL; + } + + if (head->htype != htype) { + return IS_WRONG_TYPE; + } + + switch (htype) { + case BM_VERT: { + BMVert *v = element; + if (v->e && v->e->head.htype != BM_EDGE) { + err |= IS_VERT_WRONG_EDGE_TYPE; + } + break; + } + case BM_EDGE: { + BMEdge *e = element; + if (e->v1_disk_link.prev == NULL || e->v2_disk_link.prev == NULL || + e->v1_disk_link.next == NULL || e->v2_disk_link.next == NULL) { + err |= IS_EDGE_NULL_DISK_LINK; + } + + if (e->l && e->l->head.htype != BM_LOOP) { + err |= IS_EDGE_WRONG_LOOP_TYPE; + } + if (e->l && e->l->f->head.htype != BM_FACE) { + err |= IS_EDGE_WRONG_FACE_TYPE; + } + if (e->l && (e->l->radial_next == NULL || e->l->radial_prev == NULL)) { + err |= IS_EDGE_NULL_RADIAL_LINK; + } + if (e->l && e->l->f->len <= 0) { + err |= IS_EDGE_ZERO_FACE_LENGTH; + } + break; + } + case BM_LOOP: { + BMLoop *l = element, *l2; + int i; + + if (l->f->head.htype != BM_FACE) { + err |= IS_LOOP_WRONG_FACE_TYPE; + } + if (l->e->head.htype != BM_EDGE) { + err |= IS_LOOP_WRONG_EDGE_TYPE; + } + if (l->v->head.htype != BM_VERT) { + err |= IS_LOOP_WRONG_VERT_TYPE; + } + if (!BM_vert_in_edge(l->e, l->v)) { + fprintf(stderr, + "%s: fatal bmesh error (vert not in edge)! (bmesh internal error)\n", + __func__); + err |= IS_LOOP_VERT_NOT_IN_EDGE; + } + + if (l->radial_next == NULL || l->radial_prev == NULL) { + err |= IS_LOOP_NULL_CYCLE_LINK; + } + if (l->f->len <= 0) { + err |= IS_LOOP_ZERO_FACE_LENGTH; + } + + /* validate boundary loop -- invalid for hole loops, of course, + * but we won't be allowing those for a while yet */ + l2 = l; + i = 0; + do { + if (i >= BM_NGON_MAX) { + break; + } + + i++; + } while ((l2 = l2->next) != l); + + if (i != l->f->len || l2 != l) { + err |= IS_LOOP_WRONG_FACE_LENGTH; + } + + if (!bmesh_radial_validate(bmesh_radial_length(l), l)) { + err |= IS_LOOP_WRONG_RADIAL_LENGTH; + } + + break; + } + case BM_FACE: { + BMFace *f = element; + BMLoop *l_iter; + BMLoop *l_first; + int len = 0; + +# ifdef USE_BMESH_HOLES + if (!f->loops.first) +# else + if (!f->l_first) +# endif + { + err |= IS_FACE_NULL_LOOP; + } + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (l_iter->f != f) { + fprintf(stderr, + "%s: loop inside one face points to another! (bmesh internal error)\n", + __func__); + err |= IS_FACE_WRONG_LOOP_FACE; + } + + if (!l_iter->e) { + err |= IS_FACE_NULL_EDGE; + } + if (!l_iter->v) { + err |= IS_FACE_NULL_VERT; + } + if (l_iter->e && l_iter->v) { + if (!BM_vert_in_edge(l_iter->e, l_iter->v) || + !BM_vert_in_edge(l_iter->e, l_iter->next->v)) { + err |= IS_FACE_LOOP_VERT_NOT_IN_EDGE; + } + + if (!bmesh_radial_validate(bmesh_radial_length(l_iter), l_iter)) { + err |= IS_FACE_LOOP_WRONG_RADIAL_LENGTH; + } + + if (bmesh_disk_count_at_most(l_iter->v, 2) < 2) { + err |= IS_FACE_LOOP_WRONG_DISK_LENGTH; + } + } + + /* check for duplicates */ + if (BM_ELEM_API_FLAG_TEST(l_iter, _FLAG_ELEM_CHECK)) { + err |= IS_FACE_LOOP_DUPE_LOOP; + } + BM_ELEM_API_FLAG_ENABLE(l_iter, _FLAG_ELEM_CHECK); + if (l_iter->v) { + if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_ELEM_CHECK)) { + err |= IS_FACE_LOOP_DUPE_VERT; + } + BM_ELEM_API_FLAG_ENABLE(l_iter->v, _FLAG_ELEM_CHECK); + } + if (l_iter->e) { + if (BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_ELEM_CHECK)) { + err |= IS_FACE_LOOP_DUPE_EDGE; + } + BM_ELEM_API_FLAG_ENABLE(l_iter->e, _FLAG_ELEM_CHECK); + } + + len++; + } while ((l_iter = l_iter->next) != l_first); + + /* cleanup duplicates flag */ + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BM_ELEM_API_FLAG_DISABLE(l_iter, _FLAG_ELEM_CHECK); + if (l_iter->v) { + BM_ELEM_API_FLAG_DISABLE(l_iter->v, _FLAG_ELEM_CHECK); + } + if (l_iter->e) { + BM_ELEM_API_FLAG_DISABLE(l_iter->e, _FLAG_ELEM_CHECK); + } + } while ((l_iter = l_iter->next) != l_first); + + if (len != f->len) { + err |= IS_FACE_WRONG_LENGTH; + } + break; + } + default: + BLI_assert(0); + break; + } + + BMESH_ASSERT(err == 0); + + return err; } #endif /* NDEBUG */ @@ -745,20 +744,20 @@ int bmesh_elem_check(void *element, const char htype) */ static void bm_kill_only_vert(BMesh *bm, BMVert *v) { - bm->totvert--; - bm->elem_index_dirty |= BM_VERT; - bm->elem_table_dirty |= BM_VERT; + bm->totvert--; + bm->elem_index_dirty |= BM_VERT; + bm->elem_table_dirty |= BM_VERT; - BM_select_history_remove(bm, v); + BM_select_history_remove(bm, v); - if (v->head.data) { - CustomData_bmesh_free_block(&bm->vdata, &v->head.data); - } + if (v->head.data) { + CustomData_bmesh_free_block(&bm->vdata, &v->head.data); + } - if (bm->vtoolflagpool) { - BLI_mempool_free(bm->vtoolflagpool, ((BMVert_OFlag *)v)->oflags); - } - BLI_mempool_free(bm->vpool, v); + if (bm->vtoolflagpool) { + BLI_mempool_free(bm->vtoolflagpool, ((BMVert_OFlag *)v)->oflags); + } + BLI_mempool_free(bm->vpool, v); } /** @@ -767,20 +766,20 @@ static void bm_kill_only_vert(BMesh *bm, BMVert *v) */ static void bm_kill_only_edge(BMesh *bm, BMEdge *e) { - bm->totedge--; - bm->elem_index_dirty |= BM_EDGE; - bm->elem_table_dirty |= BM_EDGE; + bm->totedge--; + bm->elem_index_dirty |= BM_EDGE; + bm->elem_table_dirty |= BM_EDGE; - BM_select_history_remove(bm, (BMElem *)e); + BM_select_history_remove(bm, (BMElem *)e); - if (e->head.data) { - CustomData_bmesh_free_block(&bm->edata, &e->head.data); - } + if (e->head.data) { + CustomData_bmesh_free_block(&bm->edata, &e->head.data); + } - if (bm->etoolflagpool) { - BLI_mempool_free(bm->etoolflagpool, ((BMEdge_OFlag *)e)->oflags); - } - BLI_mempool_free(bm->epool, e); + if (bm->etoolflagpool) { + BLI_mempool_free(bm->etoolflagpool, ((BMEdge_OFlag *)e)->oflags); + } + BLI_mempool_free(bm->epool, e); } /** @@ -789,24 +788,24 @@ static void bm_kill_only_edge(BMesh *bm, BMEdge *e) */ static void bm_kill_only_face(BMesh *bm, BMFace *f) { - if (bm->act_face == f) { - bm->act_face = NULL; - } + if (bm->act_face == f) { + bm->act_face = NULL; + } - bm->totface--; - bm->elem_index_dirty |= BM_FACE; - bm->elem_table_dirty |= BM_FACE; + bm->totface--; + bm->elem_index_dirty |= BM_FACE; + bm->elem_table_dirty |= BM_FACE; - BM_select_history_remove(bm, (BMElem *)f); + BM_select_history_remove(bm, (BMElem *)f); - if (f->head.data) { - CustomData_bmesh_free_block(&bm->pdata, &f->head.data); - } + if (f->head.data) { + CustomData_bmesh_free_block(&bm->pdata, &f->head.data); + } - if (bm->ftoolflagpool) { - BLI_mempool_free(bm->ftoolflagpool, ((BMFace_OFlag *)f)->oflags); - } - BLI_mempool_free(bm->fpool, f); + if (bm->ftoolflagpool) { + BLI_mempool_free(bm->ftoolflagpool, ((BMFace_OFlag *)f)->oflags); + } + BLI_mempool_free(bm->fpool, f); } /** @@ -815,13 +814,13 @@ static void bm_kill_only_face(BMesh *bm, BMFace *f) */ static void bm_kill_only_loop(BMesh *bm, BMLoop *l) { - bm->totloop--; - bm->elem_index_dirty |= BM_LOOP; - if (l->head.data) { - CustomData_bmesh_free_block(&bm->ldata, &l->head.data); - } + bm->totloop--; + bm->elem_index_dirty |= BM_LOOP; + if (l->head.data) { + CustomData_bmesh_free_block(&bm->ldata, &l->head.data); + } - BLI_mempool_free(bm->lpool, l); + BLI_mempool_free(bm->lpool, l); } /** @@ -830,19 +829,19 @@ static void bm_kill_only_loop(BMesh *bm, BMLoop *l) */ void BM_face_edges_kill(BMesh *bm, BMFace *f) { - BMEdge **edges = BLI_array_alloca(edges, f->len); - BMLoop *l_iter; - BMLoop *l_first; - int i = 0; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - edges[i++] = l_iter->e; - } while ((l_iter = l_iter->next) != l_first); - - for (i = 0; i < f->len; i++) { - BM_edge_kill(bm, edges[i]); - } + BMEdge **edges = BLI_array_alloca(edges, f->len); + BMLoop *l_iter; + BMLoop *l_first; + int i = 0; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + edges[i++] = l_iter->e; + } while ((l_iter = l_iter->next) != l_first); + + for (i = 0; i < f->len; i++) { + BM_edge_kill(bm, edges[i]); + } } /** @@ -851,19 +850,19 @@ void BM_face_edges_kill(BMesh *bm, BMFace *f) */ void BM_face_verts_kill(BMesh *bm, BMFace *f) { - BMVert **verts = BLI_array_alloca(verts, f->len); - BMLoop *l_iter; - BMLoop *l_first; - int i = 0; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - verts[i++] = l_iter->v; - } while ((l_iter = l_iter->next) != l_first); - - for (i = 0; i < f->len; i++) { - BM_vert_kill(bm, verts[i]); - } + BMVert **verts = BLI_array_alloca(verts, f->len); + BMLoop *l_iter; + BMLoop *l_first; + int i = 0; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + verts[i++] = l_iter->v; + } while ((l_iter = l_iter->next) != l_first); + + for (i = 0; i < f->len; i++) { + BM_vert_kill(bm, verts[i]); + } } /** @@ -872,45 +871,45 @@ void BM_face_verts_kill(BMesh *bm, BMFace *f) void BM_face_kill(BMesh *bm, BMFace *f) { #ifdef USE_BMESH_HOLES - BMLoopList *ls, *ls_next; + BMLoopList *ls, *ls_next; #endif #ifdef NDEBUG - /* check length since we may be removing degenerate faces */ - if (f->len >= 3) { - BM_CHECK_ELEMENT(f); - } + /* check length since we may be removing degenerate faces */ + if (f->len >= 3) { + BM_CHECK_ELEMENT(f); + } #endif #ifdef USE_BMESH_HOLES - for (ls = f->loops.first; ls; ls = ls_next) + for (ls = f->loops.first; ls; ls = ls_next) #else - if (f->l_first) + if (f->l_first) #endif - { - BMLoop *l_iter, *l_next, *l_first; + { + BMLoop *l_iter, *l_next, *l_first; #ifdef USE_BMESH_HOLES - ls_next = ls->next; - l_iter = l_first = ls->first; + ls_next = ls->next; + l_iter = l_first = ls->first; #else - l_iter = l_first = f->l_first; + l_iter = l_first = f->l_first; #endif - do { - l_next = l_iter->next; + do { + l_next = l_iter->next; - bmesh_radial_loop_remove(l_iter->e, l_iter); - bm_kill_only_loop(bm, l_iter); + bmesh_radial_loop_remove(l_iter->e, l_iter); + bm_kill_only_loop(bm, l_iter); - } while ((l_iter = l_next) != l_first); + } while ((l_iter = l_next) != l_first); #ifdef USE_BMESH_HOLES - BLI_mempool_free(bm->looplistpool, ls); + BLI_mempool_free(bm->looplistpool, ls); #endif - } + } - bm_kill_only_face(bm, f); + bm_kill_only_face(bm, f); } /** @@ -920,56 +919,56 @@ void BM_face_kill(BMesh *bm, BMFace *f) void BM_face_kill_loose(BMesh *bm, BMFace *f) { #ifdef USE_BMESH_HOLES - BMLoopList *ls, *ls_next; + BMLoopList *ls, *ls_next; #endif - BM_CHECK_ELEMENT(f); + BM_CHECK_ELEMENT(f); #ifdef USE_BMESH_HOLES - for (ls = f->loops.first; ls; ls = ls_next) + for (ls = f->loops.first; ls; ls = ls_next) #else - if (f->l_first) + if (f->l_first) #endif - { - BMLoop *l_iter, *l_next, *l_first; + { + BMLoop *l_iter, *l_next, *l_first; #ifdef USE_BMESH_HOLES - ls_next = ls->next; - l_iter = l_first = ls->first; + ls_next = ls->next; + l_iter = l_first = ls->first; #else - l_iter = l_first = f->l_first; + l_iter = l_first = f->l_first; #endif - do { - BMEdge *e; - l_next = l_iter->next; + do { + BMEdge *e; + l_next = l_iter->next; - e = l_iter->e; - bmesh_radial_loop_remove(e, l_iter); - bm_kill_only_loop(bm, l_iter); + e = l_iter->e; + bmesh_radial_loop_remove(e, l_iter); + bm_kill_only_loop(bm, l_iter); - if (e->l == NULL) { - BMVert *v1 = e->v1, *v2 = e->v2; + if (e->l == NULL) { + BMVert *v1 = e->v1, *v2 = e->v2; - bmesh_disk_edge_remove(e, e->v1); - bmesh_disk_edge_remove(e, e->v2); - bm_kill_only_edge(bm, e); + bmesh_disk_edge_remove(e, e->v1); + bmesh_disk_edge_remove(e, e->v2); + bm_kill_only_edge(bm, e); - if (v1->e == NULL) { - bm_kill_only_vert(bm, v1); - } - if (v2->e == NULL) { - bm_kill_only_vert(bm, v2); - } - } - } while ((l_iter = l_next) != l_first); + if (v1->e == NULL) { + bm_kill_only_vert(bm, v1); + } + if (v2->e == NULL) { + bm_kill_only_vert(bm, v2); + } + } + } while ((l_iter = l_next) != l_first); #ifdef USE_BMESH_HOLES - BLI_mempool_free(bm->looplistpool, ls); + BLI_mempool_free(bm->looplistpool, ls); #endif - } + } - bm_kill_only_face(bm, f); + bm_kill_only_face(bm, f); } /** @@ -977,14 +976,14 @@ void BM_face_kill_loose(BMesh *bm, BMFace *f) */ void BM_edge_kill(BMesh *bm, BMEdge *e) { - while (e->l) { - BM_face_kill(bm, e->l->f); - } + while (e->l) { + BM_face_kill(bm, e->l->f); + } - bmesh_disk_edge_remove(e, e->v1); - bmesh_disk_edge_remove(e, e->v2); + bmesh_disk_edge_remove(e, e->v1); + bmesh_disk_edge_remove(e, e->v2); - bm_kill_only_edge(bm, e); + bm_kill_only_edge(bm, e); } /** @@ -992,11 +991,11 @@ void BM_edge_kill(BMesh *bm, BMEdge *e) */ void BM_vert_kill(BMesh *bm, BMVert *v) { - while (v->e) { - BM_edge_kill(bm, v->e); - } + while (v->e) { + BM_edge_kill(bm, v->e); + } - bm_kill_only_vert(bm, v); + bm_kill_only_vert(bm, v); } /********** private disk and radial cycle functions ********** */ @@ -1006,14 +1005,14 @@ void BM_vert_kill(BMesh *bm, BMVert *v) */ static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l) { - BMLoop *l_first = l; - int i = 0; + BMLoop *l_first = l; + int i = 0; - do { - i++; - } while ((l = l->next) != l_first); + do { + i++; + } while ((l = l->next) != l_first); - return i; + return i; } /** @@ -1025,126 +1024,127 @@ static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l) * \param use_loop_mdisp_flip: When set, flip the Z-depth of the mdisp, * (use when flipping normals, disable when mirroring, eg: symmetrize). */ -void bmesh_kernel_loop_reverse( - BMesh *bm, BMFace *f, - const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip) +void bmesh_kernel_loop_reverse(BMesh *bm, + BMFace *f, + const int cd_loop_mdisp_offset, + const bool use_loop_mdisp_flip) { - BMLoop *l_first = f->l_first; + BMLoop *l_first = f->l_first; - /* track previous cycles radial state */ - BMEdge *e_prev = l_first->prev->e; - BMLoop *l_prev_radial_next = l_first->prev->radial_next; - BMLoop *l_prev_radial_prev = l_first->prev->radial_prev; - bool is_prev_boundary = l_prev_radial_next == l_prev_radial_next->radial_next; + /* track previous cycles radial state */ + BMEdge *e_prev = l_first->prev->e; + BMLoop *l_prev_radial_next = l_first->prev->radial_next; + BMLoop *l_prev_radial_prev = l_first->prev->radial_prev; + bool is_prev_boundary = l_prev_radial_next == l_prev_radial_next->radial_next; - BMLoop *l_iter = l_first; - do { - BMEdge *e_iter = l_iter->e; - BMLoop *l_iter_radial_next = l_iter->radial_next; - BMLoop *l_iter_radial_prev = l_iter->radial_prev; - bool is_iter_boundary = l_iter_radial_next == l_iter_radial_next->radial_next; + BMLoop *l_iter = l_first; + do { + BMEdge *e_iter = l_iter->e; + BMLoop *l_iter_radial_next = l_iter->radial_next; + BMLoop *l_iter_radial_prev = l_iter->radial_prev; + bool is_iter_boundary = l_iter_radial_next == l_iter_radial_next->radial_next; #if 0 - bmesh_radial_loop_remove(e_iter, l_iter); - bmesh_radial_loop_append(e_prev, l_iter); + bmesh_radial_loop_remove(e_iter, l_iter); + bmesh_radial_loop_append(e_prev, l_iter); #else - /* inline loop reversal */ - if (is_prev_boundary) { - /* boundary */ - l_iter->radial_next = l_iter; - l_iter->radial_prev = l_iter; - } - else { - /* non-boundary, replace radial links */ - l_iter->radial_next = l_prev_radial_next; - l_iter->radial_prev = l_prev_radial_prev; - l_prev_radial_next->radial_prev = l_iter; - l_prev_radial_prev->radial_next = l_iter; - } - - if (e_iter->l == l_iter) { - e_iter->l = l_iter->next; - } - l_iter->e = e_prev; + /* inline loop reversal */ + if (is_prev_boundary) { + /* boundary */ + l_iter->radial_next = l_iter; + l_iter->radial_prev = l_iter; + } + else { + /* non-boundary, replace radial links */ + l_iter->radial_next = l_prev_radial_next; + l_iter->radial_prev = l_prev_radial_prev; + l_prev_radial_next->radial_prev = l_iter; + l_prev_radial_prev->radial_next = l_iter; + } + + if (e_iter->l == l_iter) { + e_iter->l = l_iter->next; + } + l_iter->e = e_prev; #endif - SWAP(BMLoop *, l_iter->next, l_iter->prev); + SWAP(BMLoop *, l_iter->next, l_iter->prev); - if (cd_loop_mdisp_offset != -1) { - MDisps *md = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset); - BKE_mesh_mdisp_flip(md, use_loop_mdisp_flip); - } + if (cd_loop_mdisp_offset != -1) { + MDisps *md = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset); + BKE_mesh_mdisp_flip(md, use_loop_mdisp_flip); + } - e_prev = e_iter; - l_prev_radial_next = l_iter_radial_next; - l_prev_radial_prev = l_iter_radial_prev; - is_prev_boundary = is_iter_boundary; + e_prev = e_iter; + l_prev_radial_next = l_iter_radial_next; + l_prev_radial_prev = l_iter_radial_prev; + is_prev_boundary = is_iter_boundary; - /* step to next (now swapped) */ - } while ((l_iter = l_iter->prev) != l_first); + /* step to next (now swapped) */ + } while ((l_iter = l_iter->prev) != l_first); #ifndef NDEBUG - /* validate radial */ - int i; - for (i = 0, l_iter = l_first; i < f->len; i++, l_iter = l_iter->next) { - BM_CHECK_ELEMENT(l_iter); - BM_CHECK_ELEMENT(l_iter->e); - BM_CHECK_ELEMENT(l_iter->v); - BM_CHECK_ELEMENT(l_iter->f); - } - - BM_CHECK_ELEMENT(f); + /* validate radial */ + int i; + for (i = 0, l_iter = l_first; i < f->len; i++, l_iter = l_iter->next) { + BM_CHECK_ELEMENT(l_iter); + BM_CHECK_ELEMENT(l_iter->e); + BM_CHECK_ELEMENT(l_iter->v); + BM_CHECK_ELEMENT(l_iter->f); + } + + BM_CHECK_ELEMENT(f); #endif - /* Loop indices are no more valid! */ - bm->elem_index_dirty |= BM_LOOP; + /* Loop indices are no more valid! */ + bm->elem_index_dirty |= BM_LOOP; } static void bm_elements_systag_enable(void *veles, int tot, const char api_flag) { - BMHeader **eles = veles; - int i; + BMHeader **eles = veles; + int i; - for (i = 0; i < tot; i++) { - BM_ELEM_API_FLAG_ENABLE((BMElemF *)eles[i], api_flag); - } + for (i = 0; i < tot; i++) { + BM_ELEM_API_FLAG_ENABLE((BMElemF *)eles[i], api_flag); + } } static void bm_elements_systag_disable(void *veles, int tot, const char api_flag) { - BMHeader **eles = veles; - int i; + BMHeader **eles = veles; + int i; - for (i = 0; i < tot; i++) { - BM_ELEM_API_FLAG_DISABLE((BMElemF *)eles[i], api_flag); - } + for (i = 0; i < tot; i++) { + BM_ELEM_API_FLAG_DISABLE((BMElemF *)eles[i], api_flag); + } } static int bm_loop_systag_count_radial(BMLoop *l, const char api_flag) { - BMLoop *l_iter = l; - int i = 0; - do { - i += BM_ELEM_API_FLAG_TEST(l_iter->f, api_flag) ? 1 : 0; - } while ((l_iter = l_iter->radial_next) != l); + BMLoop *l_iter = l; + int i = 0; + do { + i += BM_ELEM_API_FLAG_TEST(l_iter->f, api_flag) ? 1 : 0; + } while ((l_iter = l_iter->radial_next) != l); - return i; + return i; } static int UNUSED_FUNCTION(bm_vert_systag_count_disk)(BMVert *v, const char api_flag) { - BMEdge *e = v->e; - int i = 0; + BMEdge *e = v->e; + int i = 0; - if (!e) { - return 0; - } + if (!e) { + return 0; + } - do { - i += BM_ELEM_API_FLAG_TEST(e, api_flag) ? 1 : 0; - } while ((e = bmesh_disk_edge_next(e, v)) != v->e); + do { + i += BM_ELEM_API_FLAG_TEST(e, api_flag) ? 1 : 0; + } while ((e = bmesh_disk_edge_next(e, v)) != v->e); - return i; + return i; } /** @@ -1153,31 +1153,31 @@ static int UNUSED_FUNCTION(bm_vert_systag_count_disk)(BMVert *v, const char api_ */ static bool bm_vert_is_manifold_flagged(BMVert *v, const char api_flag) { - BMEdge *e = v->e; + BMEdge *e = v->e; - if (!e) { - return false; - } + if (!e) { + return false; + } - do { - BMLoop *l = e->l; + do { + BMLoop *l = e->l; - if (!l) { - return false; - } + if (!l) { + return false; + } - if (BM_edge_is_boundary(l->e)) { - return false; - } + if (BM_edge_is_boundary(l->e)) { + return false; + } - do { - if (!BM_ELEM_API_FLAG_TEST(l->f, api_flag)) { - return false; - } - } while ((l = l->radial_next) != e->l); - } while ((e = bmesh_disk_edge_next(e, v)) != v->e); + do { + if (!BM_ELEM_API_FLAG_TEST(l->f, api_flag)) { + return false; + } + } while ((l = l->radial_next) != e->l); + } while ((e = bmesh_disk_edge_next(e, v)) != v->e); - return true; + return true; } /* Mid-level Topology Manipulation Functions */ @@ -1198,216 +1198,218 @@ static bool bm_vert_is_manifold_flagged(BMVert *v, const char api_flag) */ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) { - BMFace *f, *f_new; + BMFace *f, *f_new; #ifdef USE_BMESH_HOLES - BMLoopList *lst; - ListBase holes = {NULL, NULL}; + BMLoopList *lst; + ListBase holes = {NULL, NULL}; #endif - BMLoop *l_iter; - BMLoop *l_first; - BMEdge **edges = NULL; - BMEdge **deledges = NULL; - BMVert **delverts = NULL; - BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); - BLI_array_staticdeclare(deledges, BM_DEFAULT_NGON_STACK_SIZE); - BLI_array_staticdeclare(delverts, BM_DEFAULT_NGON_STACK_SIZE); - BMVert *v1 = NULL, *v2 = NULL; - int i; - const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); - - if (UNLIKELY(!totface)) { - BMESH_ASSERT(0); - return NULL; - } - - if (totface == 1) { - return faces[0]; - } - - bm_elements_systag_enable(faces, totface, _FLAG_JF); - - for (i = 0; i < totface; i++) { - f = faces[i]; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - int rlen = bm_loop_systag_count_radial(l_iter, _FLAG_JF); - - if (rlen > 2) { - /* Input faces do not form a contiguous manifold region */ - goto error; - } - else if (rlen == 1) { - BLI_array_append(edges, l_iter->e); - - if (!v1) { - v1 = l_iter->v; - v2 = BM_edge_other_vert(l_iter->e, l_iter->v); - } - } - else if (rlen == 2) { - const bool d1 = bm_vert_is_manifold_flagged(l_iter->e->v1, _FLAG_JF); - const bool d2 = bm_vert_is_manifold_flagged(l_iter->e->v2, _FLAG_JF); - - if (!d1 && !d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_JF)) { - /* don't remove an edge it makes up the side of another face - * else this will remove the face as well - campbell */ - if (!BM_edge_face_count_is_over(l_iter->e, 2)) { - if (do_del) { - BLI_array_append(deledges, l_iter->e); - } - BM_ELEM_API_FLAG_ENABLE(l_iter->e, _FLAG_JF); - } - } - else { - if (d1 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v1, _FLAG_JF)) { - if (do_del) { - BLI_array_append(delverts, l_iter->e->v1); - } - BM_ELEM_API_FLAG_ENABLE(l_iter->e->v1, _FLAG_JF); - } - - if (d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v2, _FLAG_JF)) { - if (do_del) { - BLI_array_append(delverts, l_iter->e->v2); - } - BM_ELEM_API_FLAG_ENABLE(l_iter->e->v2, _FLAG_JF); - } - } - } - } while ((l_iter = l_iter->next) != l_first); + BMLoop *l_iter; + BMLoop *l_first; + BMEdge **edges = NULL; + BMEdge **deledges = NULL; + BMVert **delverts = NULL; + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_staticdeclare(deledges, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_staticdeclare(delverts, BM_DEFAULT_NGON_STACK_SIZE); + BMVert *v1 = NULL, *v2 = NULL; + int i; + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + + if (UNLIKELY(!totface)) { + BMESH_ASSERT(0); + return NULL; + } + + if (totface == 1) { + return faces[0]; + } + + bm_elements_systag_enable(faces, totface, _FLAG_JF); + + for (i = 0; i < totface; i++) { + f = faces[i]; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + int rlen = bm_loop_systag_count_radial(l_iter, _FLAG_JF); + + if (rlen > 2) { + /* Input faces do not form a contiguous manifold region */ + goto error; + } + else if (rlen == 1) { + BLI_array_append(edges, l_iter->e); + + if (!v1) { + v1 = l_iter->v; + v2 = BM_edge_other_vert(l_iter->e, l_iter->v); + } + } + else if (rlen == 2) { + const bool d1 = bm_vert_is_manifold_flagged(l_iter->e->v1, _FLAG_JF); + const bool d2 = bm_vert_is_manifold_flagged(l_iter->e->v2, _FLAG_JF); + + if (!d1 && !d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_JF)) { + /* don't remove an edge it makes up the side of another face + * else this will remove the face as well - campbell */ + if (!BM_edge_face_count_is_over(l_iter->e, 2)) { + if (do_del) { + BLI_array_append(deledges, l_iter->e); + } + BM_ELEM_API_FLAG_ENABLE(l_iter->e, _FLAG_JF); + } + } + else { + if (d1 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v1, _FLAG_JF)) { + if (do_del) { + BLI_array_append(delverts, l_iter->e->v1); + } + BM_ELEM_API_FLAG_ENABLE(l_iter->e->v1, _FLAG_JF); + } + + if (d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v2, _FLAG_JF)) { + if (do_del) { + BLI_array_append(delverts, l_iter->e->v2); + } + BM_ELEM_API_FLAG_ENABLE(l_iter->e->v2, _FLAG_JF); + } + } + } + } while ((l_iter = l_iter->next) != l_first); #ifdef USE_BMESH_HOLES - for (lst = f->loops.first; lst; lst = lst->next) { - if (lst == f->loops.first) { - continue; - } - - BLI_remlink(&f->loops, lst); - BLI_addtail(&holes, lst); - } + for (lst = f->loops.first; lst; lst = lst->next) { + if (lst == f->loops.first) { + continue; + } + + BLI_remlink(&f->loops, lst); + BLI_addtail(&holes, lst); + } #endif - - } - - /* create region face */ - f_new = BLI_array_len(edges) ? - BM_face_create_ngon(bm, v1, v2, edges, BLI_array_len(edges), faces[0], BM_CREATE_NOP) : NULL; - if (UNLIKELY(f_new == NULL)) { - /* Invalid boundary region to join faces */ - goto error; - } - - /* copy over loop data */ - l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); - do { - BMLoop *l2 = l_iter->radial_next; - - do { - if (BM_ELEM_API_FLAG_TEST(l2->f, _FLAG_JF)) { - break; - } - l2 = l2->radial_next; - } while (l2 != l_iter); - - if (l2 != l_iter) { - /* loops share an edge, shared vert depends on winding */ - if (l2->v != l_iter->v) { - l2 = l2->next; - } - BLI_assert(l_iter->v == l2->v); - - BM_elem_attrs_copy(bm, bm, l2, l_iter); - } - } while ((l_iter = l_iter->next) != l_first); + } + + /* create region face */ + f_new = BLI_array_len(edges) ? + BM_face_create_ngon( + bm, v1, v2, edges, BLI_array_len(edges), faces[0], BM_CREATE_NOP) : + NULL; + if (UNLIKELY(f_new == NULL)) { + /* Invalid boundary region to join faces */ + goto error; + } + + /* copy over loop data */ + l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); + do { + BMLoop *l2 = l_iter->radial_next; + + do { + if (BM_ELEM_API_FLAG_TEST(l2->f, _FLAG_JF)) { + break; + } + l2 = l2->radial_next; + } while (l2 != l_iter); + + if (l2 != l_iter) { + /* loops share an edge, shared vert depends on winding */ + if (l2->v != l_iter->v) { + l2 = l2->next; + } + BLI_assert(l_iter->v == l2->v); + + BM_elem_attrs_copy(bm, bm, l2, l_iter); + } + } while ((l_iter = l_iter->next) != l_first); #ifdef USE_BMESH_HOLES - /* add holes */ - BLI_movelisttolist(&f_new->loops, &holes); - - /* update loop face pointer */ - for (lst = f_new->loops.first; lst; lst = lst->next) { - l_iter = l_first = lst->first; - do { - l_iter->f = f_new; - } while ((l_iter = l_iter->next) != l_first); - } + /* add holes */ + BLI_movelisttolist(&f_new->loops, &holes); + + /* update loop face pointer */ + for (lst = f_new->loops.first; lst; lst = lst->next) { + l_iter = l_first = lst->first; + do { + l_iter->f = f_new; + } while ((l_iter = l_iter->next) != l_first); + } #endif - bm_elements_systag_disable(faces, totface, _FLAG_JF); - BM_ELEM_API_FLAG_DISABLE(f_new, _FLAG_JF); - - /* handle multi-res data */ - if (cd_loop_mdisp_offset != -1) { - float f_center[3]; - float (*faces_center)[3] = BLI_array_alloca(faces_center, totface); - - BM_face_calc_center_median(f_new, f_center); - for (i = 0; i < totface; i++) { - BM_face_calc_center_median(faces[i], faces_center[i]); - } - - l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); - do { - for (i = 0; i < totface; i++) { - BM_loop_interp_multires_ex(bm, l_iter, faces[i], f_center, faces_center[i], cd_loop_mdisp_offset); - } - } while ((l_iter = l_iter->next) != l_first); - } - - /* delete old geometry */ - if (do_del) { - for (i = 0; i < BLI_array_len(deledges); i++) { - BM_edge_kill(bm, deledges[i]); - } - - for (i = 0; i < BLI_array_len(delverts); i++) { - BM_vert_kill(bm, delverts[i]); - } - } - else { - /* otherwise we get both old and new faces */ - for (i = 0; i < totface; i++) { - BM_face_kill(bm, faces[i]); - } - } - - BLI_array_free(edges); - BLI_array_free(deledges); - BLI_array_free(delverts); - - BM_CHECK_ELEMENT(f_new); - return f_new; + bm_elements_systag_disable(faces, totface, _FLAG_JF); + BM_ELEM_API_FLAG_DISABLE(f_new, _FLAG_JF); + + /* handle multi-res data */ + if (cd_loop_mdisp_offset != -1) { + float f_center[3]; + float(*faces_center)[3] = BLI_array_alloca(faces_center, totface); + + BM_face_calc_center_median(f_new, f_center); + for (i = 0; i < totface; i++) { + BM_face_calc_center_median(faces[i], faces_center[i]); + } + + l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); + do { + for (i = 0; i < totface; i++) { + BM_loop_interp_multires_ex( + bm, l_iter, faces[i], f_center, faces_center[i], cd_loop_mdisp_offset); + } + } while ((l_iter = l_iter->next) != l_first); + } + + /* delete old geometry */ + if (do_del) { + for (i = 0; i < BLI_array_len(deledges); i++) { + BM_edge_kill(bm, deledges[i]); + } + + for (i = 0; i < BLI_array_len(delverts); i++) { + BM_vert_kill(bm, delverts[i]); + } + } + else { + /* otherwise we get both old and new faces */ + for (i = 0; i < totface; i++) { + BM_face_kill(bm, faces[i]); + } + } + + BLI_array_free(edges); + BLI_array_free(deledges); + BLI_array_free(delverts); + + BM_CHECK_ELEMENT(f_new); + return f_new; error: - bm_elements_systag_disable(faces, totface, _FLAG_JF); - BLI_array_free(edges); - BLI_array_free(deledges); - BLI_array_free(delverts); + bm_elements_systag_disable(faces, totface, _FLAG_JF); + BLI_array_free(edges); + BLI_array_free(deledges); + BLI_array_free(delverts); - return NULL; + return NULL; } static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example) { - BMFace *f; + BMFace *f; #ifdef USE_BMESH_HOLES - BMLoopList *lst; + BMLoopList *lst; #endif - f = bm_face_create__internal(bm); + f = bm_face_create__internal(bm); #ifdef USE_BMESH_HOLES - lst = BLI_mempool_calloc(bm->looplistpool); - BLI_addtail(&f->loops, lst); + lst = BLI_mempool_calloc(bm->looplistpool); + BLI_addtail(&f->loops, lst); #endif #ifdef USE_BMESH_HOLES - f->totbounds = 1; + f->totbounds = 1; #endif - BM_elem_attrs_copy(bm, bm, f_example, f); + BM_elem_attrs_copy(bm, bm, f_example, f); - return f; + return f; } /** @@ -1447,141 +1449,143 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example) * * \return A BMFace pointer */ -BMFace *bmesh_kernel_split_face_make_edge( - BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2, - BMLoop **r_l, +BMFace *bmesh_kernel_split_face_make_edge(BMesh *bm, + BMFace *f, + BMLoop *l_v1, + BMLoop *l_v2, + BMLoop **r_l, #ifdef USE_BMESH_HOLES - ListBase *holes, + ListBase *holes, #endif - BMEdge *e_example, - const bool no_double) + BMEdge *e_example, + const bool no_double) { #ifdef USE_BMESH_HOLES - BMLoopList *lst, *lst2; + BMLoopList *lst, *lst2; #else - int first_loop_f1; + int first_loop_f1; #endif - BMFace *f2; - BMLoop *l_iter, *l_first; - BMLoop *l_f1 = NULL, *l_f2 = NULL; - BMEdge *e; - BMVert *v1 = l_v1->v, *v2 = l_v2->v; - int f1len, f2len; + BMFace *f2; + BMLoop *l_iter, *l_first; + BMLoop *l_f1 = NULL, *l_f2 = NULL; + BMEdge *e; + BMVert *v1 = l_v1->v, *v2 = l_v2->v; + int f1len, f2len; - BLI_assert(f == l_v1->f && f == l_v2->f); + BLI_assert(f == l_v1->f && f == l_v2->f); - /* allocate new edge between v1 and v2 */ - e = BM_edge_create(bm, v1, v2, e_example, no_double ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP); + /* allocate new edge between v1 and v2 */ + e = BM_edge_create(bm, v1, v2, e_example, no_double ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP); - f2 = bm_face_create__sfme(bm, f); - l_f1 = bm_loop_create(bm, v2, e, f, l_v2, 0); - l_f2 = bm_loop_create(bm, v1, e, f2, l_v1, 0); + f2 = bm_face_create__sfme(bm, f); + l_f1 = bm_loop_create(bm, v2, e, f, l_v2, 0); + l_f2 = bm_loop_create(bm, v1, e, f2, l_v1, 0); - l_f1->prev = l_v2->prev; - l_f2->prev = l_v1->prev; - l_v2->prev->next = l_f1; - l_v1->prev->next = l_f2; + l_f1->prev = l_v2->prev; + l_f2->prev = l_v1->prev; + l_v2->prev->next = l_f1; + l_v1->prev->next = l_f2; - l_f1->next = l_v1; - l_f2->next = l_v2; - l_v1->prev = l_f1; - l_v2->prev = l_f2; + l_f1->next = l_v1; + l_f2->next = l_v2; + l_v1->prev = l_f1; + l_v2->prev = l_f2; #ifdef USE_BMESH_HOLES - lst = f->loops.first; - lst2 = f2->loops.first; + lst = f->loops.first; + lst2 = f2->loops.first; - lst2->first = lst2->last = l_f2; - lst->first = lst->last = l_f1; + lst2->first = lst2->last = l_f2; + lst->first = lst->last = l_f1; #else - /* find which of the faces the original first loop is in */ - l_iter = l_first = l_f1; - 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 == l_f1) { - f2->l_first = l_f2->prev; - } - else if (f->l_first->next == l_f1) { - f2->l_first = l_f2->next; - } - else { - f2->l_first = l_f2; - } - } - else { - /* original first loop was in f2, further do same as above */ - f2->l_first = f->l_first; - - if (f->l_first->prev == l_f2) { - f->l_first = l_f1->prev; - } - else if (f->l_first->next == l_f2) { - f->l_first = l_f1->next; - } - else { - f->l_first = l_f1; - } - } + /* find which of the faces the original first loop is in */ + l_iter = l_first = l_f1; + 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 == l_f1) { + f2->l_first = l_f2->prev; + } + else if (f->l_first->next == l_f1) { + f2->l_first = l_f2->next; + } + else { + f2->l_first = l_f2; + } + } + else { + /* original first loop was in f2, further do same as above */ + f2->l_first = f->l_first; + + if (f->l_first->prev == l_f2) { + f->l_first = l_f1->prev; + } + else if (f->l_first->next == l_f2) { + f->l_first = l_f1->next; + } + else { + f->l_first = l_f1; + } + } #endif - /* validate both loop */ - /* I don't know how many loops are supposed to be in each face at this point! FIXME */ + /* 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); + /* 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_loop_append(e, l_f1); - bmesh_radial_loop_append(e, l_f2); + /* link up the new loops into the new edges radial */ + bmesh_radial_loop_append(e, l_f1); + bmesh_radial_loop_append(e, l_f2); - f2->len = f2len; + f2->len = f2len; - f1len = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - f1len++; - } while ((l_iter = l_iter->next) != l_first); + f1len = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + f1len++; + } while ((l_iter = l_iter->next) != l_first); - f->len = f1len; + f->len = f1len; - if (r_l) { - *r_l = l_f2; - } + if (r_l) { + *r_l = l_f2; + } #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); - } - } + 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); + BM_CHECK_ELEMENT(e); + BM_CHECK_ELEMENT(f); + BM_CHECK_ELEMENT(f2); - return f2; + return f2; } /** @@ -1604,156 +1608,155 @@ BMFace *bmesh_kernel_split_face_make_edge( */ BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) { - BMLoop *l_next; - BMEdge *e_new; - BMVert *v_new, *v_old; + BMLoop *l_next; + BMEdge *e_new; + BMVert *v_new, *v_old; #ifndef NDEBUG - int valence1, valence2; - bool edok; - int i; + int valence1, valence2; + bool edok; + int i; #endif - BLI_assert(BM_vert_in_edge(e, tv) != false); + BLI_assert(BM_vert_in_edge(e, tv) != false); - v_old = BM_edge_other_vert(e, tv); + v_old = BM_edge_other_vert(e, tv); #ifndef NDEBUG - valence1 = bmesh_disk_count(v_old); - valence2 = bmesh_disk_count(tv); + valence1 = bmesh_disk_count(v_old); + valence2 = bmesh_disk_count(tv); #endif - /* order of 'e_new' verts should match 'e' - * (so extruded faces don't flip) */ - v_new = BM_vert_create(bm, tv->co, tv, BM_CREATE_NOP); - e_new = BM_edge_create(bm, tv, v_new, e, BM_CREATE_NOP); + /* order of 'e_new' verts should match 'e' + * (so extruded faces don't flip) */ + v_new = BM_vert_create(bm, tv->co, tv, BM_CREATE_NOP); + e_new = BM_edge_create(bm, tv, v_new, e, BM_CREATE_NOP); - bmesh_disk_edge_remove(e_new, tv); - bmesh_disk_edge_remove(e_new, v_new); + bmesh_disk_edge_remove(e_new, tv); + bmesh_disk_edge_remove(e_new, v_new); - bmesh_disk_vert_replace(e, v_new, tv); + bmesh_disk_vert_replace(e, v_new, tv); - /* add e_new to v_new's disk cycle */ - bmesh_disk_edge_append(e_new, v_new); + /* add e_new to v_new's disk cycle */ + bmesh_disk_edge_append(e_new, v_new); - /* add e_new to tv's disk cycle */ - bmesh_disk_edge_append(e_new, tv); + /* add e_new to tv's disk cycle */ + bmesh_disk_edge_append(e_new, tv); #ifndef NDEBUG - /* verify disk cycles */ - edok = bmesh_disk_validate(valence1, v_old->e, v_old); - BMESH_ASSERT(edok != false); - edok = bmesh_disk_validate(valence2, tv->e, tv); - BMESH_ASSERT(edok != false); - edok = bmesh_disk_validate(2, v_new->e, v_new); - BMESH_ASSERT(edok != false); + /* verify disk cycles */ + edok = bmesh_disk_validate(valence1, v_old->e, v_old); + BMESH_ASSERT(edok != false); + edok = bmesh_disk_validate(valence2, tv->e, tv); + BMESH_ASSERT(edok != false); + edok = bmesh_disk_validate(2, v_new->e, v_new); + BMESH_ASSERT(edok != false); #endif - /* Split the radial cycle if present */ - l_next = e->l; - e->l = NULL; - if (l_next) { - BMLoop *l_new, *l; + /* Split the radial cycle if present */ + l_next = e->l; + e->l = NULL; + if (l_next) { + BMLoop *l_new, *l; #ifndef NDEBUG - int radlen = bmesh_radial_length(l_next); + int radlen = bmesh_radial_length(l_next); #endif - bool is_first = true; - - /* Take the next loop. Remove it from radial. Split it. Append to appropriate radials */ - while (l_next) { - l = l_next; - l->f->len++; - l_next = l_next != l_next->radial_next ? l_next->radial_next : NULL; - bmesh_radial_loop_unlink(l); - - l_new = bm_loop_create(bm, NULL, NULL, l->f, l, 0); - l_new->prev = l; - l_new->next = l->next; - l_new->prev->next = l_new; - l_new->next->prev = l_new; - l_new->v = v_new; - - /* assign the correct edge to the correct loop */ - if (BM_verts_in_edge(l_new->v, l_new->next->v, e)) { - l_new->e = e; - l->e = e_new; - - /* append l into e_new's rad cycle */ - if (is_first) { - is_first = false; - l->radial_next = l->radial_prev = NULL; - } - - bmesh_radial_loop_append(l_new->e, l_new); - bmesh_radial_loop_append(l->e, l); - } - else if (BM_verts_in_edge(l_new->v, l_new->next->v, e_new)) { - l_new->e = e_new; - l->e = e; - - /* append l into e_new's rad cycle */ - if (is_first) { - is_first = false; - l->radial_next = l->radial_prev = NULL; - } - - bmesh_radial_loop_append(l_new->e, l_new); - bmesh_radial_loop_append(l->e, l); - } - - } + bool is_first = true; + + /* Take the next loop. Remove it from radial. Split it. Append to appropriate radials */ + while (l_next) { + l = l_next; + l->f->len++; + l_next = l_next != l_next->radial_next ? l_next->radial_next : NULL; + bmesh_radial_loop_unlink(l); + + l_new = bm_loop_create(bm, NULL, NULL, l->f, l, 0); + l_new->prev = l; + l_new->next = l->next; + l_new->prev->next = l_new; + l_new->next->prev = l_new; + l_new->v = v_new; + + /* assign the correct edge to the correct loop */ + if (BM_verts_in_edge(l_new->v, l_new->next->v, e)) { + l_new->e = e; + l->e = e_new; + + /* append l into e_new's rad cycle */ + if (is_first) { + is_first = false; + l->radial_next = l->radial_prev = NULL; + } + + bmesh_radial_loop_append(l_new->e, l_new); + bmesh_radial_loop_append(l->e, l); + } + else if (BM_verts_in_edge(l_new->v, l_new->next->v, e_new)) { + l_new->e = e_new; + l->e = e; + + /* append l into e_new's rad cycle */ + if (is_first) { + is_first = false; + l->radial_next = l->radial_prev = NULL; + } + + bmesh_radial_loop_append(l_new->e, l_new); + bmesh_radial_loop_append(l->e, l); + } + } #ifndef NDEBUG - /* verify length of radial cycle */ - edok = bmesh_radial_validate(radlen, e->l); - BMESH_ASSERT(edok != false); - edok = bmesh_radial_validate(radlen, e_new->l); - BMESH_ASSERT(edok != false); - - /* verify loop->v and loop->next->v pointers for e */ - for (i = 0, l = e->l; i < radlen; i++, l = l->radial_next) { - BMESH_ASSERT(l->e == e); - //BMESH_ASSERT(l->radial_next == l); - BMESH_ASSERT(!(l->prev->e != e_new && l->next->e != e_new)); - - edok = BM_verts_in_edge(l->v, l->next->v, e); - BMESH_ASSERT(edok != false); - BMESH_ASSERT(l->v != l->next->v); - BMESH_ASSERT(l->e != l->next->e); - - /* verify loop cycle for kloop->f */ - BM_CHECK_ELEMENT(l); - BM_CHECK_ELEMENT(l->v); - BM_CHECK_ELEMENT(l->e); - BM_CHECK_ELEMENT(l->f); - } - /* verify loop->v and loop->next->v pointers for e_new */ - for (i = 0, l = e_new->l; i < radlen; i++, l = l->radial_next) { - BMESH_ASSERT(l->e == e_new); - // BMESH_ASSERT(l->radial_next == l); - BMESH_ASSERT(!(l->prev->e != e && l->next->e != e)); - edok = BM_verts_in_edge(l->v, l->next->v, e_new); - BMESH_ASSERT(edok != false); - BMESH_ASSERT(l->v != l->next->v); - BMESH_ASSERT(l->e != l->next->e); - - BM_CHECK_ELEMENT(l); - BM_CHECK_ELEMENT(l->v); - BM_CHECK_ELEMENT(l->e); - BM_CHECK_ELEMENT(l->f); - } + /* verify length of radial cycle */ + edok = bmesh_radial_validate(radlen, e->l); + BMESH_ASSERT(edok != false); + edok = bmesh_radial_validate(radlen, e_new->l); + BMESH_ASSERT(edok != false); + + /* verify loop->v and loop->next->v pointers for e */ + for (i = 0, l = e->l; i < radlen; i++, l = l->radial_next) { + BMESH_ASSERT(l->e == e); + //BMESH_ASSERT(l->radial_next == l); + BMESH_ASSERT(!(l->prev->e != e_new && l->next->e != e_new)); + + edok = BM_verts_in_edge(l->v, l->next->v, e); + BMESH_ASSERT(edok != false); + BMESH_ASSERT(l->v != l->next->v); + BMESH_ASSERT(l->e != l->next->e); + + /* verify loop cycle for kloop->f */ + BM_CHECK_ELEMENT(l); + BM_CHECK_ELEMENT(l->v); + BM_CHECK_ELEMENT(l->e); + BM_CHECK_ELEMENT(l->f); + } + /* verify loop->v and loop->next->v pointers for e_new */ + for (i = 0, l = e_new->l; i < radlen; i++, l = l->radial_next) { + BMESH_ASSERT(l->e == e_new); + // BMESH_ASSERT(l->radial_next == l); + BMESH_ASSERT(!(l->prev->e != e && l->next->e != e)); + edok = BM_verts_in_edge(l->v, l->next->v, e_new); + BMESH_ASSERT(edok != false); + BMESH_ASSERT(l->v != l->next->v); + BMESH_ASSERT(l->e != l->next->e); + + BM_CHECK_ELEMENT(l); + BM_CHECK_ELEMENT(l->v); + BM_CHECK_ELEMENT(l->e); + BM_CHECK_ELEMENT(l->f); + } #endif - } - - BM_CHECK_ELEMENT(e_new); - BM_CHECK_ELEMENT(v_new); - BM_CHECK_ELEMENT(v_old); - BM_CHECK_ELEMENT(e); - BM_CHECK_ELEMENT(tv); - - if (r_e) { - *r_e = e_new; - } - return v_new; + } + + BM_CHECK_ELEMENT(e_new); + BM_CHECK_ELEMENT(v_new); + BM_CHECK_ELEMENT(v_old); + BM_CHECK_ELEMENT(e); + BM_CHECK_ELEMENT(tv); + + if (r_e) { + *r_e = e_new; + } + return v_new; } /** @@ -1786,153 +1789,154 @@ BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEd * faces with just 2 edges. It is up to the caller to decide what to do with * these faces. */ -BMEdge *bmesh_kernel_join_edge_kill_vert( - BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool check_edge_double, - const bool kill_degenerate_faces) +BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm, + BMEdge *e_kill, + BMVert *v_kill, + const bool do_del, + const bool check_edge_double, + const bool kill_degenerate_faces) { - BMEdge *e_old; - BMVert *v_old, *v_target; - BMLoop *l_kill; + BMEdge *e_old; + BMVert *v_old, *v_target; + BMLoop *l_kill; #ifndef NDEBUG - int radlen, i; - bool edok; + int radlen, i; + bool edok; #endif - BLI_assert(BM_vert_in_edge(e_kill, v_kill)); + BLI_assert(BM_vert_in_edge(e_kill, v_kill)); - if (BM_vert_in_edge(e_kill, v_kill) == 0) { - return NULL; - } + if (BM_vert_in_edge(e_kill, v_kill) == 0) { + return NULL; + } - if (bmesh_disk_count_at_most(v_kill, 3) == 2) { + if (bmesh_disk_count_at_most(v_kill, 3) == 2) { #ifndef NDEBUG - int valence1, valence2; - BMLoop *l; + int valence1, valence2; + BMLoop *l; #endif - e_old = bmesh_disk_edge_next(e_kill, v_kill); - v_target = BM_edge_other_vert(e_kill, v_kill); - v_old = BM_edge_other_vert(e_old, v_kill); + e_old = bmesh_disk_edge_next(e_kill, v_kill); + v_target = BM_edge_other_vert(e_kill, v_kill); + v_old = BM_edge_other_vert(e_old, v_kill); - /* check for double edges */ - if (BM_verts_in_edge(v_kill, v_target, e_old)) { - return NULL; - } - else { - BMEdge *e_splice; - BLI_SMALLSTACK_DECLARE(faces_degenerate, BMFace *); - BMLoop *l_kill_next; + /* check for double edges */ + if (BM_verts_in_edge(v_kill, v_target, e_old)) { + return NULL; + } + else { + BMEdge *e_splice; + BLI_SMALLSTACK_DECLARE(faces_degenerate, BMFace *); + BMLoop *l_kill_next; #ifndef NDEBUG - /* For verification later, count valence of 'v_old' and 'v_target' */ - valence1 = bmesh_disk_count(v_old); - valence2 = bmesh_disk_count(v_target); + /* For verification later, count valence of 'v_old' and 'v_target' */ + valence1 = bmesh_disk_count(v_old); + valence2 = bmesh_disk_count(v_target); #endif - if (check_edge_double) { - e_splice = BM_edge_exists(v_target, v_old); - } + if (check_edge_double) { + e_splice = BM_edge_exists(v_target, v_old); + } - bmesh_disk_vert_replace(e_old, v_target, v_kill); + bmesh_disk_vert_replace(e_old, v_target, v_kill); - /* remove e_kill from 'v_target's disk cycle */ - bmesh_disk_edge_remove(e_kill, v_target); + /* remove e_kill from 'v_target's disk cycle */ + bmesh_disk_edge_remove(e_kill, v_target); #ifndef NDEBUG - /* deal with radial cycle of e_kill */ - radlen = bmesh_radial_length(e_kill->l); + /* deal with radial cycle of e_kill */ + radlen = bmesh_radial_length(e_kill->l); #endif - if (e_kill->l) { - - - /* fix the neighboring loops of all loops in e_kill's radial cycle */ - l_kill = e_kill->l; - do { - /* relink loops and fix vertex pointer */ - if (l_kill->next->v == v_kill) { - l_kill->next->v = v_target; - } - - l_kill->next->prev = l_kill->prev; - l_kill->prev->next = l_kill->next; - if (BM_FACE_FIRST_LOOP(l_kill->f) == l_kill) { - BM_FACE_FIRST_LOOP(l_kill->f) = l_kill->next; - } - - /* fix len attribute of face */ - l_kill->f->len--; - if (kill_degenerate_faces) { - if (l_kill->f->len < 3) { - BLI_SMALLSTACK_PUSH(faces_degenerate, l_kill->f); - } - } - l_kill_next = l_kill->radial_next; - - bm_kill_only_loop(bm, l_kill); - - } while ((l_kill = l_kill_next) != e_kill->l); - /* `e_kill->l` is invalid but the edge is freed next. */ + if (e_kill->l) { + + /* fix the neighboring loops of all loops in e_kill's radial cycle */ + l_kill = e_kill->l; + do { + /* relink loops and fix vertex pointer */ + if (l_kill->next->v == v_kill) { + l_kill->next->v = v_target; + } + + l_kill->next->prev = l_kill->prev; + l_kill->prev->next = l_kill->next; + if (BM_FACE_FIRST_LOOP(l_kill->f) == l_kill) { + BM_FACE_FIRST_LOOP(l_kill->f) = l_kill->next; + } + + /* fix len attribute of face */ + l_kill->f->len--; + if (kill_degenerate_faces) { + if (l_kill->f->len < 3) { + BLI_SMALLSTACK_PUSH(faces_degenerate, l_kill->f); + } + } + l_kill_next = l_kill->radial_next; + + bm_kill_only_loop(bm, l_kill); + + } while ((l_kill = l_kill_next) != e_kill->l); + /* `e_kill->l` is invalid but the edge is freed next. */ #ifndef NDEBUG - /* Validate radial cycle of e_old */ - edok = bmesh_radial_validate(radlen, e_old->l); - BMESH_ASSERT(edok != false); + /* Validate radial cycle of e_old */ + edok = bmesh_radial_validate(radlen, e_old->l); + BMESH_ASSERT(edok != false); #endif - } - /* deallocate edge */ - bm_kill_only_edge(bm, e_kill); - - /* deallocate vertex */ - if (do_del) { - bm_kill_only_vert(bm, v_kill); - } - else { - v_kill->e = NULL; - } + } + /* deallocate edge */ + bm_kill_only_edge(bm, e_kill); + + /* deallocate vertex */ + if (do_del) { + bm_kill_only_vert(bm, v_kill); + } + else { + v_kill->e = NULL; + } #ifndef NDEBUG - /* Validate disk cycle lengths of 'v_old', 'v_target' are unchanged */ - edok = bmesh_disk_validate(valence1, v_old->e, v_old); - BMESH_ASSERT(edok != false); - edok = bmesh_disk_validate(valence2, v_target->e, v_target); - BMESH_ASSERT(edok != false); - - /* Validate loop cycle of all faces attached to 'e_old' */ - for (i = 0, l = e_old->l; i < radlen; i++, l = l->radial_next) { - BMESH_ASSERT(l->e == e_old); - edok = BM_verts_in_edge(l->v, l->next->v, e_old); - BMESH_ASSERT(edok != false); - edok = bmesh_loop_validate(l->f); - BMESH_ASSERT(edok != false); - - BM_CHECK_ELEMENT(l); - BM_CHECK_ELEMENT(l->v); - BM_CHECK_ELEMENT(l->e); - BM_CHECK_ELEMENT(l->f); - } + /* Validate disk cycle lengths of 'v_old', 'v_target' are unchanged */ + edok = bmesh_disk_validate(valence1, v_old->e, v_old); + BMESH_ASSERT(edok != false); + edok = bmesh_disk_validate(valence2, v_target->e, v_target); + BMESH_ASSERT(edok != false); + + /* Validate loop cycle of all faces attached to 'e_old' */ + for (i = 0, l = e_old->l; i < radlen; i++, l = l->radial_next) { + BMESH_ASSERT(l->e == e_old); + edok = BM_verts_in_edge(l->v, l->next->v, e_old); + BMESH_ASSERT(edok != false); + edok = bmesh_loop_validate(l->f); + BMESH_ASSERT(edok != false); + + BM_CHECK_ELEMENT(l); + BM_CHECK_ELEMENT(l->v); + BM_CHECK_ELEMENT(l->e); + BM_CHECK_ELEMENT(l->f); + } #endif - if (check_edge_double) { - if (e_splice) { - /* removes e_splice */ - BM_edge_splice(bm, e_old, e_splice); - } - } - - if (kill_degenerate_faces) { - BMFace *f_kill; - while ((f_kill = BLI_SMALLSTACK_POP(faces_degenerate))) { - BM_face_kill(bm, f_kill); - } - } - - BM_CHECK_ELEMENT(v_old); - BM_CHECK_ELEMENT(v_target); - BM_CHECK_ELEMENT(e_old); - - return e_old; - } - } - return NULL; + if (check_edge_double) { + if (e_splice) { + /* removes e_splice */ + BM_edge_splice(bm, e_old, e_splice); + } + } + + if (kill_degenerate_faces) { + BMFace *f_kill; + while ((f_kill = BLI_SMALLSTACK_POP(faces_degenerate))) { + BM_face_kill(bm, f_kill); + } + } + + BM_CHECK_ELEMENT(v_old); + BM_CHECK_ELEMENT(v_target); + BM_CHECK_ELEMENT(e_old); + + return e_old; + } + } + return NULL; } /** @@ -1952,85 +1956,87 @@ BMEdge *bmesh_kernel_join_edge_kill_vert( * +-+-+-+ +-+-+-+ * </pre> */ -BMVert *bmesh_kernel_join_vert_kill_edge( - BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool check_edge_double, - const bool kill_degenerate_faces) +BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm, + BMEdge *e_kill, + BMVert *v_kill, + const bool do_del, + const bool check_edge_double, + const bool kill_degenerate_faces) { - BLI_SMALLSTACK_DECLARE(faces_degenerate, BMFace *); - BMVert *v_target = BM_edge_other_vert(e_kill, v_kill); - - BLI_assert(BM_vert_in_edge(e_kill, v_kill)); - - if (e_kill->l) { - BMLoop *l_kill, *l_first, *l_kill_next; - l_kill = l_first = e_kill->l; - do { - /* relink loops and fix vertex pointer */ - if (l_kill->next->v == v_kill) { - l_kill->next->v = v_target; - } - - l_kill->next->prev = l_kill->prev; - l_kill->prev->next = l_kill->next; - if (BM_FACE_FIRST_LOOP(l_kill->f) == l_kill) { - BM_FACE_FIRST_LOOP(l_kill->f) = l_kill->next; - } - - /* fix len attribute of face */ - l_kill->f->len--; - if (kill_degenerate_faces) { - if (l_kill->f->len < 3) { - BLI_SMALLSTACK_PUSH(faces_degenerate, l_kill->f); - } - } - l_kill_next = l_kill->radial_next; - - bm_kill_only_loop(bm, l_kill); - - } while ((l_kill = l_kill_next) != l_first); - - e_kill->l = NULL; - } - - BM_edge_kill(bm, e_kill); - BM_CHECK_ELEMENT(v_kill); - BM_CHECK_ELEMENT(v_target); - - if (v_target->e && v_kill->e) { - /* inline BM_vert_splice(bm, v_target, v_kill); */ - BMEdge *e; - while ((e = v_kill->e)) { - BMEdge *e_target; - - if (check_edge_double) { - e_target = BM_edge_exists(v_target, BM_edge_other_vert(e, v_kill)); - } - - bmesh_edge_vert_swap(e, v_target, v_kill); - BLI_assert(e->v1 != e->v2); - - if (check_edge_double) { - if (e_target) { - BM_edge_splice(bm, e_target, e); - } - } - } - } - - if (kill_degenerate_faces) { - BMFace *f_kill; - while ((f_kill = BLI_SMALLSTACK_POP(faces_degenerate))) { - BM_face_kill(bm, f_kill); - } - } - - if (do_del) { - BLI_assert(v_kill->e == NULL); - bm_kill_only_vert(bm, v_kill); - } - - return v_target; + BLI_SMALLSTACK_DECLARE(faces_degenerate, BMFace *); + BMVert *v_target = BM_edge_other_vert(e_kill, v_kill); + + BLI_assert(BM_vert_in_edge(e_kill, v_kill)); + + if (e_kill->l) { + BMLoop *l_kill, *l_first, *l_kill_next; + l_kill = l_first = e_kill->l; + do { + /* relink loops and fix vertex pointer */ + if (l_kill->next->v == v_kill) { + l_kill->next->v = v_target; + } + + l_kill->next->prev = l_kill->prev; + l_kill->prev->next = l_kill->next; + if (BM_FACE_FIRST_LOOP(l_kill->f) == l_kill) { + BM_FACE_FIRST_LOOP(l_kill->f) = l_kill->next; + } + + /* fix len attribute of face */ + l_kill->f->len--; + if (kill_degenerate_faces) { + if (l_kill->f->len < 3) { + BLI_SMALLSTACK_PUSH(faces_degenerate, l_kill->f); + } + } + l_kill_next = l_kill->radial_next; + + bm_kill_only_loop(bm, l_kill); + + } while ((l_kill = l_kill_next) != l_first); + + e_kill->l = NULL; + } + + BM_edge_kill(bm, e_kill); + BM_CHECK_ELEMENT(v_kill); + BM_CHECK_ELEMENT(v_target); + + if (v_target->e && v_kill->e) { + /* inline BM_vert_splice(bm, v_target, v_kill); */ + BMEdge *e; + while ((e = v_kill->e)) { + BMEdge *e_target; + + if (check_edge_double) { + e_target = BM_edge_exists(v_target, BM_edge_other_vert(e, v_kill)); + } + + bmesh_edge_vert_swap(e, v_target, v_kill); + BLI_assert(e->v1 != e->v2); + + if (check_edge_double) { + if (e_target) { + BM_edge_splice(bm, e_target, e); + } + } + } + } + + if (kill_degenerate_faces) { + BMFace *f_kill; + while ((f_kill = BLI_SMALLSTACK_POP(faces_degenerate))) { + BM_face_kill(bm, f_kill); + } + } + + if (do_del) { + BLI_assert(v_kill->e == NULL); + bm_kill_only_vert(bm, v_kill); + } + + return v_target; } /** @@ -2066,129 +2072,124 @@ BMVert *bmesh_kernel_join_vert_kill_edge( */ BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) { - BMLoop *l_iter, *l_f1 = NULL, *l_f2 = NULL; - int newlen = 0, i, f1len = 0, f2len = 0; - bool edok; - /* can't join a face to itself */ - if (f1 == f2) { - return NULL; - } - - /* validate that edge is 2-manifold edge */ - if (!BM_edge_is_manifold(e)) { - return NULL; - } - - /* verify that e is in both f1 and f2 */ - f1len = f1->len; - f2len = f2->len; - - if (!((l_f1 = BM_face_edge_share_loop(f1, e)) && - (l_f2 = BM_face_edge_share_loop(f2, e)))) - { - return NULL; - } - - /* validate direction of f2's loop cycle is compatible */ - if (l_f1->v == l_f2->v) { - return NULL; - } - - /* validate that for each face, each vertex has another edge in its disk cycle that is - * not e, and not shared. */ - if (BM_edge_in_face(l_f1->next->e, f2) || - BM_edge_in_face(l_f1->prev->e, f2) || - BM_edge_in_face(l_f2->next->e, f1) || - BM_edge_in_face(l_f2->prev->e, f1) ) - { - return NULL; - } - - /* validate only one shared edge */ - if (BM_face_share_edge_count(f1, f2) > 1) { - return NULL; - } - - /* validate no internal join */ - { - bool is_dupe = false; - - /* TODO: skip clearing once this is ensured. */ - for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) { - BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG); - } - - for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) { - BM_elem_flag_set(l_iter->v, BM_ELEM_INTERNAL_TAG, l_iter != l_f1); - } - for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) { - if (l_iter != l_f2) { - /* as soon as a duplicate is found, bail out */ - if (BM_elem_flag_test(l_iter->v, BM_ELEM_INTERNAL_TAG)) { - is_dupe = true; - break; - } - } - } - /* Cleanup tags. */ - for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) { - BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG); - } - if (is_dupe) { - return NULL; - } - } - - /* join the two loop */ - l_f1->prev->next = l_f2->next; - l_f2->next->prev = l_f1->prev; - - l_f1->next->prev = l_f2->prev; - l_f2->prev->next = l_f1->next; - - /* if l_f1 was baseloop, make l_f1->next the base. */ - if (BM_FACE_FIRST_LOOP(f1) == l_f1) { - BM_FACE_FIRST_LOOP(f1) = l_f1->next; - } - - /* increase length of f1 */ - f1->len += (f2->len - 2); - - /* make sure each loop points to the proper face */ - newlen = f1->len; - for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < newlen; i++, l_iter = l_iter->next) { - l_iter->f = f1; - } - - /* remove edge from the disk cycle of its two vertices */ - bmesh_disk_edge_remove(l_f1->e, l_f1->e->v1); - bmesh_disk_edge_remove(l_f1->e, l_f1->e->v2); - - /* deallocate edge and its two loops as well as f2 */ - if (bm->etoolflagpool) { - BLI_mempool_free(bm->etoolflagpool, ((BMEdge_OFlag *)l_f1->e)->oflags); - } - BLI_mempool_free(bm->epool, l_f1->e); - bm->totedge--; - BLI_mempool_free(bm->lpool, l_f1); - bm->totloop--; - BLI_mempool_free(bm->lpool, l_f2); - bm->totloop--; - if (bm->ftoolflagpool) { - BLI_mempool_free(bm->ftoolflagpool, ((BMFace_OFlag *)f2)->oflags); - } - BLI_mempool_free(bm->fpool, f2); - bm->totface--; - /* account for both above */ - bm->elem_index_dirty |= BM_EDGE | BM_LOOP | BM_FACE; - - BM_CHECK_ELEMENT(f1); - - /* validate the new loop cycle */ - edok = bmesh_loop_validate(f1); - BMESH_ASSERT(edok != false); - - return f1; + BMLoop *l_iter, *l_f1 = NULL, *l_f2 = NULL; + int newlen = 0, i, f1len = 0, f2len = 0; + bool edok; + /* can't join a face to itself */ + if (f1 == f2) { + return NULL; + } + + /* validate that edge is 2-manifold edge */ + if (!BM_edge_is_manifold(e)) { + return NULL; + } + + /* verify that e is in both f1 and f2 */ + f1len = f1->len; + f2len = f2->len; + + if (!((l_f1 = BM_face_edge_share_loop(f1, e)) && (l_f2 = BM_face_edge_share_loop(f2, e)))) { + return NULL; + } + + /* validate direction of f2's loop cycle is compatible */ + if (l_f1->v == l_f2->v) { + return NULL; + } + + /* validate that for each face, each vertex has another edge in its disk cycle that is + * not e, and not shared. */ + if (BM_edge_in_face(l_f1->next->e, f2) || BM_edge_in_face(l_f1->prev->e, f2) || + BM_edge_in_face(l_f2->next->e, f1) || BM_edge_in_face(l_f2->prev->e, f1)) { + return NULL; + } + + /* validate only one shared edge */ + if (BM_face_share_edge_count(f1, f2) > 1) { + return NULL; + } + + /* validate no internal join */ + { + bool is_dupe = false; + + /* TODO: skip clearing once this is ensured. */ + for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) { + BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG); + } + + for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) { + BM_elem_flag_set(l_iter->v, BM_ELEM_INTERNAL_TAG, l_iter != l_f1); + } + for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) { + if (l_iter != l_f2) { + /* as soon as a duplicate is found, bail out */ + if (BM_elem_flag_test(l_iter->v, BM_ELEM_INTERNAL_TAG)) { + is_dupe = true; + break; + } + } + } + /* Cleanup tags. */ + for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) { + BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG); + } + if (is_dupe) { + return NULL; + } + } + + /* join the two loop */ + l_f1->prev->next = l_f2->next; + l_f2->next->prev = l_f1->prev; + + l_f1->next->prev = l_f2->prev; + l_f2->prev->next = l_f1->next; + + /* if l_f1 was baseloop, make l_f1->next the base. */ + if (BM_FACE_FIRST_LOOP(f1) == l_f1) { + BM_FACE_FIRST_LOOP(f1) = l_f1->next; + } + + /* increase length of f1 */ + f1->len += (f2->len - 2); + + /* make sure each loop points to the proper face */ + newlen = f1->len; + for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < newlen; i++, l_iter = l_iter->next) { + l_iter->f = f1; + } + + /* remove edge from the disk cycle of its two vertices */ + bmesh_disk_edge_remove(l_f1->e, l_f1->e->v1); + bmesh_disk_edge_remove(l_f1->e, l_f1->e->v2); + + /* deallocate edge and its two loops as well as f2 */ + if (bm->etoolflagpool) { + BLI_mempool_free(bm->etoolflagpool, ((BMEdge_OFlag *)l_f1->e)->oflags); + } + BLI_mempool_free(bm->epool, l_f1->e); + bm->totedge--; + BLI_mempool_free(bm->lpool, l_f1); + bm->totloop--; + BLI_mempool_free(bm->lpool, l_f2); + bm->totloop--; + if (bm->ftoolflagpool) { + BLI_mempool_free(bm->ftoolflagpool, ((BMFace_OFlag *)f2)->oflags); + } + BLI_mempool_free(bm->fpool, f2); + bm->totface--; + /* account for both above */ + bm->elem_index_dirty |= BM_EDGE | BM_LOOP | BM_FACE; + + BM_CHECK_ELEMENT(f1); + + /* validate the new loop cycle */ + edok = bmesh_loop_validate(f1); + BMESH_ASSERT(edok != false); + + return f1; } /** @@ -2198,46 +2199,45 @@ BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEd */ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b) { - bool is_double = false; + bool is_double = false; - BLI_assert(BM_edge_exists(v_a, v_b) == false); + BLI_assert(BM_edge_exists(v_a, v_b) == false); - if (v_a->e && v_b->e) { - BMEdge *e, *e_first; + if (v_a->e && v_b->e) { + BMEdge *e, *e_first; #define VERT_VISIT _FLAG_WALK - /* tag 'v_a' */ - e = e_first = v_a->e; - do { - BMVert *v_other = BM_edge_other_vert(e, v_a); - BLI_assert(!BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)); - BM_ELEM_API_FLAG_ENABLE(v_other, VERT_VISIT); - } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first); - - /* check 'v_b' connects to 'v_a' edges */ - e = e_first = v_b->e; - do { - BMVert *v_other = BM_edge_other_vert(e, v_b); - if (BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)) { - is_double = true; - break; - } - } while ((e = BM_DISK_EDGE_NEXT(e, v_b)) != e_first); - - /* cleanup */ - e = e_first = v_a->e; - do { - BMVert *v_other = BM_edge_other_vert(e, v_a); - BLI_assert(BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)); - BM_ELEM_API_FLAG_DISABLE(v_other, VERT_VISIT); - } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first); + /* tag 'v_a' */ + e = e_first = v_a->e; + do { + BMVert *v_other = BM_edge_other_vert(e, v_a); + BLI_assert(!BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)); + BM_ELEM_API_FLAG_ENABLE(v_other, VERT_VISIT); + } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first); + + /* check 'v_b' connects to 'v_a' edges */ + e = e_first = v_b->e; + do { + BMVert *v_other = BM_edge_other_vert(e, v_b); + if (BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)) { + is_double = true; + break; + } + } while ((e = BM_DISK_EDGE_NEXT(e, v_b)) != e_first); + + /* cleanup */ + e = e_first = v_a->e; + do { + BMVert *v_other = BM_edge_other_vert(e, v_a); + BLI_assert(BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)); + BM_ELEM_API_FLAG_DISABLE(v_other, VERT_VISIT); + } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first); #undef VERT_VISIT + } - } - - return is_double; + return is_double; } /** @@ -2254,38 +2254,37 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b) */ bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src) { - BMEdge *e; + BMEdge *e; - /* verts already spliced */ - if (v_src == v_dst) { - return false; - } + /* verts already spliced */ + if (v_src == v_dst) { + return false; + } - BLI_assert(BM_vert_pair_share_face_check(v_src, v_dst) == false); + BLI_assert(BM_vert_pair_share_face_check(v_src, v_dst) == false); - /* move all the edges from 'v_src' disk to 'v_dst' */ - while ((e = v_src->e)) { - bmesh_edge_vert_swap(e, v_dst, v_src); - BLI_assert(e->v1 != e->v2); - } + /* move all the edges from 'v_src' disk to 'v_dst' */ + while ((e = v_src->e)) { + bmesh_edge_vert_swap(e, v_dst, v_src); + BLI_assert(e->v1 != e->v2); + } - BM_CHECK_ELEMENT(v_src); - BM_CHECK_ELEMENT(v_dst); + BM_CHECK_ELEMENT(v_src); + BM_CHECK_ELEMENT(v_dst); - /* 'v_src' is unused now, and can be killed */ - BM_vert_kill(bm, v_src); + /* 'v_src' is unused now, and can be killed */ + BM_vert_kill(bm, v_src); - return true; + return true; } - /** \name BM_vert_separate, bmesh_kernel_vert_separate and friends * \{ */ /* BM_edge_face_count(e) >= 1 */ BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e) { - return (e->l && e->l->radial_next != e->l); + return (e->l && e->l->radial_next != e->l); } /** @@ -2300,114 +2299,113 @@ BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e) * \return Success */ void bmesh_kernel_vert_separate( - BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - const bool copy_select) + BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, const bool copy_select) { - int v_edges_num = 0; + int v_edges_num = 0; - /* Detailed notes on array use since this is stack memory, we have to be careful */ + /* Detailed notes on array use since this is stack memory, we have to be careful */ - /* newly created vertices, only use when 'r_vout' is set - * (total size will be number of fans) */ - BLI_SMALLSTACK_DECLARE(verts_new, BMVert *); - /* fill with edges from the face-fan, clearing on completion - * (total size will be max fan edge count) */ - BLI_SMALLSTACK_DECLARE(edges, BMEdge *); - /* temp store edges to walk over when filling 'edges', - * (total size will be max radial edges of any edge) */ - BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *); + /* newly created vertices, only use when 'r_vout' is set + * (total size will be number of fans) */ + BLI_SMALLSTACK_DECLARE(verts_new, BMVert *); + /* fill with edges from the face-fan, clearing on completion + * (total size will be max fan edge count) */ + BLI_SMALLSTACK_DECLARE(edges, BMEdge *); + /* temp store edges to walk over when filling 'edges', + * (total size will be max radial edges of any edge) */ + BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *); - /* number of resulting verts, include self */ - int verts_num = 1; - /* track the total number of edges handled, so we know when we've found the last fan */ - int edges_found = 0; + /* number of resulting verts, include self */ + int verts_num = 1; + /* track the total number of edges handled, so we know when we've found the last fan */ + int edges_found = 0; #define EDGE_VISIT _FLAG_WALK - /* count and flag at once */ - if (v->e) { - BMEdge *e_first, *e_iter; - e_iter = e_first = v->e; - do { - v_edges_num += 1; - - BLI_assert(!BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)); - BM_ELEM_API_FLAG_ENABLE(e_iter, EDGE_VISIT); - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - } - - while (true) { - /* Considering only edges and faces incident on vertex v, walk - * the edges & collect in the 'edges' list for splitting */ - - BMEdge *e = v->e; - BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); - - do { - BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)); - BLI_SMALLSTACK_PUSH(edges, e); - edges_found += 1; - - if (e->l) { - BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next; - BLI_assert(BM_vert_in_edge(l_adjacent->e, v)); - if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) { - BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT); - BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e); - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - } while ((e = BLI_SMALLSTACK_POP(edges_search))); - - /* now we have all edges connected to 'v->e' */ - - BLI_assert(edges_found <= v_edges_num); - - if (edges_found == v_edges_num) { - /* We're done! The remaining edges in 'edges' form the last fan, - * which can be left as is. - * if 'edges' were alloc'd it'd be freed here. */ - break; - } - else { - BMVert *v_new; - - v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); - if (copy_select) { - BM_elem_select_copy(bm, v_new, v); - } - - while ((e = BLI_SMALLSTACK_POP(edges))) { - bmesh_edge_vert_swap(e, v_new, v); - } - - if (r_vout) { - BLI_SMALLSTACK_PUSH(verts_new, v_new); - } - verts_num += 1; - } - } + /* count and flag at once */ + if (v->e) { + BMEdge *e_first, *e_iter; + e_iter = e_first = v->e; + do { + v_edges_num += 1; + + BLI_assert(!BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)); + BM_ELEM_API_FLAG_ENABLE(e_iter, EDGE_VISIT); + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } + + while (true) { + /* Considering only edges and faces incident on vertex v, walk + * the edges & collect in the 'edges' list for splitting */ + + BMEdge *e = v->e; + BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); + + do { + BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)); + BLI_SMALLSTACK_PUSH(edges, e); + edges_found += 1; + + if (e->l) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next; + BLI_assert(BM_vert_in_edge(l_adjacent->e, v)); + if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) { + BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT); + BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e); + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + } while ((e = BLI_SMALLSTACK_POP(edges_search))); + + /* now we have all edges connected to 'v->e' */ + + BLI_assert(edges_found <= v_edges_num); + + if (edges_found == v_edges_num) { + /* We're done! The remaining edges in 'edges' form the last fan, + * which can be left as is. + * if 'edges' were alloc'd it'd be freed here. */ + break; + } + else { + BMVert *v_new; + + v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); + if (copy_select) { + BM_elem_select_copy(bm, v_new, v); + } + + while ((e = BLI_SMALLSTACK_POP(edges))) { + bmesh_edge_vert_swap(e, v_new, v); + } + + if (r_vout) { + BLI_SMALLSTACK_PUSH(verts_new, v_new); + } + verts_num += 1; + } + } #undef EDGE_VISIT - /* flags are clean now, handle return values */ + /* flags are clean now, handle return values */ - if (r_vout_len != NULL) { - *r_vout_len = verts_num; - } + if (r_vout_len != NULL) { + *r_vout_len = verts_num; + } - if (r_vout != NULL) { - BMVert **verts; + if (r_vout != NULL) { + BMVert **verts; - verts = MEM_mallocN(sizeof(BMVert *) * verts_num, __func__); - *r_vout = verts; + verts = MEM_mallocN(sizeof(BMVert *) * verts_num, __func__); + *r_vout = verts; - verts[0] = v; - BLI_SMALLSTACK_AS_TABLE(verts_new, &verts[1]); - } + verts[0] = v; + BLI_SMALLSTACK_AS_TABLE(verts_new, &verts[1]); + } } /** @@ -2430,131 +2428,132 @@ void bmesh_kernel_vert_separate( */ static void bmesh_kernel_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate) { - do { - LinkNode *n_orig = edges_separate->link; - do { - LinkNode *n_prev = n_orig; - LinkNode *n_step = n_orig->next; - BMEdge *e_orig = n_orig->link; - do { - BMEdge *e = n_step->link; - BLI_assert(e != e_orig); - if ((e->v1 == e_orig->v1) && (e->v2 == e_orig->v2) && - BM_edge_splice(bm, e_orig, e)) - { - /* don't visit again */ - n_prev->next = n_step->next; - } - else { - n_prev = n_step; - } - } while ((n_step = n_step->next)); - - } while ((n_orig = n_orig->next) && n_orig->next); - } while ((edges_separate = edges_separate->next)); + do { + LinkNode *n_orig = edges_separate->link; + do { + LinkNode *n_prev = n_orig; + LinkNode *n_step = n_orig->next; + BMEdge *e_orig = n_orig->link; + do { + BMEdge *e = n_step->link; + BLI_assert(e != e_orig); + if ((e->v1 == e_orig->v1) && (e->v2 == e_orig->v2) && BM_edge_splice(bm, e_orig, e)) { + /* don't visit again */ + n_prev->next = n_step->next; + } + else { + n_prev = n_step; + } + } while ((n_step = n_step->next)); + + } while ((n_orig = n_orig->next) && n_orig->next); + } while ((edges_separate = edges_separate->next)); } /** * High level function which wraps both #bmesh_kernel_vert_separate and #bmesh_kernel_edge_separate */ -void BM_vert_separate( - BMesh *bm, BMVert *v, - BMEdge **e_in, int e_in_len, - const bool copy_select, - BMVert ***r_vout, int *r_vout_len) +void BM_vert_separate(BMesh *bm, + BMVert *v, + BMEdge **e_in, + int e_in_len, + const bool copy_select, + BMVert ***r_vout, + int *r_vout_len) { - LinkNode *edges_separate = NULL; - int i; - - for (i = 0; i < e_in_len; i++) { - BMEdge *e = e_in[i]; - if (bm_edge_supports_separate(e)) { - LinkNode *edges_orig = NULL; - do { - BMLoop *l_sep = e->l; - bmesh_kernel_edge_separate(bm, e, l_sep, copy_select); - BLI_linklist_prepend_alloca(&edges_orig, l_sep->e); - BLI_assert(e != l_sep->e); - } while (bm_edge_supports_separate(e)); - BLI_linklist_prepend_alloca(&edges_orig, e); - BLI_linklist_prepend_alloca(&edges_separate, edges_orig); - } - } - - bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select); - - if (edges_separate) { - bmesh_kernel_vert_separate__cleanup(bm, edges_separate); - } + LinkNode *edges_separate = NULL; + int i; + + for (i = 0; i < e_in_len; i++) { + BMEdge *e = e_in[i]; + if (bm_edge_supports_separate(e)) { + LinkNode *edges_orig = NULL; + do { + BMLoop *l_sep = e->l; + bmesh_kernel_edge_separate(bm, e, l_sep, copy_select); + BLI_linklist_prepend_alloca(&edges_orig, l_sep->e); + BLI_assert(e != l_sep->e); + } while (bm_edge_supports_separate(e)); + BLI_linklist_prepend_alloca(&edges_orig, e); + BLI_linklist_prepend_alloca(&edges_separate, edges_orig); + } + } + + bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select); + + if (edges_separate) { + bmesh_kernel_vert_separate__cleanup(bm, edges_separate); + } } - /** * A version of #BM_vert_separate which takes a flag. */ -void BM_vert_separate_hflag( - BMesh *bm, BMVert *v, - const char hflag, - const bool copy_select, - BMVert ***r_vout, int *r_vout_len) +void BM_vert_separate_hflag(BMesh *bm, + BMVert *v, + const char hflag, + const bool copy_select, + BMVert ***r_vout, + int *r_vout_len) { - LinkNode *edges_separate = NULL; - BMEdge *e_iter, *e_first; - - e_iter = e_first = v->e; - do { - if (BM_elem_flag_test(e_iter, hflag)) { - BMEdge *e = e_iter; - if (bm_edge_supports_separate(e)) { - LinkNode *edges_orig = NULL; - do { - BMLoop *l_sep = e->l; - bmesh_kernel_edge_separate(bm, e, l_sep, copy_select); - /* trick to avoid looping over separated edges */ - if (edges_separate == NULL && edges_orig == NULL) { - e_first = l_sep->e; - } - BLI_linklist_prepend_alloca(&edges_orig, l_sep->e); - BLI_assert(e != l_sep->e); - } while (bm_edge_supports_separate(e)); - BLI_linklist_prepend_alloca(&edges_orig, e); - BLI_linklist_prepend_alloca(&edges_separate, edges_orig); - } - } - } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first); - - bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select); - - if (edges_separate) { - bmesh_kernel_vert_separate__cleanup(bm, edges_separate); - } + LinkNode *edges_separate = NULL; + BMEdge *e_iter, *e_first; + + e_iter = e_first = v->e; + do { + if (BM_elem_flag_test(e_iter, hflag)) { + BMEdge *e = e_iter; + if (bm_edge_supports_separate(e)) { + LinkNode *edges_orig = NULL; + do { + BMLoop *l_sep = e->l; + bmesh_kernel_edge_separate(bm, e, l_sep, copy_select); + /* trick to avoid looping over separated edges */ + if (edges_separate == NULL && edges_orig == NULL) { + e_first = l_sep->e; + } + BLI_linklist_prepend_alloca(&edges_orig, l_sep->e); + BLI_assert(e != l_sep->e); + } while (bm_edge_supports_separate(e)); + BLI_linklist_prepend_alloca(&edges_orig, e); + BLI_linklist_prepend_alloca(&edges_separate, edges_orig); + } + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first); + + bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select); + + if (edges_separate) { + bmesh_kernel_vert_separate__cleanup(bm, edges_separate); + } } -void BM_vert_separate_tested_edges( - BMesh *UNUSED(bm), BMVert *v_dst, BMVert *v_src, - bool (*testfn)(BMEdge *, void *arg), void *arg) +void BM_vert_separate_tested_edges(BMesh *UNUSED(bm), + BMVert *v_dst, + BMVert *v_src, + bool (*testfn)(BMEdge *, void *arg), + void *arg) { - LinkNode *edges_hflag = NULL; - BMEdge *e_iter, *e_first; - - e_iter = e_first = v_src->e; - do { - if (testfn(e_iter, arg)) { - BLI_linklist_prepend_alloca(&edges_hflag, e_iter); - } - } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_src)) != e_first); - - if (edges_hflag) { - do { - e_iter = edges_hflag->link; - bmesh_disk_vert_replace(e_iter, v_dst, v_src); - } while ((edges_hflag = edges_hflag->next)); - } + LinkNode *edges_hflag = NULL; + BMEdge *e_iter, *e_first; + + e_iter = e_first = v_src->e; + do { + if (testfn(e_iter, arg)) { + BLI_linklist_prepend_alloca(&edges_hflag, e_iter); + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_src)) != e_first); + + if (edges_hflag) { + do { + e_iter = edges_hflag->link; + bmesh_disk_vert_replace(e_iter, v_dst, v_src); + } while ((edges_hflag = edges_hflag->next)); + } } /** \} */ - /** * \brief Splice Edge * @@ -2567,35 +2566,35 @@ void BM_vert_separate_tested_edges( */ bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src) { - BMLoop *l; + BMLoop *l; - if (!BM_vert_in_edge(e_src, e_dst->v1) || !BM_vert_in_edge(e_src, e_dst->v2)) { - /* not the same vertices can't splice */ + if (!BM_vert_in_edge(e_src, e_dst->v1) || !BM_vert_in_edge(e_src, e_dst->v2)) { + /* not the same vertices can't splice */ - /* the caller should really make sure this doesn't happen ever - * so assert on release builds */ - BLI_assert(0); + /* the caller should really make sure this doesn't happen ever + * so assert on release builds */ + BLI_assert(0); - return false; - } + return false; + } - while (e_src->l) { - l = e_src->l; - BLI_assert(BM_vert_in_edge(e_dst, l->v)); - BLI_assert(BM_vert_in_edge(e_dst, l->next->v)); - bmesh_radial_loop_remove(e_src, l); - bmesh_radial_loop_append(e_dst, l); - } + while (e_src->l) { + l = e_src->l; + BLI_assert(BM_vert_in_edge(e_dst, l->v)); + BLI_assert(BM_vert_in_edge(e_dst, l->next->v)); + bmesh_radial_loop_remove(e_src, l); + bmesh_radial_loop_append(e_dst, l); + } - BLI_assert(bmesh_radial_length(e_src->l) == 0); + BLI_assert(bmesh_radial_length(e_src->l) == 0); - BM_CHECK_ELEMENT(e_src); - BM_CHECK_ELEMENT(e_dst); + BM_CHECK_ELEMENT(e_src); + BM_CHECK_ELEMENT(e_dst); - /* removes from disks too */ - BM_edge_kill(bm, e_src); + /* removes from disks too */ + BM_edge_kill(bm, e_src); - return true; + return true; } /** @@ -2609,41 +2608,39 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src) * \note Does nothing if \a l_sep is already the only loop in the * edge radial. */ -void bmesh_kernel_edge_separate( - BMesh *bm, BMEdge *e, BMLoop *l_sep, - const bool copy_select) +void bmesh_kernel_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, const bool copy_select) { - BMEdge *e_new; + BMEdge *e_new; #ifndef NDEBUG - const int radlen = bmesh_radial_length(e->l); + const int radlen = bmesh_radial_length(e->l); #endif - BLI_assert(l_sep->e == e); - BLI_assert(e->l); + BLI_assert(l_sep->e == e); + BLI_assert(e->l); - if (BM_edge_is_boundary(e)) { - BLI_assert(0); /* no cut required */ - return; - } + if (BM_edge_is_boundary(e)) { + BLI_assert(0); /* no cut required */ + return; + } - if (l_sep == e->l) { - e->l = l_sep->radial_next; - } + if (l_sep == e->l) { + e->l = l_sep->radial_next; + } - e_new = BM_edge_create(bm, e->v1, e->v2, e, BM_CREATE_NOP); - bmesh_radial_loop_remove(e, l_sep); - bmesh_radial_loop_append(e_new, l_sep); - l_sep->e = e_new; + e_new = BM_edge_create(bm, e->v1, e->v2, e, BM_CREATE_NOP); + bmesh_radial_loop_remove(e, l_sep); + bmesh_radial_loop_append(e_new, l_sep); + l_sep->e = e_new; - if (copy_select) { - BM_elem_select_copy(bm, e_new, e); - } + if (copy_select) { + BM_elem_select_copy(bm, e_new, e); + } - BLI_assert(bmesh_radial_length(e->l) == radlen - 1); - BLI_assert(bmesh_radial_length(e_new->l) == 1); + BLI_assert(bmesh_radial_length(e->l) == radlen - 1); + BLI_assert(bmesh_radial_length(e_new->l) == 1); - BM_CHECK_ELEMENT(e_new); - BM_CHECK_ELEMENT(e); + BM_CHECK_ELEMENT(e_new); + BM_CHECK_ELEMENT(e); } /** @@ -2657,64 +2654,64 @@ void bmesh_kernel_edge_separate( */ BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep) { - BMVert *v_new = NULL; - BMVert *v_sep = l_sep->v; - BMEdge *e_iter; - BMEdge *edges[2]; - int i; - - /* peel the face from the edge radials on both sides of the - * loop vert, disconnecting the face from its fan */ - if (!BM_edge_is_boundary(l_sep->e)) { - bmesh_kernel_edge_separate(bm, l_sep->e, l_sep, false); - } - if (!BM_edge_is_boundary(l_sep->prev->e)) { - bmesh_kernel_edge_separate(bm, l_sep->prev->e, l_sep->prev, false); - } - - /* do inline, below */ + BMVert *v_new = NULL; + BMVert *v_sep = l_sep->v; + BMEdge *e_iter; + BMEdge *edges[2]; + int i; + + /* peel the face from the edge radials on both sides of the + * loop vert, disconnecting the face from its fan */ + if (!BM_edge_is_boundary(l_sep->e)) { + bmesh_kernel_edge_separate(bm, l_sep->e, l_sep, false); + } + if (!BM_edge_is_boundary(l_sep->prev->e)) { + bmesh_kernel_edge_separate(bm, l_sep->prev->e, l_sep->prev, false); + } + + /* do inline, below */ #if 0 - if (BM_vert_edge_count_is_equal(v_sep, 2)) { - return v_sep; - } + if (BM_vert_edge_count_is_equal(v_sep, 2)) { + return v_sep; + } #endif - /* Search for an edge unattached to this loop */ - e_iter = v_sep->e; - while (!ELEM(e_iter, l_sep->e, l_sep->prev->e)) { - e_iter = bmesh_disk_edge_next(e_iter, v_sep); + /* Search for an edge unattached to this loop */ + e_iter = v_sep->e; + while (!ELEM(e_iter, l_sep->e, l_sep->prev->e)) { + e_iter = bmesh_disk_edge_next(e_iter, v_sep); - /* We've come back around to the initial edge, all touch this loop. - * If there are still only two edges out of v_sep, - * then this whole URMV was just a no-op, so exit now. */ - if (e_iter == v_sep->e) { - BLI_assert(BM_vert_edge_count_is_equal(v_sep, 2)); - return v_sep; - } - } + /* We've come back around to the initial edge, all touch this loop. + * If there are still only two edges out of v_sep, + * then this whole URMV was just a no-op, so exit now. */ + if (e_iter == v_sep->e) { + BLI_assert(BM_vert_edge_count_is_equal(v_sep, 2)); + return v_sep; + } + } - v_sep->e = l_sep->e; + v_sep->e = l_sep->e; - v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP); + v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP); - edges[0] = l_sep->e; - edges[1] = l_sep->prev->e; + edges[0] = l_sep->e; + edges[1] = l_sep->prev->e; - for (i = 0; i < ARRAY_SIZE(edges); i++) { - BMEdge *e = edges[i]; - bmesh_edge_vert_swap(e, v_new, v_sep); - } + for (i = 0; i < ARRAY_SIZE(edges); i++) { + BMEdge *e = edges[i]; + bmesh_edge_vert_swap(e, v_new, v_sep); + } - BLI_assert(v_sep != l_sep->v); - BLI_assert(v_sep->e != l_sep->v->e); + BLI_assert(v_sep != l_sep->v); + BLI_assert(v_sep->e != l_sep->v->e); - BM_CHECK_ELEMENT(l_sep); - BM_CHECK_ELEMENT(v_sep); - BM_CHECK_ELEMENT(edges[0]); - BM_CHECK_ELEMENT(edges[1]); - BM_CHECK_ELEMENT(v_new); + BM_CHECK_ELEMENT(l_sep); + BM_CHECK_ELEMENT(v_sep); + BM_CHECK_ELEMENT(edges[0]); + BM_CHECK_ELEMENT(edges[1]); + BM_CHECK_ELEMENT(v_new); - return v_new; + return v_new; } /** @@ -2724,186 +2721,184 @@ BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep) * * This function handles the details of finding fans boundaries. */ -BMVert *bmesh_kernel_unglue_region_make_vert_multi( - BMesh *bm, BMLoop **larr, int larr_len) +BMVert *bmesh_kernel_unglue_region_make_vert_multi(BMesh *bm, BMLoop **larr, int larr_len) { - BMVert *v_sep = larr[0]->v; - BMVert *v_new; - int edges_len = 0; - int i; - /* any edges not owned by 'larr' loops connected to 'v_sep'? */ - bool is_mixed_edge_any = false; - /* any loops not owned by 'larr' radially connected to 'larr' loop edges? */ - bool is_mixed_loop_any = false; + BMVert *v_sep = larr[0]->v; + BMVert *v_new; + int edges_len = 0; + int i; + /* any edges not owned by 'larr' loops connected to 'v_sep'? */ + bool is_mixed_edge_any = false; + /* any loops not owned by 'larr' radially connected to 'larr' loop edges? */ + bool is_mixed_loop_any = false; #define LOOP_VISIT _FLAG_WALK #define EDGE_VISIT _FLAG_WALK - for (i = 0; i < larr_len; i++) { - BMLoop *l_sep = larr[i]; - - /* all must be from the same vert! */ - BLI_assert(v_sep == l_sep->v); - - BLI_assert(!BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT)); - BM_ELEM_API_FLAG_ENABLE(l_sep, LOOP_VISIT); - - /* weak! but it makes it simpler to check for edges to split - * while doing a radial loop (where loops may be adjacent) */ - BM_ELEM_API_FLAG_ENABLE(l_sep->next, LOOP_VISIT); - BM_ELEM_API_FLAG_ENABLE(l_sep->prev, LOOP_VISIT); - - BMLoop *loop_pair[2] = {l_sep, l_sep->prev}; - for (int j = 0; j < ARRAY_SIZE(loop_pair); j++) { - BMEdge *e = loop_pair[j]->e; - if (!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)) { - BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT); - edges_len += 1; - } - } - } - - BMEdge **edges = BLI_array_alloca(edges, edges_len); - STACK_DECLARE(edges); - - STACK_INIT(edges, edges_len); - - { - BMEdge *e_first, *e_iter; - e_iter = e_first = v_sep->e; - do { - if (BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)) { - BMLoop *l_iter, *l_first; - bool is_mixed_loop = false; - - l_iter = l_first = e_iter->l; - do { - if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { - is_mixed_loop = true; - break; - } - } while ((l_iter = l_iter->radial_next) != l_first); - - if (is_mixed_loop) { - /* ensure the first loop is one we don't own so we can do a quick check below - * on the edge's loop-flag to see if the edge is mixed or not. */ - e_iter->l = l_iter; - - is_mixed_loop_any = true; - } - - STACK_PUSH(edges, e_iter); - } - else { - /* at least one edge attached isn't connected to our loops */ - is_mixed_edge_any = true; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v_sep)) != e_first); - } - - BLI_assert(edges_len == STACK_SIZE(edges)); - - if (is_mixed_loop_any == false && is_mixed_edge_any == false) { - /* all loops in 'larr' are the sole owners of their edges. - * nothing to split away from, this is a no-op */ - v_new = v_sep; - } - else { - v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP); - - for (i = 0; i < STACK_SIZE(edges); i++) { - BMEdge *e = edges[i]; - BMLoop *l_iter, *l_first, *l_next; - BMEdge *e_new; - - /* disable so copied edge isn't left dirty (loop edges are cleared last too) */ - BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); - - /* will always be false when (is_mixed_loop_any == false) */ - if (!BM_ELEM_API_FLAG_TEST(e->l, LOOP_VISIT)) { - /* edge has some loops owned by us, some owned by other loops */ - BMVert *e_new_v_pair[2]; - - if (e->v1 == v_sep) { - e_new_v_pair[0] = v_new; - e_new_v_pair[1] = e->v2; - } - else { - BLI_assert(v_sep == e->v2); - e_new_v_pair[0] = e->v1; - e_new_v_pair[1] = v_new; - } - - e_new = BM_edge_create(bm, UNPACK2(e_new_v_pair), e, BM_CREATE_NOP); - - /* now moved all loops from 'larr' to this newly created edge */ - l_iter = l_first = e->l; - do { - l_next = l_iter->radial_next; - if (BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { - bmesh_radial_loop_remove(e, l_iter); - bmesh_radial_loop_append(e_new, l_iter); - l_iter->e = e_new; - } - } while ((l_iter = l_next) != l_first); - } - else { - /* we own the edge entirely, replace the vert */ - bmesh_disk_vert_replace(e, v_new, v_sep); - } - - /* loop vert is handled last! */ - } - } - - for (i = 0; i < larr_len; i++) { - BMLoop *l_sep = larr[i]; - - l_sep->v = v_new; - - BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT)); - BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->prev, LOOP_VISIT)); - BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->next, LOOP_VISIT)); - BM_ELEM_API_FLAG_DISABLE(l_sep, LOOP_VISIT); - BM_ELEM_API_FLAG_DISABLE(l_sep->prev, LOOP_VISIT); - BM_ELEM_API_FLAG_DISABLE(l_sep->next, LOOP_VISIT); - - - BM_ELEM_API_FLAG_DISABLE(l_sep->prev->e, EDGE_VISIT); - BM_ELEM_API_FLAG_DISABLE(l_sep->e, EDGE_VISIT); - } + for (i = 0; i < larr_len; i++) { + BMLoop *l_sep = larr[i]; + + /* all must be from the same vert! */ + BLI_assert(v_sep == l_sep->v); + + BLI_assert(!BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT)); + BM_ELEM_API_FLAG_ENABLE(l_sep, LOOP_VISIT); + + /* weak! but it makes it simpler to check for edges to split + * while doing a radial loop (where loops may be adjacent) */ + BM_ELEM_API_FLAG_ENABLE(l_sep->next, LOOP_VISIT); + BM_ELEM_API_FLAG_ENABLE(l_sep->prev, LOOP_VISIT); + + BMLoop *loop_pair[2] = {l_sep, l_sep->prev}; + for (int j = 0; j < ARRAY_SIZE(loop_pair); j++) { + BMEdge *e = loop_pair[j]->e; + if (!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)) { + BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT); + edges_len += 1; + } + } + } + + BMEdge **edges = BLI_array_alloca(edges, edges_len); + STACK_DECLARE(edges); + + STACK_INIT(edges, edges_len); + + { + BMEdge *e_first, *e_iter; + e_iter = e_first = v_sep->e; + do { + if (BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)) { + BMLoop *l_iter, *l_first; + bool is_mixed_loop = false; + + l_iter = l_first = e_iter->l; + do { + if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { + is_mixed_loop = true; + break; + } + } while ((l_iter = l_iter->radial_next) != l_first); + + if (is_mixed_loop) { + /* ensure the first loop is one we don't own so we can do a quick check below + * on the edge's loop-flag to see if the edge is mixed or not. */ + e_iter->l = l_iter; + + is_mixed_loop_any = true; + } + + STACK_PUSH(edges, e_iter); + } + else { + /* at least one edge attached isn't connected to our loops */ + is_mixed_edge_any = true; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v_sep)) != e_first); + } + + BLI_assert(edges_len == STACK_SIZE(edges)); + + if (is_mixed_loop_any == false && is_mixed_edge_any == false) { + /* all loops in 'larr' are the sole owners of their edges. + * nothing to split away from, this is a no-op */ + v_new = v_sep; + } + else { + v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP); + + for (i = 0; i < STACK_SIZE(edges); i++) { + BMEdge *e = edges[i]; + BMLoop *l_iter, *l_first, *l_next; + BMEdge *e_new; + + /* disable so copied edge isn't left dirty (loop edges are cleared last too) */ + BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); + + /* will always be false when (is_mixed_loop_any == false) */ + if (!BM_ELEM_API_FLAG_TEST(e->l, LOOP_VISIT)) { + /* edge has some loops owned by us, some owned by other loops */ + BMVert *e_new_v_pair[2]; + + if (e->v1 == v_sep) { + e_new_v_pair[0] = v_new; + e_new_v_pair[1] = e->v2; + } + else { + BLI_assert(v_sep == e->v2); + e_new_v_pair[0] = e->v1; + e_new_v_pair[1] = v_new; + } + + e_new = BM_edge_create(bm, UNPACK2(e_new_v_pair), e, BM_CREATE_NOP); + + /* now moved all loops from 'larr' to this newly created edge */ + l_iter = l_first = e->l; + do { + l_next = l_iter->radial_next; + if (BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { + bmesh_radial_loop_remove(e, l_iter); + bmesh_radial_loop_append(e_new, l_iter); + l_iter->e = e_new; + } + } while ((l_iter = l_next) != l_first); + } + else { + /* we own the edge entirely, replace the vert */ + bmesh_disk_vert_replace(e, v_new, v_sep); + } + + /* loop vert is handled last! */ + } + } + + for (i = 0; i < larr_len; i++) { + BMLoop *l_sep = larr[i]; + + l_sep->v = v_new; + + BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT)); + BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->prev, LOOP_VISIT)); + BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->next, LOOP_VISIT)); + BM_ELEM_API_FLAG_DISABLE(l_sep, LOOP_VISIT); + BM_ELEM_API_FLAG_DISABLE(l_sep->prev, LOOP_VISIT); + BM_ELEM_API_FLAG_DISABLE(l_sep->next, LOOP_VISIT); + + BM_ELEM_API_FLAG_DISABLE(l_sep->prev->e, EDGE_VISIT); + BM_ELEM_API_FLAG_DISABLE(l_sep->e, EDGE_VISIT); + } #undef LOOP_VISIT #undef EDGE_VISIT - return v_new; + return v_new; } static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_src) { - BMLoop *l_iter, *l_first; - - BLI_assert(ELEM(v_src, e->v1, e->v2)); - bmesh_disk_vert_replace(e, v_dst, v_src); - - l_iter = l_first = e->l; - do { - if (l_iter->v == v_src) { - l_iter->v = v_dst; - if (BM_vert_in_edge(l_iter->prev->e, v_src)) { - bmesh_edge_vert_swap__recursive(l_iter->prev->e, v_dst, v_src); - } - } - else if (l_iter->next->v == v_src) { - l_iter->next->v = v_dst; - if (BM_vert_in_edge(l_iter->next->e, v_src)) { - bmesh_edge_vert_swap__recursive(l_iter->next->e, v_dst, v_src); - } - } - else { - BLI_assert(l_iter->prev->v != v_src); - } - } while ((l_iter = l_iter->radial_next) != l_first); + BMLoop *l_iter, *l_first; + + BLI_assert(ELEM(v_src, e->v1, e->v2)); + bmesh_disk_vert_replace(e, v_dst, v_src); + + l_iter = l_first = e->l; + do { + if (l_iter->v == v_src) { + l_iter->v = v_dst; + if (BM_vert_in_edge(l_iter->prev->e, v_src)) { + bmesh_edge_vert_swap__recursive(l_iter->prev->e, v_dst, v_src); + } + } + else if (l_iter->next->v == v_src) { + l_iter->next->v = v_dst; + if (BM_vert_in_edge(l_iter->next->e, v_src)) { + bmesh_edge_vert_swap__recursive(l_iter->next->e, v_dst, v_src); + } + } + else { + BLI_assert(l_iter->prev->v != v_src); + } + } while ((l_iter = l_iter->radial_next) != l_first); } /** @@ -2912,11 +2907,11 @@ static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_ */ BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l_sep) { - BMVert *v_new = BM_vert_create(bm, l_sep->v->co, l_sep->v, BM_CREATE_NOP); - /* passing either 'l_sep->e', 'l_sep->prev->e' will work */ - bmesh_edge_vert_swap__recursive(l_sep->e, v_new, l_sep->v); - BLI_assert(l_sep->v == v_new); - return v_new; + BMVert *v_new = BM_vert_create(bm, l_sep->v->co, l_sep->v, BM_CREATE_NOP); + /* passing either 'l_sep->e', 'l_sep->prev->e' will work */ + bmesh_edge_vert_swap__recursive(l_sep->e, v_new, l_sep->v); + BLI_assert(l_sep->v == v_new); + return v_new; } /** @@ -2926,23 +2921,23 @@ BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l */ void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b) { - BMLoop *l_iter, *l_first; + BMLoop *l_iter, *l_first; - BLI_assert(f_a != f_b); + BLI_assert(f_a != f_b); - l_iter = l_first = BM_FACE_FIRST_LOOP(f_a); - do { - l_iter->f = f_b; - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f_a); + do { + l_iter->f = f_b; + } while ((l_iter = l_iter->next) != l_first); - l_iter = l_first = BM_FACE_FIRST_LOOP(f_b); - do { - l_iter->f = f_a; - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f_b); + do { + l_iter->f = f_a; + } while ((l_iter = l_iter->next) != l_first); - SWAP(BMFace, (*f_a), (*f_b)); + SWAP(BMFace, (*f_a), (*f_b)); - /* swap back */ - SWAP(void *, f_a->head.data, f_b->head.data); - SWAP(int, f_a->head.index, f_b->head.index); + /* swap back */ + SWAP(void *, f_a->head.data, f_b->head.data); + SWAP(int, f_a->head.index, f_b->head.index); } diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index dc20b8afaac..3308f93d5d3 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -22,96 +22,107 @@ */ BMFace *BM_face_copy( - BMesh *bm_dst, BMesh *bm_src, BMFace *f, - const bool copy_verts, const bool copy_edges); + BMesh *bm_dst, BMesh *bm_src, BMFace *f, const bool copy_verts, const bool copy_edges); typedef enum eBMCreateFlag { - BM_CREATE_NOP = 0, - /* faces and edges only */ - BM_CREATE_NO_DOUBLE = (1 << 1), - /* Skip CustomData - for all element types data, - * use if we immediately write customdata into the element so this skips copying from 'example' - * args or setting defaults, speeds up conversion when data is converted all at once. */ - BM_CREATE_SKIP_CD = (1 << 2), + BM_CREATE_NOP = 0, + /* faces and edges only */ + BM_CREATE_NO_DOUBLE = (1 << 1), + /* Skip CustomData - for all element types data, + * use if we immediately write customdata into the element so this skips copying from 'example' + * args or setting defaults, speeds up conversion when data is converted all at once. */ + BM_CREATE_SKIP_CD = (1 << 2), } eBMCreateFlag; -BMVert *BM_vert_create( - BMesh *bm, const float co[3], - const BMVert *v_example, const eBMCreateFlag create_flag); +BMVert *BM_vert_create(BMesh *bm, + const float co[3], + const BMVert *v_example, + const eBMCreateFlag create_flag); BMEdge *BM_edge_create( - BMesh *bm, BMVert *v1, BMVert *v2, - const BMEdge *e_example, const eBMCreateFlag create_flag); -BMFace *BM_face_create( - BMesh *bm, BMVert **verts, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag); -BMFace *BM_face_create_verts( - BMesh *bm, BMVert **verts, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, - const bool create_edges); - -void BM_face_edges_kill(BMesh *bm, BMFace *f); -void BM_face_verts_kill(BMesh *bm, BMFace *f); - -void BM_face_kill_loose(BMesh *bm, BMFace *f); - -void BM_face_kill(BMesh *bm, BMFace *f); -void BM_edge_kill(BMesh *bm, BMEdge *e); -void BM_vert_kill(BMesh *bm, BMVert *v); - -bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src); -bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src); -bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b); - -void bmesh_kernel_loop_reverse( - BMesh *bm, BMFace *f, - const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip); - -void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b); + BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create(BMesh *bm, + BMVert **verts, + BMEdge **edges, + const int len, + const BMFace *f_example, + const eBMCreateFlag create_flag); +BMFace *BM_face_create_verts(BMesh *bm, + BMVert **verts, + const int len, + const BMFace *f_example, + const eBMCreateFlag create_flag, + const bool create_edges); + +void BM_face_edges_kill(BMesh *bm, BMFace *f); +void BM_face_verts_kill(BMesh *bm, BMFace *f); + +void BM_face_kill_loose(BMesh *bm, BMFace *f); + +void BM_face_kill(BMesh *bm, BMFace *f); +void BM_edge_kill(BMesh *bm, BMEdge *e); +void BM_vert_kill(BMesh *bm, BMVert *v); + +bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src); +bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src); +bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b); + +void bmesh_kernel_loop_reverse(BMesh *bm, + BMFace *f, + const int cd_loop_mdisp_offset, + const bool use_loop_mdisp_flip); + +void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b); BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del); -void BM_vert_separate( - BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select, - BMVert ***r_vout, int *r_vout_len); -void BM_vert_separate_hflag( - BMesh *bm, BMVert *v, const char hflag, const bool copy_select, - BMVert ***r_vout, int *r_vout_len); +void BM_vert_separate(BMesh *bm, + BMVert *v, + BMEdge **e_in, + int e_in_len, + const bool copy_select, + BMVert ***r_vout, + int *r_vout_len); +void BM_vert_separate_hflag(BMesh *bm, + BMVert *v, + const char hflag, + const bool copy_select, + BMVert ***r_vout, + int *r_vout_len); void BM_vert_separate_tested_edges( - BMesh *bm, BMVert *v_dst, BMVert *v_src, - bool (*testfn)(BMEdge *, void *arg), void *arg); + BMesh *bm, BMVert *v_dst, BMVert *v_src, bool (*testfn)(BMEdge *, void *arg), void *arg); /** * BMesh Kernel: For modifying structure. * * Names are on the verbose side but these are only for low-level access. */ -void bmesh_kernel_vert_separate( - BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - const bool copy_select); -void bmesh_kernel_edge_separate( - BMesh *bm, BMEdge *e, BMLoop *l_sep, - const bool copy_select); - -BMFace *bmesh_kernel_split_face_make_edge( - BMesh *bm, BMFace *f, - BMLoop *l1, BMLoop *l2, - BMLoop **r_l, +void bmesh_kernel_vert_separate( + BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, const bool copy_select); +void bmesh_kernel_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, const bool copy_select); + +BMFace *bmesh_kernel_split_face_make_edge(BMesh *bm, + BMFace *f, + BMLoop *l1, + BMLoop *l2, + BMLoop **r_l, #ifdef USE_BMESH_HOLES - ListBase *holes, + ListBase *holes, #endif - BMEdge *example, - const bool no_double - ); - -BMVert *bmesh_kernel_split_edge_make_vert( - BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e); -BMEdge *bmesh_kernel_join_edge_kill_vert( - BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool check_edge_splice, - const bool kill_degenerate_faces); -BMVert *bmesh_kernel_join_vert_kill_edge( - BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool check_edge_double, - const bool kill_degenerate_faces); + BMEdge *example, + const bool no_double); + +BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e); +BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm, + BMEdge *e_kill, + BMVert *v_kill, + const bool do_del, + const bool check_edge_splice, + const bool kill_degenerate_faces); +BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm, + BMEdge *e_kill, + BMVert *v_kill, + const bool do_del, + const bool check_edge_double, + const bool kill_degenerate_faces); BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e); BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep); diff --git a/source/blender/bmesh/intern/bmesh_delete.c b/source/blender/bmesh/intern/bmesh_delete.c index 23fe8a31b41..4e2c81c80c3 100644 --- a/source/blender/bmesh/intern/bmesh_delete.c +++ b/source/blender/bmesh/intern/bmesh_delete.c @@ -23,13 +23,11 @@ * BM remove functions. */ - #include "BLI_utildefines.h" #include "bmesh.h" #include "intern/bmesh_private.h" - /* -------------------------------------------------------------------- */ /* BMO functions */ @@ -42,63 +40,63 @@ */ static void bmo_remove_tagged_faces(BMesh *bm, const short oflag) { - BMFace *f, *f_next; - BMIter iter; - - BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) { - if (BMO_face_flag_test(bm, f, oflag)) { - BM_face_kill(bm, f); - } - } + BMFace *f, *f_next; + BMIter iter; + + BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) { + if (BMO_face_flag_test(bm, f, oflag)) { + BM_face_kill(bm, f); + } + } } static void bmo_remove_tagged_edges(BMesh *bm, const short oflag) { - BMEdge *e, *e_next; - BMIter iter; - - BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { - if (BMO_edge_flag_test(bm, e, oflag)) { - BM_edge_kill(bm, e); - } - } + BMEdge *e, *e_next; + BMIter iter; + + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { + if (BMO_edge_flag_test(bm, e, oflag)) { + BM_edge_kill(bm, e); + } + } } static void bmo_remove_tagged_verts(BMesh *bm, const short oflag) { - BMVert *v, *v_next; - BMIter iter; - - BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { - if (BMO_vert_flag_test(bm, v, oflag)) { - BM_vert_kill(bm, v); - } - } + BMVert *v, *v_next; + BMIter iter; + + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { + if (BMO_vert_flag_test(bm, v, oflag)) { + BM_vert_kill(bm, v); + } + } } static void bmo_remove_tagged_verts_loose(BMesh *bm, const short oflag) { - BMVert *v, *v_next; - BMIter iter; - - BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { - if (BMO_vert_flag_test(bm, v, oflag) && (v->e == NULL)) { - BM_vert_kill(bm, v); - } - } + BMVert *v, *v_next; + BMIter iter; + + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { + if (BMO_vert_flag_test(bm, v, oflag) && (v->e == NULL)) { + BM_vert_kill(bm, v); + } + } } void BMO_mesh_delete_oflag_tagged(BMesh *bm, const short oflag, const char htype) { - if (htype & BM_FACE) { - bmo_remove_tagged_faces(bm, oflag); - } - if (htype & BM_EDGE) { - bmo_remove_tagged_edges(bm, oflag); - } - if (htype & BM_VERT) { - bmo_remove_tagged_verts(bm, oflag); - } + if (htype & BM_FACE) { + bmo_remove_tagged_faces(bm, oflag); + } + if (htype & BM_EDGE) { + bmo_remove_tagged_edges(bm, oflag); + } + if (htype & BM_VERT) { + bmo_remove_tagged_verts(bm, oflag); + } } /** @@ -107,111 +105,104 @@ void BMO_mesh_delete_oflag_tagged(BMesh *bm, const short oflag, const char htype */ void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type) { - BMEdge *e; - BMFace *f; - - BMIter eiter; - BMIter fiter; - - switch (type) { - case DEL_VERTS: - { - bmo_remove_tagged_verts(bm, oflag); - - break; - } - case DEL_EDGES: - { - /* flush down to vert */ - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BMO_edge_flag_test(bm, e, oflag)) { - BMO_vert_flag_enable(bm, e->v1, oflag); - BMO_vert_flag_enable(bm, e->v2, oflag); - } - } - bmo_remove_tagged_edges(bm, oflag); - bmo_remove_tagged_verts_loose(bm, oflag); - - break; - } - case DEL_EDGESFACES: - { - bmo_remove_tagged_edges(bm, oflag); - - break; - } - case DEL_ONLYFACES: - { - bmo_remove_tagged_faces(bm, oflag); - - break; - } - case DEL_ONLYTAGGED: - { - BMO_mesh_delete_oflag_tagged(bm, oflag, BM_ALL_NOLOOP); - - break; - } - case DEL_FACES: - case DEL_FACES_KEEP_BOUNDARY: - { - /* go through and mark all edges and all verts of all faces for delete */ - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - if (BMO_face_flag_test(bm, f, oflag)) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter; - - l_iter = l_first; - do { - BMO_vert_flag_enable(bm, l_iter->v, oflag); - BMO_edge_flag_enable(bm, l_iter->e, oflag); - } while ((l_iter = l_iter->next) != l_first); - } - } - /* now go through and mark all remaining faces all edges for keeping */ - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - if (!BMO_face_flag_test(bm, f, oflag)) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter; - - l_iter = l_first; - do { - BMO_vert_flag_disable(bm, l_iter->v, oflag); - BMO_edge_flag_disable(bm, l_iter->e, oflag); - } while ((l_iter = l_iter->next) != l_first); - } - } - /* also mark all the vertices of remaining edges for keeping */ - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - - /* Only exception to normal 'DEL_FACES' logic. */ - if (type == DEL_FACES_KEEP_BOUNDARY) { - if (BM_edge_is_boundary(e)) { - BMO_edge_flag_disable(bm, e, oflag); - } - } - - if (!BMO_edge_flag_test(bm, e, oflag)) { - BMO_vert_flag_disable(bm, e->v1, oflag); - BMO_vert_flag_disable(bm, e->v2, oflag); - } - } - - /* now delete marked face */ - bmo_remove_tagged_faces(bm, oflag); - /* delete marked edge */ - bmo_remove_tagged_edges(bm, oflag); - /* remove loose vertice */ - bmo_remove_tagged_verts(bm, oflag); - - break; - } - } + BMEdge *e; + BMFace *f; + + BMIter eiter; + BMIter fiter; + + switch (type) { + case DEL_VERTS: { + bmo_remove_tagged_verts(bm, oflag); + + break; + } + case DEL_EDGES: { + /* flush down to vert */ + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (BMO_edge_flag_test(bm, e, oflag)) { + BMO_vert_flag_enable(bm, e->v1, oflag); + BMO_vert_flag_enable(bm, e->v2, oflag); + } + } + bmo_remove_tagged_edges(bm, oflag); + bmo_remove_tagged_verts_loose(bm, oflag); + + break; + } + case DEL_EDGESFACES: { + bmo_remove_tagged_edges(bm, oflag); + + break; + } + case DEL_ONLYFACES: { + bmo_remove_tagged_faces(bm, oflag); + + break; + } + case DEL_ONLYTAGGED: { + BMO_mesh_delete_oflag_tagged(bm, oflag, BM_ALL_NOLOOP); + + break; + } + case DEL_FACES: + case DEL_FACES_KEEP_BOUNDARY: { + /* go through and mark all edges and all verts of all faces for delete */ + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + if (BMO_face_flag_test(bm, f, oflag)) { + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter; + + l_iter = l_first; + do { + BMO_vert_flag_enable(bm, l_iter->v, oflag); + BMO_edge_flag_enable(bm, l_iter->e, oflag); + } while ((l_iter = l_iter->next) != l_first); + } + } + /* now go through and mark all remaining faces all edges for keeping */ + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + if (!BMO_face_flag_test(bm, f, oflag)) { + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter; + + l_iter = l_first; + do { + BMO_vert_flag_disable(bm, l_iter->v, oflag); + BMO_edge_flag_disable(bm, l_iter->e, oflag); + } while ((l_iter = l_iter->next) != l_first); + } + } + /* also mark all the vertices of remaining edges for keeping */ + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + + /* Only exception to normal 'DEL_FACES' logic. */ + if (type == DEL_FACES_KEEP_BOUNDARY) { + if (BM_edge_is_boundary(e)) { + BMO_edge_flag_disable(bm, e, oflag); + } + } + + if (!BMO_edge_flag_test(bm, e, oflag)) { + BMO_vert_flag_disable(bm, e->v1, oflag); + BMO_vert_flag_disable(bm, e->v2, oflag); + } + } + + /* now delete marked face */ + bmo_remove_tagged_faces(bm, oflag); + /* delete marked edge */ + bmo_remove_tagged_edges(bm, oflag); + /* remove loose vertice */ + bmo_remove_tagged_verts(bm, oflag); + + break; + } + } } /** \} */ - /* -------------------------------------------------------------------- */ /* BM functions * @@ -225,63 +216,63 @@ void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type) static void bm_remove_tagged_faces(BMesh *bm, const char hflag) { - BMFace *f, *f_next; - BMIter iter; - - BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, hflag)) { - BM_face_kill(bm, f); - } - } + BMFace *f, *f_next; + BMIter iter; + + BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, hflag)) { + BM_face_kill(bm, f); + } + } } static void bm_remove_tagged_edges(BMesh *bm, const char hflag) { - BMEdge *e, *e_next; - BMIter iter; - - BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, hflag)) { - BM_edge_kill(bm, e); - } - } + BMEdge *e, *e_next; + BMIter iter; + + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, hflag)) { + BM_edge_kill(bm, e); + } + } } static void bm_remove_tagged_verts(BMesh *bm, const char hflag) { - BMVert *v, *v_next; - BMIter iter; - - BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, hflag)) { - BM_vert_kill(bm, v); - } - } + BMVert *v, *v_next; + BMIter iter; + + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, hflag)) { + BM_vert_kill(bm, v); + } + } } static void bm_remove_tagged_verts_loose(BMesh *bm, const char hflag) { - BMVert *v, *v_next; - BMIter iter; - - BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, hflag) && (v->e == NULL)) { - BM_vert_kill(bm, v); - } - } + BMVert *v, *v_next; + BMIter iter; + + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, hflag) && (v->e == NULL)) { + BM_vert_kill(bm, v); + } + } } void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype) { - if (htype & BM_FACE) { - bm_remove_tagged_faces(bm, hflag); - } - if (htype & BM_EDGE) { - bm_remove_tagged_edges(bm, hflag); - } - if (htype & BM_VERT) { - bm_remove_tagged_verts(bm, hflag); - } + if (htype & BM_FACE) { + bm_remove_tagged_faces(bm, hflag); + } + if (htype & BM_EDGE) { + bm_remove_tagged_edges(bm, hflag); + } + if (htype & BM_VERT) { + bm_remove_tagged_verts(bm, hflag); + } } /** @@ -290,96 +281,90 @@ void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype) */ void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type) { - BMEdge *e; - BMFace *f; - - BMIter eiter; - BMIter fiter; - - switch (type) { - case DEL_VERTS: - { - bm_remove_tagged_verts(bm, hflag); - - break; - } - case DEL_EDGES: - { - /* flush down to vert */ - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, hflag)) { - BM_elem_flag_enable(e->v1, hflag); - BM_elem_flag_enable(e->v2, hflag); - } - } - bm_remove_tagged_edges(bm, hflag); - bm_remove_tagged_verts_loose(bm, hflag); - - break; - } - case DEL_EDGESFACES: - { - bm_remove_tagged_edges(bm, hflag); - - break; - } - case DEL_ONLYFACES: - { - bm_remove_tagged_faces(bm, hflag); - - break; - } - case DEL_ONLYTAGGED: - { - BM_mesh_delete_hflag_tagged(bm, hflag, BM_ALL_NOLOOP); - - break; - } - case DEL_FACES: - { - /* go through and mark all edges and all verts of all faces for delete */ - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, hflag)) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter; - - l_iter = l_first; - do { - BM_elem_flag_enable(l_iter->v, hflag); - BM_elem_flag_enable(l_iter->e, hflag); - } while ((l_iter = l_iter->next) != l_first); - } - } - /* now go through and mark all remaining faces all edges for keeping */ - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(f, hflag)) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter; - - l_iter = l_first; - do { - BM_elem_flag_disable(l_iter->v, hflag); - BM_elem_flag_disable(l_iter->e, hflag); - } while ((l_iter = l_iter->next) != l_first); - } - } - /* also mark all the vertices of remaining edges for keeping */ - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (!BM_elem_flag_test(e, hflag)) { - BM_elem_flag_disable(e->v1, hflag); - BM_elem_flag_disable(e->v2, hflag); - } - } - /* now delete marked face */ - bm_remove_tagged_faces(bm, hflag); - /* delete marked edge */ - bm_remove_tagged_edges(bm, hflag); - /* remove loose vertice */ - bm_remove_tagged_verts(bm, hflag); - - break; - } - } + BMEdge *e; + BMFace *f; + + BMIter eiter; + BMIter fiter; + + switch (type) { + case DEL_VERTS: { + bm_remove_tagged_verts(bm, hflag); + + break; + } + case DEL_EDGES: { + /* flush down to vert */ + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, hflag)) { + BM_elem_flag_enable(e->v1, hflag); + BM_elem_flag_enable(e->v2, hflag); + } + } + bm_remove_tagged_edges(bm, hflag); + bm_remove_tagged_verts_loose(bm, hflag); + + break; + } + case DEL_EDGESFACES: { + bm_remove_tagged_edges(bm, hflag); + + break; + } + case DEL_ONLYFACES: { + bm_remove_tagged_faces(bm, hflag); + + break; + } + case DEL_ONLYTAGGED: { + BM_mesh_delete_hflag_tagged(bm, hflag, BM_ALL_NOLOOP); + + break; + } + case DEL_FACES: { + /* go through and mark all edges and all verts of all faces for delete */ + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, hflag)) { + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter; + + l_iter = l_first; + do { + BM_elem_flag_enable(l_iter->v, hflag); + BM_elem_flag_enable(l_iter->e, hflag); + } while ((l_iter = l_iter->next) != l_first); + } + } + /* now go through and mark all remaining faces all edges for keeping */ + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + if (!BM_elem_flag_test(f, hflag)) { + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter; + + l_iter = l_first; + do { + BM_elem_flag_disable(l_iter->v, hflag); + BM_elem_flag_disable(l_iter->e, hflag); + } while ((l_iter = l_iter->next) != l_first); + } + } + /* also mark all the vertices of remaining edges for keeping */ + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (!BM_elem_flag_test(e, hflag)) { + BM_elem_flag_disable(e->v1, hflag); + BM_elem_flag_disable(e->v2, hflag); + } + } + /* now delete marked face */ + bm_remove_tagged_faces(bm, hflag); + /* delete marked edge */ + bm_remove_tagged_edges(bm, hflag); + /* remove loose vertice */ + bm_remove_tagged_verts(bm, hflag); + + break; + } + } } /** \} */ diff --git a/source/blender/bmesh/intern/bmesh_delete.h b/source/blender/bmesh/intern/bmesh_delete.h index 616485b242e..d41f26baddd 100644 --- a/source/blender/bmesh/intern/bmesh_delete.h +++ b/source/blender/bmesh/intern/bmesh_delete.h @@ -22,9 +22,9 @@ */ void BMO_mesh_delete_oflag_tagged(BMesh *bm, const short oflag, const char htype); -void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype); +void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype); void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type); -void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type); +void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type); #endif /* __BMESH_DELETE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c index 1f8661c3e04..a802515a3b2 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.c +++ b/source/blender/bmesh/intern/bmesh_edgeloop.c @@ -33,15 +33,15 @@ #include "bmesh.h" -#include "bmesh_edgeloop.h" /* own include */ +#include "bmesh_edgeloop.h" /* own include */ typedef struct BMEdgeLoopStore { - struct BMEdgeLoopStore *next, *prev; - ListBase verts; - int flag; - int len; - /* optional values to calc */ - float co[3], no[3]; + struct BMEdgeLoopStore *next, *prev; + ListBase verts; + int flag; + int len; + /* optional values to calc */ + float co[3], no[3]; } BMEdgeLoopStore; #define BM_EDGELOOP_IS_CLOSED (1 << 0) @@ -50,26 +50,24 @@ typedef struct BMEdgeLoopStore { /* -------------------------------------------------------------------- */ /* BM_mesh_edgeloops_find & Util Functions */ -static int bm_vert_other_tag( - BMVert *v, BMVert *v_prev, - BMEdge **r_e) +static int bm_vert_other_tag(BMVert *v, BMVert *v_prev, BMEdge **r_e) { - BMIter iter; - BMEdge *e, *e_next = NULL; - uint count = 0; - - BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) { - BMVert *v_other = BM_edge_other_vert(e, v); - if (v_other != v_prev) { - e_next = e; - count++; - } - } - } - - *r_e = e_next; - return count; + BMIter iter; + BMEdge *e, *e_next = NULL; + uint count = 0; + + BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) { + BMVert *v_other = BM_edge_other_vert(e, v); + if (v_other != v_prev) { + e_next = e; + count++; + } + } + } + + *r_e = e_next; + return count; } /** @@ -77,117 +75,115 @@ static int bm_vert_other_tag( */ static bool bm_loop_build(BMEdgeLoopStore *el_store, BMVert *v_prev, BMVert *v, int dir) { - void (*add_fn)(ListBase *, void *) = dir == 1 ? BLI_addhead : BLI_addtail; - BMEdge *e_next; - BMVert *v_next; - BMVert *v_first = v; - - BLI_assert(ABS(dir) == 1); - - if (!BM_elem_flag_test(v, BM_ELEM_INTERNAL_TAG)) { - return true; - } - - while (v) { - LinkData *node = MEM_callocN(sizeof(*node), __func__); - int count; - node->data = v; - add_fn(&el_store->verts, node); - el_store->len++; - BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG); - - count = bm_vert_other_tag(v, v_prev, &e_next); - if (count == 1) { - v_next = BM_edge_other_vert(e_next, v); - BM_elem_flag_disable(e_next, BM_ELEM_INTERNAL_TAG); - if (UNLIKELY(v_next == v_first)) { - el_store->flag |= BM_EDGELOOP_IS_CLOSED; - v_next = NULL; - } - } - else if (count == 0) { - /* pass */ - v_next = NULL; - } - else { - v_next = NULL; - return false; - } - - v_prev = v; - v = v_next; - } - - return true; + void (*add_fn)(ListBase *, void *) = dir == 1 ? BLI_addhead : BLI_addtail; + BMEdge *e_next; + BMVert *v_next; + BMVert *v_first = v; + + BLI_assert(ABS(dir) == 1); + + if (!BM_elem_flag_test(v, BM_ELEM_INTERNAL_TAG)) { + return true; + } + + while (v) { + LinkData *node = MEM_callocN(sizeof(*node), __func__); + int count; + node->data = v; + add_fn(&el_store->verts, node); + el_store->len++; + BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG); + + count = bm_vert_other_tag(v, v_prev, &e_next); + if (count == 1) { + v_next = BM_edge_other_vert(e_next, v); + BM_elem_flag_disable(e_next, BM_ELEM_INTERNAL_TAG); + if (UNLIKELY(v_next == v_first)) { + el_store->flag |= BM_EDGELOOP_IS_CLOSED; + v_next = NULL; + } + } + else if (count == 0) { + /* pass */ + v_next = NULL; + } + else { + v_next = NULL; + return false; + } + + v_prev = v; + v = v_next; + } + + return true; } /** * \return listbase of listbases, each linking to a vertex. */ -int BM_mesh_edgeloops_find( - BMesh *bm, ListBase *r_eloops, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data) +int BM_mesh_edgeloops_find(BMesh *bm, + ListBase *r_eloops, + bool (*test_fn)(BMEdge *, void *user_data), + void *user_data) { - BMIter iter; - BMEdge *e; - BMVert *v; - int count = 0; - - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG); - } - - /* first flush edges to tags, and tag verts */ - BLI_Stack *edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__); - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - BLI_assert(!BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)); - if (test_fn(e, user_data)) { - BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG); - BLI_stack_push(edge_stack, (void *)&e); - } - else { - BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); - } - } - - const uint edges_len = BLI_stack_count(edge_stack); - BMEdge **edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__); - BLI_stack_pop_n_reverse(edge_stack, edges, BLI_stack_count(edge_stack)); - BLI_stack_free(edge_stack); - - for (uint i = 0; i < edges_len; i += 1) { - e = edges[i]; - if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) { - BMEdgeLoopStore *el_store = MEM_callocN(sizeof(BMEdgeLoopStore), __func__); - - /* add both directions */ - if (bm_loop_build(el_store, e->v1, e->v2, 1) && - bm_loop_build(el_store, e->v2, e->v1, -1) && - el_store->len > 1) - { - BLI_addtail(r_eloops, el_store); - count++; - } - else { - BM_edgeloop_free(el_store); - } - } - } - - for (uint i = 0; i < edges_len; i += 1) { - e = edges[i]; - BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_disable(e->v1, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_disable(e->v2, BM_ELEM_INTERNAL_TAG); - } - - MEM_freeN(edges); - return count; + BMIter iter; + BMEdge *e; + BMVert *v; + int count = 0; + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG); + } + + /* first flush edges to tags, and tag verts */ + BLI_Stack *edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__); + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BLI_assert(!BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)); + if (test_fn(e, user_data)) { + BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG); + BLI_stack_push(edge_stack, (void *)&e); + } + else { + BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); + } + } + + const uint edges_len = BLI_stack_count(edge_stack); + BMEdge **edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__); + BLI_stack_pop_n_reverse(edge_stack, edges, BLI_stack_count(edge_stack)); + BLI_stack_free(edge_stack); + + for (uint i = 0; i < edges_len; i += 1) { + e = edges[i]; + if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) { + BMEdgeLoopStore *el_store = MEM_callocN(sizeof(BMEdgeLoopStore), __func__); + + /* add both directions */ + if (bm_loop_build(el_store, e->v1, e->v2, 1) && bm_loop_build(el_store, e->v2, e->v1, -1) && + el_store->len > 1) { + BLI_addtail(r_eloops, el_store); + count++; + } + else { + BM_edgeloop_free(el_store); + } + } + } + + for (uint i = 0; i < edges_len; i += 1) { + e = edges[i]; + BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_disable(e->v1, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_disable(e->v2, BM_ELEM_INTERNAL_TAG); + } + + MEM_freeN(edges); + return count; } - /* -------------------------------------------------------------------- */ /* BM_mesh_edgeloops_find_path & Util Functions */ @@ -196,310 +192,312 @@ int BM_mesh_edgeloops_find( * Add to */ struct VertStep { - struct VertStep *next, *prev; - BMVert *v; + struct VertStep *next, *prev; + BMVert *v; }; static void vs_add( - BLI_mempool *vs_pool, ListBase *lb, - BMVert *v, BMEdge *e_prev, const int iter_tot) + BLI_mempool *vs_pool, ListBase *lb, BMVert *v, BMEdge *e_prev, const int iter_tot) { - struct VertStep *vs_new = BLI_mempool_alloc(vs_pool); - vs_new->v = v; + struct VertStep *vs_new = BLI_mempool_alloc(vs_pool); + vs_new->v = v; - BM_elem_index_set(v, iter_tot); /* set_dirty */ + BM_elem_index_set(v, iter_tot); /* set_dirty */ - /* This edge stores a direct path back to the original vertex so we can - * backtrack without having to store an array of previous verts. */ + /* This edge stores a direct path back to the original vertex so we can + * backtrack without having to store an array of previous verts. */ - /* WARNING - setting the edge is not common practice - * but currently harmless, take care. */ - BLI_assert(BM_vert_in_edge(e_prev, v)); - v->e = e_prev; + /* WARNING - setting the edge is not common practice + * but currently harmless, take care. */ + BLI_assert(BM_vert_in_edge(e_prev, v)); + v->e = e_prev; - BLI_addtail(lb, vs_new); + BLI_addtail(lb, vs_new); } -static bool bm_loop_path_build_step(BLI_mempool *vs_pool, ListBase *lb, const int dir, BMVert *v_match[2]) +static bool bm_loop_path_build_step(BLI_mempool *vs_pool, + ListBase *lb, + const int dir, + BMVert *v_match[2]) { - ListBase lb_tmp = {NULL, NULL}; - struct VertStep *vs, *vs_next; - BLI_assert(ABS(dir) == 1); - - for (vs = lb->first; vs; vs = vs_next) { - BMIter iter; - BMEdge *e; - /* these values will be the same every iteration */ - const int vs_iter_tot = BM_elem_index_get(vs->v); - const int vs_iter_next = vs_iter_tot + dir; - - vs_next = vs->next; - - BM_ITER_ELEM (e, &iter, vs->v, BM_EDGES_OF_VERT) { - if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) { - BMVert *v_next = BM_edge_other_vert(e, vs->v); - const int v_next_index = BM_elem_index_get(v_next); - /* not essential to clear flag but prevents more checking next time round */ - BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); - if (v_next_index == 0) { - vs_add(vs_pool, &lb_tmp, v_next, e, vs_iter_next); - } - else if ((dir < 0) == (v_next_index < 0)) { - /* on the same side - do nothing */ - } - else { - /* we have met out match! (vertices from different sides meet) */ - if (dir == 1) { - v_match[0] = vs->v; - v_match[1] = v_next; - } - else { - v_match[0] = v_next; - v_match[1] = vs->v; - } - /* normally we would manage memory of remaining items in (lb, lb_tmp), - * but search is done, vs_pool will get destroyed immediately */ - return true; - } - } - } - - BLI_mempool_free(vs_pool, vs); - } - /* bm->elem_index_dirty |= BM_VERT; */ /* Commented because used in a loop, and this flag has already been set. */ - - /* lb is now full of free'd items, overwrite */ - *lb = lb_tmp; - - return (BLI_listbase_is_empty(lb) == false); + ListBase lb_tmp = {NULL, NULL}; + struct VertStep *vs, *vs_next; + BLI_assert(ABS(dir) == 1); + + for (vs = lb->first; vs; vs = vs_next) { + BMIter iter; + BMEdge *e; + /* these values will be the same every iteration */ + const int vs_iter_tot = BM_elem_index_get(vs->v); + const int vs_iter_next = vs_iter_tot + dir; + + vs_next = vs->next; + + BM_ITER_ELEM (e, &iter, vs->v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) { + BMVert *v_next = BM_edge_other_vert(e, vs->v); + const int v_next_index = BM_elem_index_get(v_next); + /* not essential to clear flag but prevents more checking next time round */ + BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); + if (v_next_index == 0) { + vs_add(vs_pool, &lb_tmp, v_next, e, vs_iter_next); + } + else if ((dir < 0) == (v_next_index < 0)) { + /* on the same side - do nothing */ + } + else { + /* we have met out match! (vertices from different sides meet) */ + if (dir == 1) { + v_match[0] = vs->v; + v_match[1] = v_next; + } + else { + v_match[0] = v_next; + v_match[1] = vs->v; + } + /* normally we would manage memory of remaining items in (lb, lb_tmp), + * but search is done, vs_pool will get destroyed immediately */ + return true; + } + } + } + + BLI_mempool_free(vs_pool, vs); + } + /* bm->elem_index_dirty |= BM_VERT; */ /* Commented because used in a loop, and this flag has already been set. */ + + /* lb is now full of free'd items, overwrite */ + *lb = lb_tmp; + + return (BLI_listbase_is_empty(lb) == false); } -bool BM_mesh_edgeloops_find_path( - BMesh *bm, ListBase *r_eloops, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data, - BMVert *v_src, BMVert *v_dst) +bool BM_mesh_edgeloops_find_path(BMesh *bm, + ListBase *r_eloops, + bool (*test_fn)(BMEdge *, void *user_data), + void *user_data, + BMVert *v_src, + BMVert *v_dst) { - BMIter iter; - BMEdge *e; - bool found = false; - - BLI_assert(v_src != v_dst); - - { - BMVert *v; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BM_elem_index_set(v, 0); - BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG); - } - } - bm->elem_index_dirty |= BM_VERT; - - /* first flush edges to tags, and tag verts */ - int edges_len; - BMEdge **edges; - - if (test_fn) { - BLI_Stack *edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__); - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (test_fn(e, user_data)) { - BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG); - BLI_stack_push(edge_stack, (void *)&e); - } - else { - BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); - } - } - edges_len = BLI_stack_count(edge_stack); - edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__); - BLI_stack_pop_n_reverse(edge_stack, edges, BLI_stack_count(edge_stack)); - BLI_stack_free(edge_stack); - } - else { - int i = 0; - edges_len = bm->totedge; - edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__); - - BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { - BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG); - edges[i] = e; - } - } - - /* prime the lists and begin search */ - { - BMVert *v_match[2] = {NULL, NULL}; - ListBase lb_src = {NULL, NULL}; - ListBase lb_dst = {NULL, NULL}; - BLI_mempool *vs_pool = BLI_mempool_create(sizeof(struct VertStep), 0, 512, BLI_MEMPOOL_NOP); - - /* edge args are dummy */ - vs_add(vs_pool, &lb_src, v_src, v_src->e, 1); - vs_add(vs_pool, &lb_dst, v_dst, v_dst->e, -1); - bm->elem_index_dirty |= BM_VERT; - - do { - if ((bm_loop_path_build_step(vs_pool, &lb_src, 1, v_match) == false) || v_match[0]) { - break; - } - if ((bm_loop_path_build_step(vs_pool, &lb_dst, -1, v_match) == false) || v_match[0]) { - break; - } - } while (true); - - BLI_mempool_destroy(vs_pool); - - if (v_match[0]) { - BMEdgeLoopStore *el_store = MEM_callocN(sizeof(BMEdgeLoopStore), __func__); - BMVert *v; - - /* build loop from edge pointers */ - v = v_match[0]; - while (true) { - LinkData *node = MEM_callocN(sizeof(*node), __func__); - node->data = v; - BLI_addhead(&el_store->verts, node); - el_store->len++; - if (v == v_src) { - break; - } - v = BM_edge_other_vert(v->e, v); - } - - v = v_match[1]; - while (true) { - LinkData *node = MEM_callocN(sizeof(*node), __func__); - node->data = v; - BLI_addtail(&el_store->verts, node); - el_store->len++; - if (v == v_dst) { - break; - } - v = BM_edge_other_vert(v->e, v); - } - - - BLI_addtail(r_eloops, el_store); - - found = true; - } - } - - for (uint i = 0; i < edges_len; i += 1) { - e = edges[i]; - BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_disable(e->v1, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_disable(e->v2, BM_ELEM_INTERNAL_TAG); - } - MEM_freeN(edges); - - return found; + BMIter iter; + BMEdge *e; + bool found = false; + + BLI_assert(v_src != v_dst); + + { + BMVert *v; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_elem_index_set(v, 0); + BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG); + } + } + bm->elem_index_dirty |= BM_VERT; + + /* first flush edges to tags, and tag verts */ + int edges_len; + BMEdge **edges; + + if (test_fn) { + BLI_Stack *edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__); + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (test_fn(e, user_data)) { + BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG); + BLI_stack_push(edge_stack, (void *)&e); + } + else { + BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); + } + } + edges_len = BLI_stack_count(edge_stack); + edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__); + BLI_stack_pop_n_reverse(edge_stack, edges, BLI_stack_count(edge_stack)); + BLI_stack_free(edge_stack); + } + else { + int i = 0; + edges_len = bm->totedge; + edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__); + + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG); + edges[i] = e; + } + } + + /* prime the lists and begin search */ + { + BMVert *v_match[2] = {NULL, NULL}; + ListBase lb_src = {NULL, NULL}; + ListBase lb_dst = {NULL, NULL}; + BLI_mempool *vs_pool = BLI_mempool_create(sizeof(struct VertStep), 0, 512, BLI_MEMPOOL_NOP); + + /* edge args are dummy */ + vs_add(vs_pool, &lb_src, v_src, v_src->e, 1); + vs_add(vs_pool, &lb_dst, v_dst, v_dst->e, -1); + bm->elem_index_dirty |= BM_VERT; + + do { + if ((bm_loop_path_build_step(vs_pool, &lb_src, 1, v_match) == false) || v_match[0]) { + break; + } + if ((bm_loop_path_build_step(vs_pool, &lb_dst, -1, v_match) == false) || v_match[0]) { + break; + } + } while (true); + + BLI_mempool_destroy(vs_pool); + + if (v_match[0]) { + BMEdgeLoopStore *el_store = MEM_callocN(sizeof(BMEdgeLoopStore), __func__); + BMVert *v; + + /* build loop from edge pointers */ + v = v_match[0]; + while (true) { + LinkData *node = MEM_callocN(sizeof(*node), __func__); + node->data = v; + BLI_addhead(&el_store->verts, node); + el_store->len++; + if (v == v_src) { + break; + } + v = BM_edge_other_vert(v->e, v); + } + + v = v_match[1]; + while (true) { + LinkData *node = MEM_callocN(sizeof(*node), __func__); + node->data = v; + BLI_addtail(&el_store->verts, node); + el_store->len++; + if (v == v_dst) { + break; + } + v = BM_edge_other_vert(v->e, v); + } + + BLI_addtail(r_eloops, el_store); + + found = true; + } + } + + for (uint i = 0; i < edges_len; i += 1) { + e = edges[i]; + BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_disable(e->v1, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_disable(e->v2, BM_ELEM_INTERNAL_TAG); + } + MEM_freeN(edges); + + return found; } - /* -------------------------------------------------------------------- */ /* BM_mesh_edgeloops_xxx utility function */ void BM_mesh_edgeloops_free(ListBase *eloops) { - BMEdgeLoopStore *el_store; - while ((el_store = BLI_pophead(eloops))) { - BM_edgeloop_free(el_store); - } + BMEdgeLoopStore *el_store; + while ((el_store = BLI_pophead(eloops))) { + BM_edgeloop_free(el_store); + } } void BM_mesh_edgeloops_calc_center(BMesh *bm, ListBase *eloops) { - BMEdgeLoopStore *el_store; - for (el_store = eloops->first; el_store; el_store = el_store->next) { - BM_edgeloop_calc_center(bm, el_store); - } + BMEdgeLoopStore *el_store; + for (el_store = eloops->first; el_store; el_store = el_store->next) { + BM_edgeloop_calc_center(bm, el_store); + } } void BM_mesh_edgeloops_calc_normal(BMesh *bm, ListBase *eloops) { - BMEdgeLoopStore *el_store; - for (el_store = eloops->first; el_store; el_store = el_store->next) { - BM_edgeloop_calc_normal(bm, el_store); - } + BMEdgeLoopStore *el_store; + for (el_store = eloops->first; el_store; el_store = el_store->next) { + BM_edgeloop_calc_normal(bm, el_store); + } } void BM_mesh_edgeloops_calc_normal_aligned(BMesh *bm, ListBase *eloops, const float no_align[3]) { - BMEdgeLoopStore *el_store; - for (el_store = eloops->first; el_store; el_store = el_store->next) { - BM_edgeloop_calc_normal_aligned(bm, el_store, no_align); - } + BMEdgeLoopStore *el_store; + for (el_store = eloops->first; el_store; el_store = el_store->next) { + BM_edgeloop_calc_normal_aligned(bm, el_store, no_align); + } } void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const bool use_normals) { - ListBase eloops_ordered = {NULL}; - BMEdgeLoopStore *el_store; - float cent[3]; - int tot = 0; - zero_v3(cent); - /* assumes we calculated centers already */ - for (el_store = eloops->first; el_store; el_store = el_store->next, tot++) { - add_v3_v3(cent, el_store->co); - } - mul_v3_fl(cent, 1.0f / (float)tot); - - /* find far outest loop */ - { - BMEdgeLoopStore *el_store_best = NULL; - float len_best_sq = -1.0f; - for (el_store = eloops->first; el_store; el_store = el_store->next) { - const float len_sq = len_squared_v3v3(cent, el_store->co); - if (len_sq > len_best_sq) { - len_best_sq = len_sq; - el_store_best = el_store; - } - } - - BLI_remlink(eloops, el_store_best); - BLI_addtail(&eloops_ordered, el_store_best); - } - - /* not so efficient re-ordering */ - while (eloops->first) { - BMEdgeLoopStore *el_store_best = NULL; - const float *co = ((BMEdgeLoopStore *)eloops_ordered.last)->co; - const float *no = ((BMEdgeLoopStore *)eloops_ordered.last)->no; - float len_best_sq = FLT_MAX; - - if (use_normals) { - BLI_ASSERT_UNIT_V3(no); - } - - for (el_store = eloops->first; el_store; el_store = el_store->next) { - float len_sq; - if (use_normals) { - /* scale the length by how close the loops are to pointing at eachother */ - float dir[3]; - sub_v3_v3v3(dir, co, el_store->co); - len_sq = normalize_v3(dir); - len_sq = len_sq * ((1.0f - fabsf(dot_v3v3(dir, no))) + - (1.0f - fabsf(dot_v3v3(dir, el_store->no)))); - } - else { - len_sq = len_squared_v3v3(co, el_store->co); - } - - if (len_sq < len_best_sq) { - len_best_sq = len_sq; - el_store_best = el_store; - } - } - - BLI_remlink(eloops, el_store_best); - BLI_addtail(&eloops_ordered, el_store_best); - } - - *eloops = eloops_ordered; + ListBase eloops_ordered = {NULL}; + BMEdgeLoopStore *el_store; + float cent[3]; + int tot = 0; + zero_v3(cent); + /* assumes we calculated centers already */ + for (el_store = eloops->first; el_store; el_store = el_store->next, tot++) { + add_v3_v3(cent, el_store->co); + } + mul_v3_fl(cent, 1.0f / (float)tot); + + /* find far outest loop */ + { + BMEdgeLoopStore *el_store_best = NULL; + float len_best_sq = -1.0f; + for (el_store = eloops->first; el_store; el_store = el_store->next) { + const float len_sq = len_squared_v3v3(cent, el_store->co); + if (len_sq > len_best_sq) { + len_best_sq = len_sq; + el_store_best = el_store; + } + } + + BLI_remlink(eloops, el_store_best); + BLI_addtail(&eloops_ordered, el_store_best); + } + + /* not so efficient re-ordering */ + while (eloops->first) { + BMEdgeLoopStore *el_store_best = NULL; + const float *co = ((BMEdgeLoopStore *)eloops_ordered.last)->co; + const float *no = ((BMEdgeLoopStore *)eloops_ordered.last)->no; + float len_best_sq = FLT_MAX; + + if (use_normals) { + BLI_ASSERT_UNIT_V3(no); + } + + for (el_store = eloops->first; el_store; el_store = el_store->next) { + float len_sq; + if (use_normals) { + /* scale the length by how close the loops are to pointing at eachother */ + float dir[3]; + sub_v3_v3v3(dir, co, el_store->co); + len_sq = normalize_v3(dir); + len_sq = len_sq * + ((1.0f - fabsf(dot_v3v3(dir, no))) + (1.0f - fabsf(dot_v3v3(dir, el_store->no)))); + } + else { + len_sq = len_squared_v3v3(co, el_store->co); + } + + if (len_sq < len_best_sq) { + len_best_sq = len_sq; + el_store_best = el_store; + } + } + + BLI_remlink(eloops, el_store_best); + BLI_addtail(&eloops_ordered, el_store_best); + } + + *eloops = eloops_ordered; } /* -------------------------------------------------------------------- */ @@ -508,60 +506,60 @@ void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const boo /* return new edgeloops */ BMEdgeLoopStore *BM_edgeloop_copy(BMEdgeLoopStore *el_store) { - BMEdgeLoopStore *el_store_copy = MEM_mallocN(sizeof(*el_store), __func__); - *el_store_copy = *el_store; - BLI_duplicatelist(&el_store_copy->verts, &el_store->verts); - return el_store_copy; + BMEdgeLoopStore *el_store_copy = MEM_mallocN(sizeof(*el_store), __func__); + *el_store_copy = *el_store; + BLI_duplicatelist(&el_store_copy->verts, &el_store->verts); + return el_store_copy; } BMEdgeLoopStore *BM_edgeloop_from_verts(BMVert **v_arr, const int v_arr_tot, bool is_closed) { - BMEdgeLoopStore *el_store = MEM_callocN(sizeof(*el_store), __func__); - int i; - for (i = 0; i < v_arr_tot; i++) { - LinkData *node = MEM_callocN(sizeof(*node), __func__); - node->data = v_arr[i]; - BLI_addtail(&el_store->verts, node); - } - el_store->len = v_arr_tot; - if (is_closed) { - el_store->flag |= BM_EDGELOOP_IS_CLOSED; - } - return el_store; + BMEdgeLoopStore *el_store = MEM_callocN(sizeof(*el_store), __func__); + int i; + for (i = 0; i < v_arr_tot; i++) { + LinkData *node = MEM_callocN(sizeof(*node), __func__); + node->data = v_arr[i]; + BLI_addtail(&el_store->verts, node); + } + el_store->len = v_arr_tot; + if (is_closed) { + el_store->flag |= BM_EDGELOOP_IS_CLOSED; + } + return el_store; } void BM_edgeloop_free(BMEdgeLoopStore *el_store) { - BLI_freelistN(&el_store->verts); - MEM_freeN(el_store); + BLI_freelistN(&el_store->verts); + MEM_freeN(el_store); } bool BM_edgeloop_is_closed(BMEdgeLoopStore *el_store) { - return (el_store->flag & BM_EDGELOOP_IS_CLOSED) != 0; + return (el_store->flag & BM_EDGELOOP_IS_CLOSED) != 0; } ListBase *BM_edgeloop_verts_get(BMEdgeLoopStore *el_store) { - return &el_store->verts; + return &el_store->verts; } int BM_edgeloop_length_get(BMEdgeLoopStore *el_store) { - return el_store->len; + return el_store->len; } const float *BM_edgeloop_normal_get(struct BMEdgeLoopStore *el_store) { - return el_store->no; + return el_store->no; } const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store) { - return el_store->co; + return el_store->co; } -#define NODE_AS_V(n) ((BMVert *)((LinkData *)n)->data) +#define NODE_AS_V(n) ((BMVert *)((LinkData *)n)->data) #define NODE_AS_CO(n) ((BMVert *)((LinkData *)n)->data)->co /** @@ -569,92 +567,89 @@ const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store) */ void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr) { - LinkData *node; - int i = 0; - for (node = el_store->verts.first; node && node->next; node = node->next) { - e_arr[i++] = BM_edge_exists(NODE_AS_V(node), NODE_AS_V(node->next)); - BLI_assert(e_arr[i - 1] != NULL); - } - - if (el_store->flag & BM_EDGELOOP_IS_CLOSED) { - e_arr[i] = BM_edge_exists(NODE_AS_V(el_store->verts.first), NODE_AS_V(el_store->verts.last)); - BLI_assert(e_arr[i] != NULL); - } - BLI_assert(el_store->len == i + 1); + LinkData *node; + int i = 0; + for (node = el_store->verts.first; node && node->next; node = node->next) { + e_arr[i++] = BM_edge_exists(NODE_AS_V(node), NODE_AS_V(node->next)); + BLI_assert(e_arr[i - 1] != NULL); + } + + if (el_store->flag & BM_EDGELOOP_IS_CLOSED) { + e_arr[i] = BM_edge_exists(NODE_AS_V(el_store->verts.first), NODE_AS_V(el_store->verts.last)); + BLI_assert(e_arr[i] != NULL); + } + BLI_assert(el_store->len == i + 1); } void BM_edgeloop_calc_center(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store) { - LinkData *node_curr = el_store->verts.last; - LinkData *node_prev = ((LinkData *)el_store->verts.last)->prev; - LinkData *node_first = el_store->verts.first; - LinkData *node_next = node_first; - - const float *v_prev = NODE_AS_CO(node_prev); - const float *v_curr = NODE_AS_CO(node_curr); - const float *v_next = NODE_AS_CO(node_next); - - float totw = 0.0f; - float w_prev; - - zero_v3(el_store->co); - - w_prev = len_v3v3(v_prev, v_curr); - do { - const float w_curr = len_v3v3(v_curr, v_next); - const float w = (w_curr + w_prev); - madd_v3_v3fl(el_store->co, v_curr, w); - totw += w; - w_prev = w_curr; - - - node_prev = node_curr; - node_curr = node_next; - node_next = node_next->next; - - if (node_next == NULL) { - break; - } - v_prev = v_curr; - v_curr = v_next; - v_next = NODE_AS_CO(node_next); - } while (1); - - if (totw != 0.0f) { - mul_v3_fl(el_store->co, 1.0f / (float) totw); - } - + LinkData *node_curr = el_store->verts.last; + LinkData *node_prev = ((LinkData *)el_store->verts.last)->prev; + LinkData *node_first = el_store->verts.first; + LinkData *node_next = node_first; + + const float *v_prev = NODE_AS_CO(node_prev); + const float *v_curr = NODE_AS_CO(node_curr); + const float *v_next = NODE_AS_CO(node_next); + + float totw = 0.0f; + float w_prev; + + zero_v3(el_store->co); + + w_prev = len_v3v3(v_prev, v_curr); + do { + const float w_curr = len_v3v3(v_curr, v_next); + const float w = (w_curr + w_prev); + madd_v3_v3fl(el_store->co, v_curr, w); + totw += w; + w_prev = w_curr; + + node_prev = node_curr; + node_curr = node_next; + node_next = node_next->next; + + if (node_next == NULL) { + break; + } + v_prev = v_curr; + v_curr = v_next; + v_next = NODE_AS_CO(node_next); + } while (1); + + if (totw != 0.0f) { + mul_v3_fl(el_store->co, 1.0f / (float)totw); + } } bool BM_edgeloop_calc_normal(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store) { - LinkData *node_curr = el_store->verts.first; - const float *v_prev = NODE_AS_CO(el_store->verts.last); - const float *v_curr = NODE_AS_CO(node_curr); - - zero_v3(el_store->no); - - /* Newell's Method */ - do { - add_newell_cross_v3_v3v3(el_store->no, v_prev, v_curr); - - if ((node_curr = node_curr->next)) { - v_prev = v_curr; - v_curr = NODE_AS_CO(node_curr); - } - else { - break; - } - } while (true); - - if (UNLIKELY(normalize_v3(el_store->no) < EDGELOOP_EPS)) { - el_store->no[2] = 1.0f; /* other axis set to 0.0 */ - return false; - - } - else { - return true; - } + LinkData *node_curr = el_store->verts.first; + const float *v_prev = NODE_AS_CO(el_store->verts.last); + const float *v_curr = NODE_AS_CO(node_curr); + + zero_v3(el_store->no); + + /* Newell's Method */ + do { + add_newell_cross_v3_v3v3(el_store->no, v_prev, v_curr); + + if ((node_curr = node_curr->next)) { + v_prev = v_curr; + v_curr = NODE_AS_CO(node_curr); + } + else { + break; + } + } while (true); + + if (UNLIKELY(normalize_v3(el_store->no) < EDGELOOP_EPS)) { + el_store->no[2] = 1.0f; /* other axis set to 0.0 */ + return false; + } + else { + return true; + } } /** @@ -663,159 +658,164 @@ bool BM_edgeloop_calc_normal(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store) * * Instead use an alignment vector and calculate the normal based on that. */ -bool BM_edgeloop_calc_normal_aligned(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store, const float no_align[3]) +bool BM_edgeloop_calc_normal_aligned(BMesh *UNUSED(bm), + BMEdgeLoopStore *el_store, + const float no_align[3]) { - LinkData *node_curr = el_store->verts.first; - const float *v_prev = NODE_AS_CO(el_store->verts.last); - const float *v_curr = NODE_AS_CO(node_curr); - - zero_v3(el_store->no); - - /* Own Method */ - do { - float cross[3], no[3], dir[3]; - sub_v3_v3v3(dir, v_curr, v_prev); - cross_v3_v3v3(cross, no_align, dir); - cross_v3_v3v3(no, dir, cross); - add_v3_v3(el_store->no, no); - - if ((node_curr = node_curr->next)) { - v_prev = v_curr; - v_curr = NODE_AS_CO(node_curr); - } - else { - break; - } - } while (true); - - if (UNLIKELY(normalize_v3(el_store->no) < EDGELOOP_EPS)) { - el_store->no[2] = 1.0f; /* other axis set to 0.0 */ - return false; - } - else { - return true; - } + LinkData *node_curr = el_store->verts.first; + const float *v_prev = NODE_AS_CO(el_store->verts.last); + const float *v_curr = NODE_AS_CO(node_curr); + + zero_v3(el_store->no); + + /* Own Method */ + do { + float cross[3], no[3], dir[3]; + sub_v3_v3v3(dir, v_curr, v_prev); + cross_v3_v3v3(cross, no_align, dir); + cross_v3_v3v3(no, dir, cross); + add_v3_v3(el_store->no, no); + + if ((node_curr = node_curr->next)) { + v_prev = v_curr; + v_curr = NODE_AS_CO(node_curr); + } + else { + break; + } + } while (true); + + if (UNLIKELY(normalize_v3(el_store->no) < EDGELOOP_EPS)) { + el_store->no[2] = 1.0f; /* other axis set to 0.0 */ + return false; + } + else { + return true; + } } - - void BM_edgeloop_flip(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store) { - negate_v3(el_store->no); - BLI_listbase_reverse(&el_store->verts); + negate_v3(el_store->no); + BLI_listbase_reverse(&el_store->verts); } void BM_edgeloop_expand( - BMesh *bm, BMEdgeLoopStore *el_store, int el_store_len, - bool split, GSet *split_edges) + BMesh *bm, BMEdgeLoopStore *el_store, int el_store_len, bool split, GSet *split_edges) { - bool split_swap = true; - -#define EDGE_SPLIT(node_copy, node_other) { \ - BMVert *v_split, *v_other = (node_other)->data; \ - BMEdge *e_split, *e_other = BM_edge_exists((node_copy)->data, v_other); \ - v_split = BM_edge_split(bm, e_other, split_swap ? (node_copy)->data : v_other, &e_split, 0.0f); \ - v_split->e = e_split; \ - BLI_assert(v_split == e_split->v2); \ - BLI_gset_insert(split_edges, e_split); \ - (node_copy)->data = v_split; \ - } ((void)0) - - /* first double until we are more than half as big */ - while ((el_store->len * 2) < el_store_len) { - LinkData *node_curr = el_store->verts.first; - while (node_curr) { - LinkData *node_curr_copy = MEM_dupallocN(node_curr); - if (split == false) { - BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy); - node_curr = node_curr_copy->next; - } - else { - if (node_curr->next || (el_store->flag & BM_EDGELOOP_IS_CLOSED)) { - EDGE_SPLIT(node_curr_copy, node_curr->next ? node_curr->next : (LinkData *)el_store->verts.first); - BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy); - node_curr = node_curr_copy->next; - } - else { - EDGE_SPLIT(node_curr_copy, node_curr->prev); - BLI_insertlinkbefore(&el_store->verts, node_curr, node_curr_copy); - node_curr = node_curr->next; - } - split_swap = !split_swap; - } - el_store->len++; - } - split_swap = !split_swap; - } - - if (el_store->len < el_store_len) { - LinkData *node_curr = el_store->verts.first; - - int iter_prev = 0; - BLI_FOREACH_SPARSE_RANGE(el_store->len, (el_store_len - el_store->len), iter) { - while (iter_prev < iter) { - node_curr = node_curr->next; - iter_prev += 1; - } - - LinkData *node_curr_copy; - node_curr_copy = MEM_dupallocN(node_curr); - if (split == false) { - BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy); - node_curr = node_curr_copy->next; - } - else { - if (node_curr->next || (el_store->flag & BM_EDGELOOP_IS_CLOSED)) { - EDGE_SPLIT(node_curr_copy, - node_curr->next ? node_curr->next : (LinkData *)el_store->verts.first); - BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy); - node_curr = node_curr_copy->next; - } - else { - EDGE_SPLIT(node_curr_copy, node_curr->prev); - BLI_insertlinkbefore(&el_store->verts, node_curr, node_curr_copy); - node_curr = node_curr->next; - } - split_swap = !split_swap; - } - el_store->len++; - iter_prev += 1; - } - } + bool split_swap = true; + +#define EDGE_SPLIT(node_copy, node_other) \ + { \ + BMVert *v_split, *v_other = (node_other)->data; \ + BMEdge *e_split, *e_other = BM_edge_exists((node_copy)->data, v_other); \ + v_split = BM_edge_split( \ + bm, e_other, split_swap ? (node_copy)->data : v_other, &e_split, 0.0f); \ + v_split->e = e_split; \ + BLI_assert(v_split == e_split->v2); \ + BLI_gset_insert(split_edges, e_split); \ + (node_copy)->data = v_split; \ + } \ + ((void)0) + + /* first double until we are more than half as big */ + while ((el_store->len * 2) < el_store_len) { + LinkData *node_curr = el_store->verts.first; + while (node_curr) { + LinkData *node_curr_copy = MEM_dupallocN(node_curr); + if (split == false) { + BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy); + node_curr = node_curr_copy->next; + } + else { + if (node_curr->next || (el_store->flag & BM_EDGELOOP_IS_CLOSED)) { + EDGE_SPLIT(node_curr_copy, + node_curr->next ? node_curr->next : (LinkData *)el_store->verts.first); + BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy); + node_curr = node_curr_copy->next; + } + else { + EDGE_SPLIT(node_curr_copy, node_curr->prev); + BLI_insertlinkbefore(&el_store->verts, node_curr, node_curr_copy); + node_curr = node_curr->next; + } + split_swap = !split_swap; + } + el_store->len++; + } + split_swap = !split_swap; + } + + if (el_store->len < el_store_len) { + LinkData *node_curr = el_store->verts.first; + + int iter_prev = 0; + BLI_FOREACH_SPARSE_RANGE(el_store->len, (el_store_len - el_store->len), iter) + { + while (iter_prev < iter) { + node_curr = node_curr->next; + iter_prev += 1; + } + + LinkData *node_curr_copy; + node_curr_copy = MEM_dupallocN(node_curr); + if (split == false) { + BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy); + node_curr = node_curr_copy->next; + } + else { + if (node_curr->next || (el_store->flag & BM_EDGELOOP_IS_CLOSED)) { + EDGE_SPLIT(node_curr_copy, + node_curr->next ? node_curr->next : (LinkData *)el_store->verts.first); + BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy); + node_curr = node_curr_copy->next; + } + else { + EDGE_SPLIT(node_curr_copy, node_curr->prev); + BLI_insertlinkbefore(&el_store->verts, node_curr, node_curr_copy); + node_curr = node_curr->next; + } + split_swap = !split_swap; + } + el_store->len++; + iter_prev += 1; + } + } #undef BKE_FOREACH_SUBSET_OF_RANGE #undef EDGE_SPLIT - BLI_assert(el_store->len == el_store_len); + BLI_assert(el_store->len == el_store_len); } -bool BM_edgeloop_overlap_check(struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b) +bool BM_edgeloop_overlap_check(struct BMEdgeLoopStore *el_store_a, + struct BMEdgeLoopStore *el_store_b) { - LinkData *node; - - /* A little more efficient if 'a' as smaller. */ - if (el_store_a->len > el_store_b->len) { - SWAP(BMEdgeLoopStore *, el_store_a, el_store_b); - } - - /* init */ - for (node = el_store_a->verts.first; node; node = node->next) { - BM_elem_flag_enable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG); - } - for (node = el_store_b->verts.first; node; node = node->next) { - BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG); - } - - /* Check 'a' (clear as we go). */ - for (node = el_store_a->verts.first; node; node = node->next) { - if (!BM_elem_flag_test((BMVert *)node->data, BM_ELEM_INTERNAL_TAG)) { - /* Finish clearing 'a', leave tag clean. */ - while ((node = node->next)) { - BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG); - } - return true; - } - BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG); - } - return false; + LinkData *node; + + /* A little more efficient if 'a' as smaller. */ + if (el_store_a->len > el_store_b->len) { + SWAP(BMEdgeLoopStore *, el_store_a, el_store_b); + } + + /* init */ + for (node = el_store_a->verts.first; node; node = node->next) { + BM_elem_flag_enable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG); + } + for (node = el_store_b->verts.first; node; node = node->next) { + BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG); + } + + /* Check 'a' (clear as we go). */ + for (node = el_store_a->verts.first; node; node = node->next) { + if (!BM_elem_flag_test((BMVert *)node->data, BM_ELEM_INTERNAL_TAG)) { + /* Finish clearing 'a', leave tag clean. */ + while ((node = node->next)) { + BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG); + } + return true; + } + BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG); + } + return false; } diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.h b/source/blender/bmesh/intern/bmesh_edgeloop.h index e21a62bc25f..7701c680ae9 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.h +++ b/source/blender/bmesh/intern/bmesh_edgeloop.h @@ -29,51 +29,60 @@ struct GSet; struct ListBase; /* multiple edgeloops (ListBase) */ -int BM_mesh_edgeloops_find( - BMesh *bm, struct ListBase *r_lb, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data); -bool BM_mesh_edgeloops_find_path( - BMesh *bm, ListBase *r_eloops, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data, - BMVert *v_src, BMVert *v_dst); - -void BM_mesh_edgeloops_free(struct ListBase *eloops); -void BM_mesh_edgeloops_calc_center(BMesh *bm, struct ListBase *eloops); -void BM_mesh_edgeloops_calc_normal(BMesh *bm, struct ListBase *eloops); -void BM_mesh_edgeloops_calc_normal_aligned( - BMesh *bm, struct ListBase *eloops, - const float no_align[3]); -void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const bool use_normals); +int BM_mesh_edgeloops_find(BMesh *bm, + struct ListBase *r_lb, + bool (*test_fn)(BMEdge *, void *user_data), + void *user_data); +bool BM_mesh_edgeloops_find_path(BMesh *bm, + ListBase *r_eloops, + bool (*test_fn)(BMEdge *, void *user_data), + void *user_data, + BMVert *v_src, + BMVert *v_dst); +void BM_mesh_edgeloops_free(struct ListBase *eloops); +void BM_mesh_edgeloops_calc_center(BMesh *bm, struct ListBase *eloops); +void BM_mesh_edgeloops_calc_normal(BMesh *bm, struct ListBase *eloops); +void BM_mesh_edgeloops_calc_normal_aligned(BMesh *bm, + struct ListBase *eloops, + const float no_align[3]); +void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const bool use_normals); /* single edgeloop */ struct BMEdgeLoopStore *BM_edgeloop_copy(struct BMEdgeLoopStore *el_store); -struct BMEdgeLoopStore *BM_edgeloop_from_verts(BMVert **v_arr, const int v_arr_tot, bool is_closed); +struct BMEdgeLoopStore *BM_edgeloop_from_verts(BMVert **v_arr, + const int v_arr_tot, + bool is_closed); -void BM_edgeloop_free(struct BMEdgeLoopStore *el_store); -bool BM_edgeloop_is_closed(struct BMEdgeLoopStore *el_store); -int BM_edgeloop_length_get(struct BMEdgeLoopStore *el_store); -struct ListBase *BM_edgeloop_verts_get(struct BMEdgeLoopStore *el_store); -const float *BM_edgeloop_normal_get(struct BMEdgeLoopStore *el_store); -const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store); -void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr); -void BM_edgeloop_calc_center(BMesh *bm, struct BMEdgeLoopStore *el_store); -bool BM_edgeloop_calc_normal(BMesh *bm, struct BMEdgeLoopStore *el_store); -bool BM_edgeloop_calc_normal_aligned( - BMesh *bm, struct BMEdgeLoopStore *el_store, - const float no_align[3]); -void BM_edgeloop_flip(BMesh *bm, struct BMEdgeLoopStore *el_store); -void BM_edgeloop_expand( - BMesh *bm, struct BMEdgeLoopStore *el_store, int el_store_len, - bool split, struct GSet *split_edges); +void BM_edgeloop_free(struct BMEdgeLoopStore *el_store); +bool BM_edgeloop_is_closed(struct BMEdgeLoopStore *el_store); +int BM_edgeloop_length_get(struct BMEdgeLoopStore *el_store); +struct ListBase *BM_edgeloop_verts_get(struct BMEdgeLoopStore *el_store); +const float *BM_edgeloop_normal_get(struct BMEdgeLoopStore *el_store); +const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store); +void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr); +void BM_edgeloop_calc_center(BMesh *bm, struct BMEdgeLoopStore *el_store); +bool BM_edgeloop_calc_normal(BMesh *bm, struct BMEdgeLoopStore *el_store); +bool BM_edgeloop_calc_normal_aligned(BMesh *bm, + struct BMEdgeLoopStore *el_store, + const float no_align[3]); +void BM_edgeloop_flip(BMesh *bm, struct BMEdgeLoopStore *el_store); +void BM_edgeloop_expand(BMesh *bm, + struct BMEdgeLoopStore *el_store, + int el_store_len, + bool split, + struct GSet *split_edges); -bool BM_edgeloop_overlap_check(struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b); +bool BM_edgeloop_overlap_check(struct BMEdgeLoopStore *el_store_a, + struct BMEdgeLoopStore *el_store_b); #define BM_EDGELINK_NEXT(el_store, elink) \ - (elink)->next ? elink->next : (BM_edgeloop_is_closed(el_store) ? BM_edgeloop_verts_get(el_store)->first : NULL) + (elink)->next ? \ + elink->next : \ + (BM_edgeloop_is_closed(el_store) ? BM_edgeloop_verts_get(el_store)->first : NULL) #define BM_EDGELOOP_NEXT(el_store) \ - (CHECK_TYPE_INLINE(el_store, struct BMEdgeLoopStore *), \ - (struct BMEdgeLoopStore *)((LinkData *)el_store)->next) + (CHECK_TYPE_INLINE(el_store, struct BMEdgeLoopStore *), \ + (struct BMEdgeLoopStore *)((LinkData *)el_store)->next) -#endif /* __BMESH_EDGELOOP_H__ */ +#endif /* __BMESH_EDGELOOP_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_error.h b/source/blender/bmesh/intern/bmesh_error.h index 0035a43dc1e..b5235c64215 100644 --- a/source/blender/bmesh/intern/bmesh_error.h +++ b/source/blender/bmesh/intern/bmesh_error.h @@ -29,11 +29,11 @@ void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg) /* gets the topmost error from the stack. * returns error code or 0 if no error.*/ -int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op); +int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op); bool BMO_error_occurred(BMesh *bm); /* same as geterror, only pops the error off the stack as well */ -int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op); +int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op); void BMO_error_clear(BMesh *bm); /* this is meant for handling errors, like self-intersection test failures. @@ -48,24 +48,24 @@ void BMO_error_clear(BMesh *bm); */ #define BM_ELEM_INDEX_VALIDATE(_bm, _msg_a, _msg_b) \ - BM_mesh_elem_index_validate(_bm, __FILE__ ":" STRINGIFY(__LINE__), __func__, _msg_a, _msg_b) + BM_mesh_elem_index_validate(_bm, __FILE__ ":" STRINGIFY(__LINE__), __func__, _msg_a, _msg_b) /*------ error code defines -------*/ /*error messages*/ enum { - BMERR_SELF_INTERSECTING = 1, - BMERR_DISSOLVEDISK_FAILED, - BMERR_CONNECTVERT_FAILED, - BMERR_WALKER_FAILED, - BMERR_DISSOLVEFACES_FAILED, - BMERR_TESSELLATION, - BMERR_NONMANIFOLD, - BMERR_INVALID_SELECTION, - BMERR_MESH_ERROR, - BMERR_CONVEX_HULL_FAILED, - - BMERR_TOTAL, + BMERR_SELF_INTERSECTING = 1, + BMERR_DISSOLVEDISK_FAILED, + BMERR_CONNECTVERT_FAILED, + BMERR_WALKER_FAILED, + BMERR_DISSOLVEFACES_FAILED, + BMERR_TESSELLATION, + BMERR_NONMANIFOLD, + BMERR_INVALID_SELECTION, + BMERR_MESH_ERROR, + BMERR_CONVEX_HULL_FAILED, + + BMERR_TOTAL, }; /* BMESH_ASSERT */ @@ -77,13 +77,15 @@ enum { /* this is meant to be higher level then BLI_assert(), * its enabled even when in Release mode*/ -#define BMESH_ASSERT(a) \ - (void)((!(a)) ? ( \ - ( \ - fprintf(stderr, \ - "BMESH_ASSERT failed: %s, %s(), %d at \'%s\'\n", \ - __FILE__, __func__, __LINE__, STRINGIFY(a)), \ - _BMESH_DUMMY_ABORT(), \ - NULL)) : NULL) +#define BMESH_ASSERT(a) \ + (void)((!(a)) ? ((fprintf(stderr, \ + "BMESH_ASSERT failed: %s, %s(), %d at \'%s\'\n", \ + __FILE__, \ + __func__, \ + __LINE__, \ + STRINGIFY(a)), \ + _BMESH_DUMMY_ABORT(), \ + NULL)) : \ + NULL) #endif /* __BMESH_ERROR_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_inline.h b/source/blender/bmesh/intern/bmesh_inline.h index 549fc90fe40..13691776a27 100644 --- a/source/blender/bmesh/intern/bmesh_inline.h +++ b/source/blender/bmesh/intern/bmesh_inline.h @@ -24,66 +24,74 @@ #define __BMESH_INLINE_H__ /* stuff for dealing with header flags */ -#define BM_elem_flag_test( ele, hflag) _bm_elem_flag_test (&(ele)->head, hflag) -#define BM_elem_flag_test_bool(ele, hflag) _bm_elem_flag_test_bool(&(ele)->head, hflag) -#define BM_elem_flag_enable( ele, hflag) _bm_elem_flag_enable (&(ele)->head, hflag) -#define BM_elem_flag_disable( ele, hflag) _bm_elem_flag_disable (&(ele)->head, hflag) -#define BM_elem_flag_set( ele, hflag, val) _bm_elem_flag_set (&(ele)->head, hflag, val) -#define BM_elem_flag_toggle( ele, hflag) _bm_elem_flag_toggle (&(ele)->head, hflag) -#define BM_elem_flag_merge( ele_a, ele_b) _bm_elem_flag_merge (&(ele_a)->head, &(ele_b)->head) -#define BM_elem_flag_merge_ex( ele_a, ele_b, hflag_and)_bm_elem_flag_merge_ex (&(ele_a)->head, &(ele_b)->head, hflag_and) -#define BM_elem_flag_merge_into(ele, ele_a, ele_b)_bm_elem_flag_merge_into (&(ele)->head, &(ele_a)->head, &(ele_b)->head) +#define BM_elem_flag_test(ele, hflag) _bm_elem_flag_test(&(ele)->head, hflag) +#define BM_elem_flag_test_bool(ele, hflag) _bm_elem_flag_test_bool(&(ele)->head, hflag) +#define BM_elem_flag_enable(ele, hflag) _bm_elem_flag_enable(&(ele)->head, hflag) +#define BM_elem_flag_disable(ele, hflag) _bm_elem_flag_disable(&(ele)->head, hflag) +#define BM_elem_flag_set(ele, hflag, val) _bm_elem_flag_set(&(ele)->head, hflag, val) +#define BM_elem_flag_toggle(ele, hflag) _bm_elem_flag_toggle(&(ele)->head, hflag) +#define BM_elem_flag_merge(ele_a, ele_b) _bm_elem_flag_merge(&(ele_a)->head, &(ele_b)->head) +#define BM_elem_flag_merge_ex(ele_a, ele_b, hflag_and) \ + _bm_elem_flag_merge_ex(&(ele_a)->head, &(ele_b)->head, hflag_and) +#define BM_elem_flag_merge_into(ele, ele_a, ele_b) \ + _bm_elem_flag_merge_into(&(ele)->head, &(ele_a)->head, &(ele_b)->head) ATTR_WARN_UNUSED_RESULT BLI_INLINE char _bm_elem_flag_test(const BMHeader *head, const char hflag) { - return head->hflag & hflag; + return head->hflag & hflag; } ATTR_WARN_UNUSED_RESULT BLI_INLINE bool _bm_elem_flag_test_bool(const BMHeader *head, const char hflag) { - return (head->hflag & hflag) != 0; + return (head->hflag & hflag) != 0; } BLI_INLINE void _bm_elem_flag_enable(BMHeader *head, const char hflag) { - head->hflag |= hflag; + head->hflag |= hflag; } BLI_INLINE void _bm_elem_flag_disable(BMHeader *head, const char hflag) { - head->hflag &= (char)~hflag; + head->hflag &= (char)~hflag; } BLI_INLINE void _bm_elem_flag_set(BMHeader *head, const char hflag, const int val) { - if (val) { _bm_elem_flag_enable(head, hflag); } - else { _bm_elem_flag_disable(head, hflag); } + if (val) { + _bm_elem_flag_enable(head, hflag); + } + else { + _bm_elem_flag_disable(head, hflag); + } } BLI_INLINE void _bm_elem_flag_toggle(BMHeader *head, const char hflag) { - head->hflag ^= hflag; + head->hflag ^= hflag; } BLI_INLINE void _bm_elem_flag_merge(BMHeader *head_a, BMHeader *head_b) { - head_a->hflag = head_b->hflag = head_a->hflag | head_b->hflag; + head_a->hflag = head_b->hflag = head_a->hflag | head_b->hflag; } BLI_INLINE void _bm_elem_flag_merge_ex(BMHeader *head_a, BMHeader *head_b, const char hflag_and) { - if (((head_a->hflag & head_b->hflag) & hflag_and) == 0) { - head_a->hflag &= ~hflag_and; - head_b->hflag &= ~hflag_and; - } - _bm_elem_flag_merge(head_a, head_b); + if (((head_a->hflag & head_b->hflag) & hflag_and) == 0) { + head_a->hflag &= ~hflag_and; + head_b->hflag &= ~hflag_and; + } + _bm_elem_flag_merge(head_a, head_b); } -BLI_INLINE void _bm_elem_flag_merge_into(BMHeader *head, const BMHeader *head_a, const BMHeader *head_b) +BLI_INLINE void _bm_elem_flag_merge_into(BMHeader *head, + const BMHeader *head_a, + const BMHeader *head_b) { - head->hflag = head_a->hflag | head_b->hflag; + head->hflag = head_a->hflag | head_b->hflag; } /** @@ -114,18 +122,18 @@ BLI_INLINE void _bm_elem_flag_merge_into(BMHeader *head, const BMHeader *head_a, * * - campbell */ -#define BM_elem_index_get(ele) _bm_elem_index_get(&(ele)->head) -#define BM_elem_index_set(ele, index) _bm_elem_index_set(&(ele)->head, index) +#define BM_elem_index_get(ele) _bm_elem_index_get(&(ele)->head) +#define BM_elem_index_set(ele, index) _bm_elem_index_set(&(ele)->head, index) BLI_INLINE void _bm_elem_index_set(BMHeader *head, const int index) { - head->index = index; + head->index = index; } ATTR_WARN_UNUSED_RESULT BLI_INLINE int _bm_elem_index_get(const BMHeader *head) { - return head->index; + return head->index; } #endif /* __BMESH_INLINE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 11d6df430c3..c58521297dd 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -40,41 +40,45 @@ #include "intern/bmesh_private.h" /* edge and vertex share, currently theres no need to have different logic */ -static void bm_data_interp_from_elem( - CustomData *data_layer, const BMElem *ele_src_1, const BMElem *ele_src_2, - BMElem *ele_dst, const float fac) +static void bm_data_interp_from_elem(CustomData *data_layer, + const BMElem *ele_src_1, + const BMElem *ele_src_2, + BMElem *ele_dst, + const float fac) { - if (ele_src_1->head.data && ele_src_2->head.data) { - /* first see if we can avoid interpolation */ - if (fac <= 0.0f) { - if (ele_src_1 == ele_dst) { - /* do nothing */ - } - else { - CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data); - CustomData_bmesh_copy_data(data_layer, data_layer, ele_src_1->head.data, &ele_dst->head.data); - } - } - else if (fac >= 1.0f) { - if (ele_src_2 == ele_dst) { - /* do nothing */ - } - else { - CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data); - CustomData_bmesh_copy_data(data_layer, data_layer, ele_src_2->head.data, &ele_dst->head.data); - } - } - else { - const void *src[2]; - float w[2]; - - src[0] = ele_src_1->head.data; - src[1] = ele_src_2->head.data; - w[0] = 1.0f - fac; - w[1] = fac; - CustomData_bmesh_interp(data_layer, src, w, NULL, 2, ele_dst->head.data); - } - } + if (ele_src_1->head.data && ele_src_2->head.data) { + /* first see if we can avoid interpolation */ + if (fac <= 0.0f) { + if (ele_src_1 == ele_dst) { + /* do nothing */ + } + else { + CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data); + CustomData_bmesh_copy_data( + data_layer, data_layer, ele_src_1->head.data, &ele_dst->head.data); + } + } + else if (fac >= 1.0f) { + if (ele_src_2 == ele_dst) { + /* do nothing */ + } + else { + CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data); + CustomData_bmesh_copy_data( + data_layer, data_layer, ele_src_2->head.data, &ele_dst->head.data); + } + } + else { + const void *src[2]; + float w[2]; + + src[0] = ele_src_1->head.data; + src[1] = ele_src_2->head.data; + w[0] = 1.0f - fac; + w[1] = fac; + CustomData_bmesh_interp(data_layer, src, w, NULL, 2, ele_dst->head.data); + } + } } /** @@ -84,9 +88,11 @@ static void bm_data_interp_from_elem( * * \note This is an exact match to #BM_data_interp_from_edges */ -void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac) +void BM_data_interp_from_verts( + BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac) { - bm_data_interp_from_elem(&bm->vdata, (const BMElem *)v_src_1, (const BMElem *)v_src_2, (BMElem *)v_dst, fac); + bm_data_interp_from_elem( + &bm->vdata, (const BMElem *)v_src_1, (const BMElem *)v_src_2, (BMElem *)v_dst, fac); } /** @@ -96,9 +102,11 @@ void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v * * \note This is an exact match to #BM_data_interp_from_verts */ -void BM_data_interp_from_edges(BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac) +void BM_data_interp_from_edges( + BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac) { - bm_data_interp_from_elem(&bm->edata, (const BMElem *)e_src_1, (const BMElem *)e_src_2, (BMElem *)e_dst, fac); + bm_data_interp_from_elem( + &bm->edata, (const BMElem *)e_src_1, (const BMElem *)e_src_2, (BMElem *)e_dst, fac); } /** @@ -109,7 +117,7 @@ void BM_data_interp_from_edges(BMesh *bm, const BMEdge *e_src_1, const BMEdge *e */ static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh *UNUSED(bm), BMFace *UNUSED(f)) { - // BMIter iter; + // BMIter iter; } /** @@ -118,44 +126,48 @@ static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh *UNUSED(bm), BMFace *UNU * Walks around the faces of \a e and interpolates * the loop data between two sources. */ -void BM_data_interp_face_vert_edge( - BMesh *bm, const BMVert *v_src_1, const BMVert *UNUSED(v_src_2), BMVert *v, BMEdge *e, const float fac) +void BM_data_interp_face_vert_edge(BMesh *bm, + const BMVert *v_src_1, + const BMVert *UNUSED(v_src_2), + BMVert *v, + BMEdge *e, + const float fac) { - float w[2]; - BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL; - BMLoop *l_iter = NULL; - - if (!e->l) { - return; - } - - w[1] = 1.0f - fac; - w[0] = fac; - - l_iter = e->l; - do { - if (l_iter->v == v_src_1) { - l_v1 = l_iter; - l_v = l_v1->next; - l_v2 = l_v->next; - } - else if (l_iter->v == v) { - l_v1 = l_iter->next; - l_v = l_iter; - l_v2 = l_iter->prev; - } - - if (!l_v1 || !l_v2) { - return; - } - else { - const void *src[2]; - src[0] = l_v1->head.data; - src[1] = l_v2->head.data; - - CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data); - } - } while ((l_iter = l_iter->radial_next) != e->l); + float w[2]; + BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL; + BMLoop *l_iter = NULL; + + if (!e->l) { + return; + } + + w[1] = 1.0f - fac; + w[0] = fac; + + l_iter = e->l; + do { + if (l_iter->v == v_src_1) { + l_v1 = l_iter; + l_v = l_v1->next; + l_v2 = l_v->next; + } + else if (l_iter->v == v) { + l_v1 = l_iter->next; + l_v = l_iter; + l_v2 = l_iter->prev; + } + + if (!l_v1 || !l_v2) { + return; + } + else { + const void *src[2]; + src[0] = l_v1->head.data; + src[1] = l_v2->head.data; + + CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data); + } + } while ((l_iter = l_iter->radial_next) != e->l); } /** @@ -166,61 +178,65 @@ void BM_data_interp_face_vert_edge( * * \note Only handles loop customdata. multires is handled. */ -void BM_face_interp_from_face_ex( - BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex, - const void **blocks_l, const void **blocks_v, float (*cos_2d)[2], float axis_mat[3][3]) +void BM_face_interp_from_face_ex(BMesh *bm, + BMFace *f_dst, + const BMFace *f_src, + const bool do_vertex, + const void **blocks_l, + const void **blocks_v, + float (*cos_2d)[2], + float axis_mat[3][3]) { - BMLoop *l_iter; - BMLoop *l_first; - - float *w = BLI_array_alloca(w, f_src->len); - float co[2]; - int i; - - if (f_src != f_dst) { - BM_elem_attrs_copy(bm, bm, f_src, f_dst); - } - - /* interpolate */ - i = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst); - do { - mul_v2_m3v3(co, axis_mat, l_iter->v->co); - interp_weights_poly_v2(w, cos_2d, f_src->len, co); - CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, f_src->len, l_iter->head.data); - if (do_vertex) { - CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data); - } - } while ((void)i++, (l_iter = l_iter->next) != l_first); + BMLoop *l_iter; + BMLoop *l_first; + + float *w = BLI_array_alloca(w, f_src->len); + float co[2]; + int i; + + if (f_src != f_dst) { + BM_elem_attrs_copy(bm, bm, f_src, f_dst); + } + + /* interpolate */ + i = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst); + do { + mul_v2_m3v3(co, axis_mat, l_iter->v->co); + interp_weights_poly_v2(w, cos_2d, f_src->len, co); + CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, f_src->len, l_iter->head.data); + if (do_vertex) { + CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data); + } + } while ((void)i++, (l_iter = l_iter->next) != l_first); } void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex) { - BMLoop *l_iter; - BMLoop *l_first; - - const void **blocks_l = BLI_array_alloca(blocks_l, f_src->len); - const void **blocks_v = do_vertex ? BLI_array_alloca(blocks_v, f_src->len) : NULL; - float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len); - float axis_mat[3][3]; /* use normal to transform into 2d xy coords */ - int i; - - /* convert the 3d coords into 2d for projection */ - BLI_assert(BM_face_is_normal_valid(f_src)); - axis_dominant_v3_to_m3(axis_mat, f_src->no); - - i = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f_src); - do { - mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); - blocks_l[i] = l_iter->head.data; - if (do_vertex) { - blocks_v[i] = l_iter->v->head.data; - } - } while ((void)i++, (l_iter = l_iter->next) != l_first); - - BM_face_interp_from_face_ex(bm, f_dst, f_src, do_vertex, - blocks_l, blocks_v, cos_2d, axis_mat); + BMLoop *l_iter; + BMLoop *l_first; + + const void **blocks_l = BLI_array_alloca(blocks_l, f_src->len); + const void **blocks_v = do_vertex ? BLI_array_alloca(blocks_v, f_src->len) : NULL; + float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len); + float axis_mat[3][3]; /* use normal to transform into 2d xy coords */ + int i; + + /* convert the 3d coords into 2d for projection */ + BLI_assert(BM_face_is_normal_valid(f_src)); + axis_dominant_v3_to_m3(axis_mat, f_src->no); + + i = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(f_src); + do { + mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); + blocks_l[i] = l_iter->head.data; + if (do_vertex) { + blocks_v[i] = l_iter->v->head.data; + } + } while ((void)i++, (l_iter = l_iter->next) != l_first); + + BM_face_interp_from_face_ex(bm, f_dst, f_src, do_vertex, blocks_l, blocks_v, cos_2d, axis_mat); } /** @@ -237,283 +253,318 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, con * y * </pre> */ -static int compute_mdisp_quad( - const BMLoop *l, const float l_f_center[3], - float v1[3], float v2[3], float v3[3], float v4[3], - float e1[3], float e2[3]) +static int compute_mdisp_quad(const BMLoop *l, + const float l_f_center[3], + float v1[3], + float v2[3], + float v3[3], + float v4[3], + float e1[3], + float e2[3]) { - float n[3], p[3]; + float n[3], p[3]; #ifndef NDEBUG - { - float cent[3]; - /* computer center */ - BM_face_calc_center_median(l->f, cent); - BLI_assert(equals_v3v3(cent, l_f_center)); - } + { + float cent[3]; + /* computer center */ + BM_face_calc_center_median(l->f, cent); + BLI_assert(equals_v3v3(cent, l_f_center)); + } #endif - mid_v3_v3v3(p, l->prev->v->co, l->v->co); - mid_v3_v3v3(n, l->next->v->co, l->v->co); + mid_v3_v3v3(p, l->prev->v->co, l->v->co); + mid_v3_v3v3(n, l->next->v->co, l->v->co); - copy_v3_v3(v1, l_f_center); - copy_v3_v3(v2, p); - copy_v3_v3(v3, l->v->co); - copy_v3_v3(v4, n); + copy_v3_v3(v1, l_f_center); + copy_v3_v3(v2, p); + copy_v3_v3(v3, l->v->co); + copy_v3_v3(v4, n); - sub_v3_v3v3(e1, v2, v1); - sub_v3_v3v3(e2, v3, v4); + sub_v3_v3v3(e1, v2, v1); + sub_v3_v3v3(e2, v3, v4); - return 1; + return 1; } -static bool quad_co( - const float v1[3], const float v2[3], const float v3[3], const float v4[3], - const float p[3], const float n[3], - float r_uv[2]) +static bool quad_co(const float v1[3], + const float v2[3], + const float v3[3], + const float v4[3], + const float p[3], + const float n[3], + float r_uv[2]) { - float projverts[5][3], n2[3]; - float origin[2] = {0.0f, 0.0f}; - int i; + float projverts[5][3], n2[3]; + float origin[2] = {0.0f, 0.0f}; + int i; - /* project points into 2d along normal */ - copy_v3_v3(projverts[0], v1); - copy_v3_v3(projverts[1], v2); - copy_v3_v3(projverts[2], v3); - copy_v3_v3(projverts[3], v4); - copy_v3_v3(projverts[4], p); + /* project points into 2d along normal */ + copy_v3_v3(projverts[0], v1); + copy_v3_v3(projverts[1], v2); + copy_v3_v3(projverts[2], v3); + copy_v3_v3(projverts[3], v4); + copy_v3_v3(projverts[4], p); - normal_quad_v3(n2, projverts[0], projverts[1], projverts[2], projverts[3]); + normal_quad_v3(n2, projverts[0], projverts[1], projverts[2], projverts[3]); - if (dot_v3v3(n, n2) < -FLT_EPSILON) { - return false; - } + if (dot_v3v3(n, n2) < -FLT_EPSILON) { + return false; + } - /* rotate */ - poly_rotate_plane(n, projverts, 5); + /* rotate */ + poly_rotate_plane(n, projverts, 5); - /* subtract origin */ - for (i = 0; i < 4; i++) { - sub_v2_v2(projverts[i], projverts[4]); - } + /* subtract origin */ + for (i = 0; i < 4; i++) { + sub_v2_v2(projverts[i], projverts[4]); + } - if (!isect_point_quad_v2(origin, projverts[0], projverts[1], projverts[2], projverts[3])) { - return false; - } + if (!isect_point_quad_v2(origin, projverts[0], projverts[1], projverts[2], projverts[3])) { + return false; + } - resolve_quad_uv_v2(r_uv, origin, projverts[0], projverts[3], projverts[2], projverts[1]); + resolve_quad_uv_v2(r_uv, origin, projverts[0], projverts[3], projverts[2], projverts[1]); - return true; + return true; } -static void mdisp_axis_from_quad( - float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3], - float r_axis_x[3], float r_axis_y[3]) +static void mdisp_axis_from_quad(float v1[3], + float v2[3], + float UNUSED(v3[3]), + float v4[3], + float r_axis_x[3], + float r_axis_y[3]) { - sub_v3_v3v3(r_axis_x, v4, v1); - sub_v3_v3v3(r_axis_y, v2, v1); + sub_v3_v3v3(r_axis_x, v4, v1); + sub_v3_v3v3(r_axis_y, v2, v1); - normalize_v3(r_axis_x); - normalize_v3(r_axis_y); + normalize_v3(r_axis_x); + normalize_v3(r_axis_y); } /* tl is loop to project onto, l is loop whose internal displacement, co, is being * projected. x and y are location in loop's mdisps grid of point co. */ -static bool mdisp_in_mdispquad( - BMLoop *l_src, BMLoop *l_dst, const float l_dst_f_center[3], - const float p[3], int res, - float r_axis_x[3], float r_axis_y[3], float r_uv[2]) +static bool mdisp_in_mdispquad(BMLoop *l_src, + BMLoop *l_dst, + const float l_dst_f_center[3], + const float p[3], + int res, + float r_axis_x[3], + float r_axis_y[3], + float r_uv[2]) { - float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3]; - float eps = FLT_EPSILON * 4000; - - if (is_zero_v3(l_src->v->no)) { - BM_vert_normal_update_all(l_src->v); - } - if (is_zero_v3(l_dst->v->no)) { - BM_vert_normal_update_all(l_dst->v); - } - - compute_mdisp_quad(l_dst, l_dst_f_center, v1, v2, v3, v4, e1, e2); - - /* expand quad a bit */ - mid_v3_v3v3v3v3(c, v1, v2, v3, v4); - - sub_v3_v3(v1, c); sub_v3_v3(v2, c); - sub_v3_v3(v3, c); sub_v3_v3(v4, c); - mul_v3_fl(v1, 1.0f + eps); mul_v3_fl(v2, 1.0f + eps); - mul_v3_fl(v3, 1.0f + eps); mul_v3_fl(v4, 1.0f + eps); - add_v3_v3(v1, c); add_v3_v3(v2, c); - add_v3_v3(v3, c); add_v3_v3(v4, c); - - if (!quad_co(v1, v2, v3, v4, p, l_src->v->no, r_uv)) { - return 0; - } - - mul_v2_fl(r_uv, (float)(res - 1)); - - mdisp_axis_from_quad(v1, v2, v3, v4, r_axis_x, r_axis_y); - - return 1; + float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3]; + float eps = FLT_EPSILON * 4000; + + if (is_zero_v3(l_src->v->no)) { + BM_vert_normal_update_all(l_src->v); + } + if (is_zero_v3(l_dst->v->no)) { + BM_vert_normal_update_all(l_dst->v); + } + + compute_mdisp_quad(l_dst, l_dst_f_center, v1, v2, v3, v4, e1, e2); + + /* expand quad a bit */ + mid_v3_v3v3v3v3(c, v1, v2, v3, v4); + + sub_v3_v3(v1, c); + sub_v3_v3(v2, c); + sub_v3_v3(v3, c); + sub_v3_v3(v4, c); + mul_v3_fl(v1, 1.0f + eps); + mul_v3_fl(v2, 1.0f + eps); + mul_v3_fl(v3, 1.0f + eps); + mul_v3_fl(v4, 1.0f + eps); + add_v3_v3(v1, c); + add_v3_v3(v2, c); + add_v3_v3(v3, c); + add_v3_v3(v4, c); + + if (!quad_co(v1, v2, v3, v4, p, l_src->v->no, r_uv)) { + return 0; + } + + mul_v2_fl(r_uv, (float)(res - 1)); + + mdisp_axis_from_quad(v1, v2, v3, v4, r_axis_x, r_axis_y); + + return 1; } -static float bm_loop_flip_equotion( - float mat[2][2], float b[2], const float target_axis_x[3], const float target_axis_y[3], - const float coord[3], int i, int j) +static float bm_loop_flip_equotion(float mat[2][2], + float b[2], + const float target_axis_x[3], + const float target_axis_y[3], + const float coord[3], + int i, + int j) { - mat[0][0] = target_axis_x[i]; - mat[0][1] = target_axis_y[i]; - mat[1][0] = target_axis_x[j]; - mat[1][1] = target_axis_y[j]; - b[0] = coord[i]; - b[1] = coord[j]; - - return cross_v2v2(mat[0], mat[1]); + mat[0][0] = target_axis_x[i]; + mat[0][1] = target_axis_y[i]; + mat[1][0] = target_axis_x[j]; + mat[1][1] = target_axis_y[j]; + b[0] = coord[i]; + b[1] = coord[j]; + + return cross_v2v2(mat[0], mat[1]); } -static void bm_loop_flip_disp( - const float source_axis_x[3], const float source_axis_y[3], - const float target_axis_x[3], const float target_axis_y[3], float disp[3]) +static void bm_loop_flip_disp(const float source_axis_x[3], + const float source_axis_y[3], + const float target_axis_x[3], + const float target_axis_y[3], + float disp[3]) { - float vx[3], vy[3], coord[3]; - float n[3], vec[3]; - float b[2], mat[2][2], d; - - mul_v3_v3fl(vx, source_axis_x, disp[0]); - mul_v3_v3fl(vy, source_axis_y, disp[1]); - add_v3_v3v3(coord, vx, vy); - - /* project displacement from source grid plane onto target grid plane */ - cross_v3_v3v3(n, target_axis_x, target_axis_y); - project_v3_v3v3(vec, coord, n); - sub_v3_v3v3(coord, coord, vec); - - d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 1); - - if (fabsf(d) < 1e-4f) { - d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 2); - if (fabsf(d) < 1e-4f) { - d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 1, 2); - } - } - - disp[0] = (b[0] * mat[1][1] - mat[0][1] * b[1]) / d; - disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d; + float vx[3], vy[3], coord[3]; + float n[3], vec[3]; + float b[2], mat[2][2], d; + + mul_v3_v3fl(vx, source_axis_x, disp[0]); + mul_v3_v3fl(vy, source_axis_y, disp[1]); + add_v3_v3v3(coord, vx, vy); + + /* project displacement from source grid plane onto target grid plane */ + cross_v3_v3v3(n, target_axis_x, target_axis_y); + project_v3_v3v3(vec, coord, n); + sub_v3_v3v3(coord, coord, vec); + + d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 1); + + if (fabsf(d) < 1e-4f) { + d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 2); + if (fabsf(d) < 1e-4f) { + d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 1, 2); + } + } + + disp[0] = (b[0] * mat[1][1] - mat[0][1] * b[1]) / d; + disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d; } - typedef struct BMLoopInterpMultiresData { - BMLoop *l_dst; - BMLoop *l_src_first; - int cd_loop_mdisp_offset; + BMLoop *l_dst; + BMLoop *l_src_first; + int cd_loop_mdisp_offset; - MDisps *md_dst; - const float *f_src_center; + MDisps *md_dst; + const float *f_src_center; - float *axis_x, *axis_y; - float *v1, *v4; - float *e1, *e2; + float *axis_x, *axis_y; + float *v1, *v4; + float *e1, *e2; - int res; - float d; + int res; + float d; } BMLoopInterpMultiresData; -static void loop_interp_multires_cb( - void *__restrict userdata, - const int ix, - const ParallelRangeTLS *__restrict UNUSED(tls)) +static void loop_interp_multires_cb(void *__restrict userdata, + const int ix, + const ParallelRangeTLS *__restrict UNUSED(tls)) { - BMLoopInterpMultiresData *data = userdata; + BMLoopInterpMultiresData *data = userdata; - BMLoop *l_first = data->l_src_first; - BMLoop *l_dst = data->l_dst; - const int cd_loop_mdisp_offset = data->cd_loop_mdisp_offset; + BMLoop *l_first = data->l_src_first; + BMLoop *l_dst = data->l_dst; + const int cd_loop_mdisp_offset = data->cd_loop_mdisp_offset; - MDisps *md_dst = data->md_dst; - const float *f_src_center = data->f_src_center; + MDisps *md_dst = data->md_dst; + const float *f_src_center = data->f_src_center; - float *axis_x = data->axis_x; - float *axis_y = data->axis_y; + float *axis_x = data->axis_x; + float *axis_y = data->axis_y; - float *v1 = data->v1; - float *v4 = data->v4; - float *e1 = data->e1; - float *e2 = data->e2; + float *v1 = data->v1; + float *v4 = data->v4; + float *e1 = data->e1; + float *e2 = data->e2; - const int res = data->res; - const float d = data->d; + const int res = data->res; + const float d = data->d; - float x = d * ix, y; - int iy; - for (y = 0.0f, iy = 0; iy < res; y += d, iy++) { - BMLoop *l_iter = l_first; - float co1[3], co2[3], co[3]; + float x = d * ix, y; + int iy; + for (y = 0.0f, iy = 0; iy < res; y += d, iy++) { + BMLoop *l_iter = l_first; + float co1[3], co2[3], co[3]; - madd_v3_v3v3fl(co1, v1, e1, y); - madd_v3_v3v3fl(co2, v4, e2, y); - interp_v3_v3v3(co, co1, co2, x); + madd_v3_v3v3fl(co1, v1, e1, y); + madd_v3_v3v3fl(co2, v4, e2, y); + interp_v3_v3v3(co, co1, co2, x); - do { - MDisps *md_src; - float src_axis_x[3], src_axis_y[3]; - float uv[2]; + do { + MDisps *md_src; + float src_axis_x[3], src_axis_y[3]; + float uv[2]; - md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset); + md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset); - if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) { - old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]); - bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]); + if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) { + old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]); + bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]); - break; - } - } while ((l_iter = l_iter->next) != l_first); - } + break; + } + } while ((l_iter = l_iter->next) != l_first); + } } -void BM_loop_interp_multires_ex( - BMesh *UNUSED(bm), BMLoop *l_dst, const BMFace *f_src, - const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset) +void BM_loop_interp_multires_ex(BMesh *UNUSED(bm), + BMLoop *l_dst, + const BMFace *f_src, + const float f_dst_center[3], + const float f_src_center[3], + const int cd_loop_mdisp_offset) { - MDisps *md_dst; - float v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3]; - float axis_x[3], axis_y[3]; - - /* ignore 2-edged faces */ - if (UNLIKELY(l_dst->f->len < 3)) { - return; - } - - md_dst = BM_ELEM_CD_GET_VOID_P(l_dst, cd_loop_mdisp_offset); - compute_mdisp_quad(l_dst, f_dst_center, v1, v2, v3, v4, e1, e2); - - /* if no disps data allocate a new grid, the size of the first grid in f_src. */ - if (!md_dst->totdisp) { - const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset); - - md_dst->totdisp = md_src->totdisp; - md_dst->level = md_src->level; - if (md_dst->totdisp) { - md_dst->disps = MEM_callocN(sizeof(float) * 3 * md_dst->totdisp, __func__); - } - else { - return; - } - } - - mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y); - - const int res = (int)sqrt(md_dst->totdisp); - BMLoopInterpMultiresData data = { - .l_dst = l_dst, .l_src_first = BM_FACE_FIRST_LOOP(f_src), - .cd_loop_mdisp_offset = cd_loop_mdisp_offset, - .md_dst = md_dst, .f_src_center = f_src_center, - .axis_x = axis_x, .axis_y = axis_y, .v1 = v1, .v4 = v4, .e1 = e1, .e2 = e2, - .res = res, .d = 1.0f / (float)(res - 1), - }; - ParallelRangeSettings settings; - BLI_parallel_range_settings_defaults(&settings); - settings.use_threading = (res > 5); - BLI_task_parallel_range(0, res, &data, loop_interp_multires_cb, &settings); + MDisps *md_dst; + float v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3]; + float axis_x[3], axis_y[3]; + + /* ignore 2-edged faces */ + if (UNLIKELY(l_dst->f->len < 3)) { + return; + } + + md_dst = BM_ELEM_CD_GET_VOID_P(l_dst, cd_loop_mdisp_offset); + compute_mdisp_quad(l_dst, f_dst_center, v1, v2, v3, v4, e1, e2); + + /* if no disps data allocate a new grid, the size of the first grid in f_src. */ + if (!md_dst->totdisp) { + const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset); + + md_dst->totdisp = md_src->totdisp; + md_dst->level = md_src->level; + if (md_dst->totdisp) { + md_dst->disps = MEM_callocN(sizeof(float) * 3 * md_dst->totdisp, __func__); + } + else { + return; + } + } + + mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y); + + const int res = (int)sqrt(md_dst->totdisp); + BMLoopInterpMultiresData data = { + .l_dst = l_dst, + .l_src_first = BM_FACE_FIRST_LOOP(f_src), + .cd_loop_mdisp_offset = cd_loop_mdisp_offset, + .md_dst = md_dst, + .f_src_center = f_src_center, + .axis_x = axis_x, + .axis_y = axis_y, + .v1 = v1, + .v4 = v4, + .e1 = e1, + .e2 = e2, + .res = res, + .d = 1.0f / (float)(res - 1), + }; + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.use_threading = (res > 5); + BLI_task_parallel_range(0, res, &data, loop_interp_multires_cb, &settings); } /** @@ -521,45 +572,47 @@ void BM_loop_interp_multires_ex( */ void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src) { - const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); - if (cd_loop_mdisp_offset != -1) { - float f_dst_center[3]; - float f_src_center[3]; + if (cd_loop_mdisp_offset != -1) { + float f_dst_center[3]; + float f_src_center[3]; - BM_face_calc_center_median(l_dst->f, f_dst_center); - BM_face_calc_center_median(f_src, f_src_center); + BM_face_calc_center_median(l_dst->f, f_dst_center); + BM_face_calc_center_median(f_src, f_src_center); - BM_loop_interp_multires_ex(bm, l_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset); - } + BM_loop_interp_multires_ex(bm, l_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset); + } } -void BM_face_interp_multires_ex( - BMesh *bm, BMFace *f_dst, const BMFace *f_src, - const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset) +void BM_face_interp_multires_ex(BMesh *bm, + BMFace *f_dst, + const BMFace *f_src, + const float f_dst_center[3], + const float f_src_center[3], + const int cd_loop_mdisp_offset) { - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst); - do { - BM_loop_interp_multires_ex( - bm, l_iter, f_src, - f_dst_center, f_src_center, cd_loop_mdisp_offset); - } while ((l_iter = l_iter->next) != l_first); + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst); + do { + BM_loop_interp_multires_ex( + bm, l_iter, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset); + } while ((l_iter = l_iter->next) != l_first); } void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src) { - const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); - if (cd_loop_mdisp_offset != -1) { - float f_dst_center[3]; - float f_src_center[3]; + if (cd_loop_mdisp_offset != -1) { + float f_dst_center[3]; + float f_src_center[3]; - BM_face_calc_center_median(f_dst, f_dst_center); - BM_face_calc_center_median(f_src, f_src_center); + BM_face_calc_center_median(f_dst, f_dst_center); + BM_face_calc_center_median(f_src, f_src_center); - BM_face_interp_multires_ex(bm, f_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset); - } + BM_face_interp_multires_ex(bm, f_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset); + } } /** @@ -568,110 +621,110 @@ void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src) */ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f) { - const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); - BMLoop *l; - BMIter liter; - - if (cd_loop_mdisp_offset == -1) { - return; - } - - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - MDisps *mdp = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_mdisp_offset); - MDisps *mdl = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset); - MDisps *mdn = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_mdisp_offset); - float co1[3]; - int sides; - int y; - - /** - * mdisps is a grid of displacements, ordered thus: - * <pre> - * v4/next - * | - * | v1/cent-----mid2 ---> x - * | | | - * | | | - * v2/prev---mid1-----v3/cur - * | - * V - * y - * </pre> - */ - - sides = (int)sqrt(mdp->totdisp); - for (y = 0; y < sides; y++) { - mid_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]); - - copy_v3_v3(mdn->disps[y * sides], co1); - copy_v3_v3(mdl->disps[y], co1); - } - } - - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - MDisps *mdl1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset); - MDisps *mdl2; - float co1[3], co2[3], co[3]; - int sides; - int y; - - /** - * mdisps is a grid of displacements, ordered thus: - * <pre> - * v4/next - * | - * | v1/cent-----mid2 ---> x - * | | | - * | | | - * v2/prev---mid1-----v3/cur - * | - * V - * y - * </pre> - */ - - if (l->radial_next == l) { - continue; - } - - if (l->radial_next->v == l->v) { - mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next, cd_loop_mdisp_offset); - } - else { - mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next->next, cd_loop_mdisp_offset); - } - - sides = (int)sqrt(mdl1->totdisp); - for (y = 0; y < sides; y++) { - int a1, a2, o1, o2; - - if (l->v != l->radial_next->v) { - a1 = sides * y + sides - 2; - a2 = (sides - 2) * sides + y; - - o1 = sides * y + sides - 1; - o2 = (sides - 1) * sides + y; - } - else { - a1 = sides * y + sides - 2; - a2 = sides * y + sides - 2; - o1 = sides * y + sides - 1; - o2 = sides * y + sides - 1; - } - - /* magic blending numbers, hardcoded! */ - add_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2]); - mul_v3_fl(co1, 0.18); - - add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]); - mul_v3_fl(co2, 0.32); - - add_v3_v3v3(co, co1, co2); - - copy_v3_v3(mdl1->disps[o1], co); - copy_v3_v3(mdl2->disps[o2], co); - } - } + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + BMLoop *l; + BMIter liter; + + if (cd_loop_mdisp_offset == -1) { + return; + } + + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + MDisps *mdp = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_mdisp_offset); + MDisps *mdl = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset); + MDisps *mdn = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_mdisp_offset); + float co1[3]; + int sides; + int y; + + /** + * mdisps is a grid of displacements, ordered thus: + * <pre> + * v4/next + * | + * | v1/cent-----mid2 ---> x + * | | | + * | | | + * v2/prev---mid1-----v3/cur + * | + * V + * y + * </pre> + */ + + sides = (int)sqrt(mdp->totdisp); + for (y = 0; y < sides; y++) { + mid_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]); + + copy_v3_v3(mdn->disps[y * sides], co1); + copy_v3_v3(mdl->disps[y], co1); + } + } + + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + MDisps *mdl1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset); + MDisps *mdl2; + float co1[3], co2[3], co[3]; + int sides; + int y; + + /** + * mdisps is a grid of displacements, ordered thus: + * <pre> + * v4/next + * | + * | v1/cent-----mid2 ---> x + * | | | + * | | | + * v2/prev---mid1-----v3/cur + * | + * V + * y + * </pre> + */ + + if (l->radial_next == l) { + continue; + } + + if (l->radial_next->v == l->v) { + mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next, cd_loop_mdisp_offset); + } + else { + mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next->next, cd_loop_mdisp_offset); + } + + sides = (int)sqrt(mdl1->totdisp); + for (y = 0; y < sides; y++) { + int a1, a2, o1, o2; + + if (l->v != l->radial_next->v) { + a1 = sides * y + sides - 2; + a2 = (sides - 2) * sides + y; + + o1 = sides * y + sides - 1; + o2 = (sides - 1) * sides + y; + } + else { + a1 = sides * y + sides - 2; + a2 = sides * y + sides - 2; + o1 = sides * y + sides - 1; + o2 = sides * y + sides - 1; + } + + /* magic blending numbers, hardcoded! */ + add_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2]); + mul_v3_fl(co1, 0.18); + + add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]); + mul_v3_fl(co2, 0.32); + + add_v3_v3v3(co, co1, co2); + + copy_v3_v3(mdl1->disps[o1], co); + copy_v3_v3(mdl2->disps[o2], co); + } + } } /** @@ -679,290 +732,288 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f) * if do_vertex is true, target's vert data will also get interpolated. */ void BM_loop_interp_from_face( - BMesh *bm, BMLoop *l_dst, const BMFace *f_src, - const bool do_vertex, const bool do_multires) + BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires) { - BMLoop *l_iter; - BMLoop *l_first; - const void **vblocks = do_vertex ? BLI_array_alloca(vblocks, f_src->len) : NULL; - const void **blocks = BLI_array_alloca(blocks, f_src->len); - float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len); - float *w = BLI_array_alloca(w, f_src->len); - float axis_mat[3][3]; /* use normal to transform into 2d xy coords */ - float co[2]; - int i; - - /* convert the 3d coords into 2d for projection */ - BLI_assert(BM_face_is_normal_valid(f_src)); - axis_dominant_v3_to_m3(axis_mat, f_src->no); - - i = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f_src); - do { - mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); - blocks[i] = l_iter->head.data; - - if (do_vertex) { - vblocks[i] = l_iter->v->head.data; - } - } while ((void)i++, (l_iter = l_iter->next) != l_first); - - mul_v2_m3v3(co, axis_mat, l_dst->v->co); - - /* interpolate */ - interp_weights_poly_v2(w, cos_2d, f_src->len, co); - CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f_src->len, l_dst->head.data); - if (do_vertex) { - CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, f_src->len, l_dst->v->head.data); - } - - if (do_multires) { - BM_loop_interp_multires(bm, l_dst, f_src); - } + BMLoop *l_iter; + BMLoop *l_first; + const void **vblocks = do_vertex ? BLI_array_alloca(vblocks, f_src->len) : NULL; + const void **blocks = BLI_array_alloca(blocks, f_src->len); + float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len); + float *w = BLI_array_alloca(w, f_src->len); + float axis_mat[3][3]; /* use normal to transform into 2d xy coords */ + float co[2]; + int i; + + /* convert the 3d coords into 2d for projection */ + BLI_assert(BM_face_is_normal_valid(f_src)); + axis_dominant_v3_to_m3(axis_mat, f_src->no); + + i = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(f_src); + do { + mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); + blocks[i] = l_iter->head.data; + + if (do_vertex) { + vblocks[i] = l_iter->v->head.data; + } + } while ((void)i++, (l_iter = l_iter->next) != l_first); + + mul_v2_m3v3(co, axis_mat, l_dst->v->co); + + /* interpolate */ + interp_weights_poly_v2(w, cos_2d, f_src->len, co); + CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f_src->len, l_dst->head.data); + if (do_vertex) { + CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, f_src->len, l_dst->v->head.data); + } + + if (do_multires) { + BM_loop_interp_multires(bm, l_dst, f_src); + } } - void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src) { - BMLoop *l_iter; - BMLoop *l_first; - const void **blocks = BLI_array_alloca(blocks, f_src->len); - float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len); - float *w = BLI_array_alloca(w, f_src->len); - float axis_mat[3][3]; /* use normal to transform into 2d xy coords */ - float co[2]; - int i; - - /* convert the 3d coords into 2d for projection */ - BLI_assert(BM_face_is_normal_valid(f_src)); - axis_dominant_v3_to_m3(axis_mat, f_src->no); - - i = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f_src); - do { - mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); - blocks[i] = l_iter->v->head.data; - } while ((void)i++, (l_iter = l_iter->next) != l_first); - - mul_v2_m3v3(co, axis_mat, v_dst->co); - - /* interpolate */ - interp_weights_poly_v2(w, cos_2d, f_src->len, co); - CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, f_src->len, v_dst->head.data); + BMLoop *l_iter; + BMLoop *l_first; + const void **blocks = BLI_array_alloca(blocks, f_src->len); + float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len); + float *w = BLI_array_alloca(w, f_src->len); + float axis_mat[3][3]; /* use normal to transform into 2d xy coords */ + float co[2]; + int i; + + /* convert the 3d coords into 2d for projection */ + BLI_assert(BM_face_is_normal_valid(f_src)); + axis_dominant_v3_to_m3(axis_mat, f_src->no); + + i = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(f_src); + do { + mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); + blocks[i] = l_iter->v->head.data; + } while ((void)i++, (l_iter = l_iter->next) != l_first); + + mul_v2_m3v3(co, axis_mat, v_dst->co); + + /* interpolate */ + interp_weights_poly_v2(w, cos_2d, f_src->len, co); + CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, f_src->len, v_dst->head.data); } static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data) { - BMIter iter; - BLI_mempool *oldpool = olddata->pool; - void *block; - - if (data == &bm->vdata) { - BMVert *eve; - - CustomData_bmesh_init_pool(data, bm->totvert, BM_VERT); - - BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - block = NULL; - CustomData_bmesh_set_default(data, &block); - CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block); - CustomData_bmesh_free_block(olddata, &eve->head.data); - eve->head.data = block; - } - } - else if (data == &bm->edata) { - BMEdge *eed; - - CustomData_bmesh_init_pool(data, bm->totedge, BM_EDGE); - - BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { - block = NULL; - CustomData_bmesh_set_default(data, &block); - CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block); - CustomData_bmesh_free_block(olddata, &eed->head.data); - eed->head.data = block; - } - } - else if (data == &bm->ldata) { - BMIter liter; - BMFace *efa; - BMLoop *l; - - CustomData_bmesh_init_pool(data, bm->totloop, BM_LOOP); - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - block = NULL; - CustomData_bmesh_set_default(data, &block); - CustomData_bmesh_copy_data(olddata, data, l->head.data, &block); - CustomData_bmesh_free_block(olddata, &l->head.data); - l->head.data = block; - } - } - } - else if (data == &bm->pdata) { - BMFace *efa; - - CustomData_bmesh_init_pool(data, bm->totface, BM_FACE); - - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - block = NULL; - CustomData_bmesh_set_default(data, &block); - CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block); - CustomData_bmesh_free_block(olddata, &efa->head.data); - efa->head.data = block; - } - } - else { - /* should never reach this! */ - BLI_assert(0); - } - - if (oldpool) { - /* this should never happen but can when dissolve fails - [#28960] */ - BLI_assert(data->pool != oldpool); - - BLI_mempool_destroy(oldpool); - } + BMIter iter; + BLI_mempool *oldpool = olddata->pool; + void *block; + + if (data == &bm->vdata) { + BMVert *eve; + + CustomData_bmesh_init_pool(data, bm->totvert, BM_VERT); + + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + block = NULL; + CustomData_bmesh_set_default(data, &block); + CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block); + CustomData_bmesh_free_block(olddata, &eve->head.data); + eve->head.data = block; + } + } + else if (data == &bm->edata) { + BMEdge *eed; + + CustomData_bmesh_init_pool(data, bm->totedge, BM_EDGE); + + BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { + block = NULL; + CustomData_bmesh_set_default(data, &block); + CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block); + CustomData_bmesh_free_block(olddata, &eed->head.data); + eed->head.data = block; + } + } + else if (data == &bm->ldata) { + BMIter liter; + BMFace *efa; + BMLoop *l; + + CustomData_bmesh_init_pool(data, bm->totloop, BM_LOOP); + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + block = NULL; + CustomData_bmesh_set_default(data, &block); + CustomData_bmesh_copy_data(olddata, data, l->head.data, &block); + CustomData_bmesh_free_block(olddata, &l->head.data); + l->head.data = block; + } + } + } + else if (data == &bm->pdata) { + BMFace *efa; + + CustomData_bmesh_init_pool(data, bm->totface, BM_FACE); + + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + block = NULL; + CustomData_bmesh_set_default(data, &block); + CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block); + CustomData_bmesh_free_block(olddata, &efa->head.data); + efa->head.data = block; + } + } + else { + /* should never reach this! */ + BLI_assert(0); + } + + if (oldpool) { + /* this should never happen but can when dissolve fails - [#28960] */ + BLI_assert(data->pool != oldpool); + + BLI_mempool_destroy(oldpool); + } } void BM_data_layer_add(BMesh *bm, CustomData *data, int type) { - CustomData olddata; + CustomData olddata; - olddata = *data; - olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; + olddata = *data; + olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; - /* the pool is now owned by olddata and must not be shared */ - data->pool = NULL; + /* the pool is now owned by olddata and must not be shared */ + data->pool = NULL; - CustomData_add_layer(data, type, CD_DEFAULT, NULL, 0); + CustomData_add_layer(data, type, CD_DEFAULT, NULL, 0); - update_data_blocks(bm, &olddata, data); - if (olddata.layers) { - MEM_freeN(olddata.layers); - } + update_data_blocks(bm, &olddata, data); + if (olddata.layers) { + MEM_freeN(olddata.layers); + } } void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name) { - CustomData olddata; + CustomData olddata; - olddata = *data; - olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; + olddata = *data; + olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; - /* the pool is now owned by olddata and must not be shared */ - data->pool = NULL; + /* the pool is now owned by olddata and must not be shared */ + data->pool = NULL; - CustomData_add_layer_named(data, type, CD_DEFAULT, NULL, 0, name); + CustomData_add_layer_named(data, type, CD_DEFAULT, NULL, 0, name); - update_data_blocks(bm, &olddata, data); - if (olddata.layers) { - MEM_freeN(olddata.layers); - } + update_data_blocks(bm, &olddata, data); + if (olddata.layers) { + MEM_freeN(olddata.layers); + } } void BM_data_layer_free(BMesh *bm, CustomData *data, int type) { - CustomData olddata; - bool has_layer; + CustomData olddata; + bool has_layer; - olddata = *data; - olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; + olddata = *data; + olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; - /* the pool is now owned by olddata and must not be shared */ - data->pool = NULL; + /* the pool is now owned by olddata and must not be shared */ + data->pool = NULL; - has_layer = CustomData_free_layer_active(data, type, 0); - /* assert because its expensive to realloc - better not do if layer isnt present */ - BLI_assert(has_layer != false); - UNUSED_VARS_NDEBUG(has_layer); + has_layer = CustomData_free_layer_active(data, type, 0); + /* assert because its expensive to realloc - better not do if layer isnt present */ + BLI_assert(has_layer != false); + UNUSED_VARS_NDEBUG(has_layer); - update_data_blocks(bm, &olddata, data); - if (olddata.layers) { - MEM_freeN(olddata.layers); - } + update_data_blocks(bm, &olddata, data); + if (olddata.layers) { + MEM_freeN(olddata.layers); + } } void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n) { - CustomData olddata; - bool has_layer; + CustomData olddata; + bool has_layer; - olddata = *data; - olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; + olddata = *data; + olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL; - /* the pool is now owned by olddata and must not be shared */ - data->pool = NULL; + /* the pool is now owned by olddata and must not be shared */ + data->pool = NULL; - has_layer = CustomData_free_layer(data, type, 0, CustomData_get_layer_index_n(data, type, n)); - /* assert because its expensive to realloc - better not do if layer isnt present */ - BLI_assert(has_layer != false); - UNUSED_VARS_NDEBUG(has_layer); + has_layer = CustomData_free_layer(data, type, 0, CustomData_get_layer_index_n(data, type, n)); + /* assert because its expensive to realloc - better not do if layer isnt present */ + BLI_assert(has_layer != false); + UNUSED_VARS_NDEBUG(has_layer); - update_data_blocks(bm, &olddata, data); - if (olddata.layers) { - MEM_freeN(olddata.layers); - } + update_data_blocks(bm, &olddata, data); + if (olddata.layers) { + MEM_freeN(olddata.layers); + } } void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n) { - BMIter iter; - - if (&bm->vdata == data) { - BMVert *eve; - - BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - void *ptr = CustomData_bmesh_get_n(data, eve->head.data, type, src_n); - CustomData_bmesh_set_n(data, eve->head.data, type, dst_n, ptr); - } - } - else if (&bm->edata == data) { - BMEdge *eed; - - BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { - void *ptr = CustomData_bmesh_get_n(data, eed->head.data, type, src_n); - CustomData_bmesh_set_n(data, eed->head.data, type, dst_n, ptr); - } - } - else if (&bm->pdata == data) { - BMFace *efa; - - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - void *ptr = CustomData_bmesh_get_n(data, efa->head.data, type, src_n); - CustomData_bmesh_set_n(data, efa->head.data, type, dst_n, ptr); - } - } - else if (&bm->ldata == data) { - BMIter liter; - BMFace *efa; - BMLoop *l; - - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - void *ptr = CustomData_bmesh_get_n(data, l->head.data, type, src_n); - CustomData_bmesh_set_n(data, l->head.data, type, dst_n, ptr); - } - } - } - else { - /* should never reach this! */ - BLI_assert(0); - } + BMIter iter; + + if (&bm->vdata == data) { + BMVert *eve; + + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + void *ptr = CustomData_bmesh_get_n(data, eve->head.data, type, src_n); + CustomData_bmesh_set_n(data, eve->head.data, type, dst_n, ptr); + } + } + else if (&bm->edata == data) { + BMEdge *eed; + + BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { + void *ptr = CustomData_bmesh_get_n(data, eed->head.data, type, src_n); + CustomData_bmesh_set_n(data, eed->head.data, type, dst_n, ptr); + } + } + else if (&bm->pdata == data) { + BMFace *efa; + + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + void *ptr = CustomData_bmesh_get_n(data, efa->head.data, type, src_n); + CustomData_bmesh_set_n(data, efa->head.data, type, dst_n, ptr); + } + } + else if (&bm->ldata == data) { + BMIter liter; + BMFace *efa; + BMLoop *l; + + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + void *ptr = CustomData_bmesh_get_n(data, l->head.data, type, src_n); + CustomData_bmesh_set_n(data, l->head.data, type, dst_n, ptr); + } + } + } + else { + /* should never reach this! */ + BLI_assert(0); + } } float BM_elem_float_data_get(CustomData *cd, void *element, int type) { - const float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type); - return f ? *f : 0.0f; + const float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type); + return f ? *f : 0.0f; } void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val) { - float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type); - if (f) { - *f = val; - } + float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type); + if (f) { + *f = val; + } } /** \name Loop interpolation functions: BM_vert_loop_groups_data_layer_*** @@ -984,51 +1035,51 @@ void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float * \{ */ struct LoopWalkCtx { - /* same for all groups */ - int type; - int cd_layer_offset; - const float *loop_weights; - MemArena *arena; - - /* --- Per loop fan vars --- */ - - /* reference for this contiguous fan */ - const void *data_ref; - int data_len; - - /* accumulate 'LoopGroupCD.weight' to make unit length */ - float weight_accum; - - /* both arrays the size of the 'BM_vert_face_count(v)' - * each contiguous fan gets a slide of these arrays */ - void **data_array; - int *data_index_array; - float *weight_array; + /* same for all groups */ + int type; + int cd_layer_offset; + const float *loop_weights; + MemArena *arena; + + /* --- Per loop fan vars --- */ + + /* reference for this contiguous fan */ + const void *data_ref; + int data_len; + + /* accumulate 'LoopGroupCD.weight' to make unit length */ + float weight_accum; + + /* both arrays the size of the 'BM_vert_face_count(v)' + * each contiguous fan gets a slide of these arrays */ + void **data_array; + int *data_index_array; + float *weight_array; }; /* Store vars to pass into 'CustomData_bmesh_interp' */ struct LoopGroupCD { - /* direct customdata pointer array */ - void **data; - /* weights (aligned with 'data') */ - float *data_weights; - /* index-in-face */ - int *data_index; - /* number of loops in the fan */ - int data_len; + /* direct customdata pointer array */ + void **data; + /* weights (aligned with 'data') */ + float *data_weights; + /* index-in-face */ + int *data_index; + /* number of loops in the fan */ + int data_len; }; static void bm_loop_walk_add(struct LoopWalkCtx *lwc, BMLoop *l) { - const int i = BM_elem_index_get(l); - const float w = lwc->loop_weights[i]; - BM_elem_flag_disable(l, BM_ELEM_INTERNAL_TAG); - lwc->data_array[lwc->data_len] = BM_ELEM_CD_GET_VOID_P(l, lwc->cd_layer_offset); - lwc->data_index_array[lwc->data_len] = i; - lwc->weight_array[lwc->data_len] = w; - lwc->weight_accum += w; - - lwc->data_len += 1; + const int i = BM_elem_index_get(l); + const float w = lwc->loop_weights[i]; + BM_elem_flag_disable(l, BM_ELEM_INTERNAL_TAG); + lwc->data_array[lwc->data_len] = BM_ELEM_CD_GET_VOID_P(l, lwc->cd_layer_offset); + lwc->data_index_array[lwc->data_len] = i; + lwc->weight_array[lwc->data_len] = w; + lwc->weight_accum += w; + + lwc->data_len += 1; } /** @@ -1038,146 +1089,145 @@ static void bm_loop_walk_add(struct LoopWalkCtx *lwc, BMLoop *l) */ static void bm_loop_walk_data(struct LoopWalkCtx *lwc, BMLoop *l_walk) { - int i; - - BLI_assert(CustomData_data_equals(lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_walk, lwc->cd_layer_offset))); - BLI_assert(BM_elem_flag_test(l_walk, BM_ELEM_INTERNAL_TAG)); - - bm_loop_walk_add(lwc, l_walk); - - /* recurse around this loop-fan (in both directions) */ - for (i = 0; i < 2; i++) { - BMLoop *l_other = ((i == 0) ? l_walk : l_walk->prev)->radial_next; - if (l_other->radial_next != l_other) { - if (l_other->v != l_walk->v) { - l_other = l_other->next; - } - BLI_assert(l_other->v == l_walk->v); - if (BM_elem_flag_test(l_other, BM_ELEM_INTERNAL_TAG)) { - if (CustomData_data_equals(lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_other, lwc->cd_layer_offset))) { - bm_loop_walk_data(lwc, l_other); - } - } - } - } + int i; + + BLI_assert(CustomData_data_equals( + lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_walk, lwc->cd_layer_offset))); + BLI_assert(BM_elem_flag_test(l_walk, BM_ELEM_INTERNAL_TAG)); + + bm_loop_walk_add(lwc, l_walk); + + /* recurse around this loop-fan (in both directions) */ + for (i = 0; i < 2; i++) { + BMLoop *l_other = ((i == 0) ? l_walk : l_walk->prev)->radial_next; + if (l_other->radial_next != l_other) { + if (l_other->v != l_walk->v) { + l_other = l_other->next; + } + BLI_assert(l_other->v == l_walk->v); + if (BM_elem_flag_test(l_other, BM_ELEM_INTERNAL_TAG)) { + if (CustomData_data_equals( + lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_other, lwc->cd_layer_offset))) { + bm_loop_walk_data(lwc, l_other); + } + } + } + } } LinkNode *BM_vert_loop_groups_data_layer_create( - BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena) + BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena) { - struct LoopWalkCtx lwc; - LinkNode *groups = NULL; - BMLoop *l; - BMIter liter; - int loop_num; - - - lwc.type = bm->ldata.layers[layer_n].type; - lwc.cd_layer_offset = bm->ldata.layers[layer_n].offset; - lwc.loop_weights = loop_weights; - lwc.arena = arena; - - /* Enable 'BM_ELEM_INTERNAL_TAG', leaving the flag clean on completion. */ - loop_num = 0; - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - BM_elem_flag_enable(l, BM_ELEM_INTERNAL_TAG); - BM_elem_index_set(l, loop_num); /* set_dirty! */ - loop_num++; - } - bm->elem_index_dirty |= BM_LOOP; - - lwc.data_len = 0; - lwc.data_array = BLI_memarena_alloc(lwc.arena, sizeof(void *) * loop_num); - lwc.data_index_array = BLI_memarena_alloc(lwc.arena, sizeof(int) * loop_num); - lwc.weight_array = BLI_memarena_alloc(lwc.arena, sizeof(float) * loop_num); - - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - if (BM_elem_flag_test(l, BM_ELEM_INTERNAL_TAG)) { - struct LoopGroupCD *lf = BLI_memarena_alloc(lwc.arena, sizeof(*lf)); - int len_prev = lwc.data_len; - - lwc.data_ref = BM_ELEM_CD_GET_VOID_P(l, lwc.cd_layer_offset); - - /* assign len-last */ - lf->data = &lwc.data_array[lwc.data_len]; - lf->data_index = &lwc.data_index_array[lwc.data_len]; - lf->data_weights = &lwc.weight_array[lwc.data_len]; - lwc.weight_accum = 0.0f; - - /* new group */ - bm_loop_walk_data(&lwc, l); - lf->data_len = lwc.data_len - len_prev; - - if (LIKELY(lwc.weight_accum != 0.0f)) { - mul_vn_fl(lf->data_weights, lf->data_len, 1.0f / lwc.weight_accum); - } - else { - copy_vn_fl(lf->data_weights, lf->data_len, 1.0f / (float)lf->data_len); - } - - BLI_linklist_prepend_arena(&groups, lf, lwc.arena); - } - } - - BLI_assert(lwc.data_len == loop_num); - - return groups; + struct LoopWalkCtx lwc; + LinkNode *groups = NULL; + BMLoop *l; + BMIter liter; + int loop_num; + + lwc.type = bm->ldata.layers[layer_n].type; + lwc.cd_layer_offset = bm->ldata.layers[layer_n].offset; + lwc.loop_weights = loop_weights; + lwc.arena = arena; + + /* Enable 'BM_ELEM_INTERNAL_TAG', leaving the flag clean on completion. */ + loop_num = 0; + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + BM_elem_flag_enable(l, BM_ELEM_INTERNAL_TAG); + BM_elem_index_set(l, loop_num); /* set_dirty! */ + loop_num++; + } + bm->elem_index_dirty |= BM_LOOP; + + lwc.data_len = 0; + lwc.data_array = BLI_memarena_alloc(lwc.arena, sizeof(void *) * loop_num); + lwc.data_index_array = BLI_memarena_alloc(lwc.arena, sizeof(int) * loop_num); + lwc.weight_array = BLI_memarena_alloc(lwc.arena, sizeof(float) * loop_num); + + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + if (BM_elem_flag_test(l, BM_ELEM_INTERNAL_TAG)) { + struct LoopGroupCD *lf = BLI_memarena_alloc(lwc.arena, sizeof(*lf)); + int len_prev = lwc.data_len; + + lwc.data_ref = BM_ELEM_CD_GET_VOID_P(l, lwc.cd_layer_offset); + + /* assign len-last */ + lf->data = &lwc.data_array[lwc.data_len]; + lf->data_index = &lwc.data_index_array[lwc.data_len]; + lf->data_weights = &lwc.weight_array[lwc.data_len]; + lwc.weight_accum = 0.0f; + + /* new group */ + bm_loop_walk_data(&lwc, l); + lf->data_len = lwc.data_len - len_prev; + + if (LIKELY(lwc.weight_accum != 0.0f)) { + mul_vn_fl(lf->data_weights, lf->data_len, 1.0f / lwc.weight_accum); + } + else { + copy_vn_fl(lf->data_weights, lf->data_len, 1.0f / (float)lf->data_len); + } + + BLI_linklist_prepend_arena(&groups, lf, lwc.arena); + } + } + + BLI_assert(lwc.data_len == loop_num); + + return groups; } -static void bm_vert_loop_groups_data_layer_merge__single( - BMesh *bm, void *lf_p, int layer_n, - void *data_tmp) +static void bm_vert_loop_groups_data_layer_merge__single(BMesh *bm, + void *lf_p, + int layer_n, + void *data_tmp) { - struct LoopGroupCD *lf = lf_p; - const int type = bm->ldata.layers[layer_n].type; - int i; - const float *data_weights; + struct LoopGroupCD *lf = lf_p; + const int type = bm->ldata.layers[layer_n].type; + int i; + const float *data_weights; - data_weights = lf->data_weights; + data_weights = lf->data_weights; - CustomData_bmesh_interp_n( - &bm->ldata, (const void **)lf->data, - data_weights, NULL, lf->data_len, data_tmp, layer_n); + CustomData_bmesh_interp_n( + &bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n); - for (i = 0; i < lf->data_len; i++) { - CustomData_copy_elements(type, data_tmp, lf->data[i], 1); - } + for (i = 0; i < lf->data_len; i++) { + CustomData_copy_elements(type, data_tmp, lf->data[i], 1); + } } static void bm_vert_loop_groups_data_layer_merge_weights__single( - BMesh *bm, void *lf_p, const int layer_n, void *data_tmp, - const float *loop_weights) + BMesh *bm, void *lf_p, const int layer_n, void *data_tmp, const float *loop_weights) { - struct LoopGroupCD *lf = lf_p; - const int type = bm->ldata.layers[layer_n].type; - int i; - const float *data_weights; - - /* re-weight */ - float *temp_weights = BLI_array_alloca(temp_weights, lf->data_len); - float weight_accum = 0.0f; - - for (i = 0; i < lf->data_len; i++) { - float w = loop_weights[lf->data_index[i]] * lf->data_weights[i]; - temp_weights[i] = w; - weight_accum += w; - } - - if (LIKELY(weight_accum != 0.0f)) { - mul_vn_fl(temp_weights, lf->data_len, 1.0f / weight_accum); - data_weights = temp_weights; - } - else { - data_weights = lf->data_weights; - } - - CustomData_bmesh_interp_n( - &bm->ldata, (const void **)lf->data, - data_weights, NULL, lf->data_len, data_tmp, layer_n); - - for (i = 0; i < lf->data_len; i++) { - CustomData_copy_elements(type, data_tmp, lf->data[i], 1); - } + struct LoopGroupCD *lf = lf_p; + const int type = bm->ldata.layers[layer_n].type; + int i; + const float *data_weights; + + /* re-weight */ + float *temp_weights = BLI_array_alloca(temp_weights, lf->data_len); + float weight_accum = 0.0f; + + for (i = 0; i < lf->data_len; i++) { + float w = loop_weights[lf->data_index[i]] * lf->data_weights[i]; + temp_weights[i] = w; + weight_accum += w; + } + + if (LIKELY(weight_accum != 0.0f)) { + mul_vn_fl(temp_weights, lf->data_len, 1.0f / weight_accum); + data_weights = temp_weights; + } + else { + data_weights = lf->data_weights; + } + + CustomData_bmesh_interp_n( + &bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n); + + for (i = 0; i < lf->data_len; i++) { + CustomData_copy_elements(type, data_tmp, lf->data[i], 1); + } } /** @@ -1185,29 +1235,32 @@ static void bm_vert_loop_groups_data_layer_merge_weights__single( */ void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int layer_n) { - const int type = bm->ldata.layers[layer_n].type; - const int size = CustomData_sizeof(type); - void *data_tmp = alloca(size); + const int type = bm->ldata.layers[layer_n].type; + const int size = CustomData_sizeof(type); + void *data_tmp = alloca(size); - do { - bm_vert_loop_groups_data_layer_merge__single(bm, groups->link, layer_n, data_tmp); - } while ((groups = groups->next)); + do { + bm_vert_loop_groups_data_layer_merge__single(bm, groups->link, layer_n, data_tmp); + } while ((groups = groups->next)); } /** * A version of #BM_vert_loop_groups_data_layer_merge * that takes an array of loop-weights (aligned with #BM_LOOPS_OF_VERT iterator) */ -void BM_vert_loop_groups_data_layer_merge_weights( - BMesh *bm, LinkNode *groups, const int layer_n, const float *loop_weights) +void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm, + LinkNode *groups, + const int layer_n, + const float *loop_weights) { - const int type = bm->ldata.layers[layer_n].type; - const int size = CustomData_sizeof(type); - void *data_tmp = alloca(size); - - do { - bm_vert_loop_groups_data_layer_merge_weights__single(bm, groups->link, layer_n, data_tmp, loop_weights); - } while ((groups = groups->next)); + const int type = bm->ldata.layers[layer_n].type; + const int size = CustomData_sizeof(type); + void *data_tmp = alloca(size); + + do { + bm_vert_loop_groups_data_layer_merge_weights__single( + bm, groups->link, layer_n, data_tmp, loop_weights); + } while ((groups = groups->next)); } /** \} */ diff --git a/source/blender/bmesh/intern/bmesh_interp.h b/source/blender/bmesh/intern/bmesh_interp.h index ce6eb2186c5..bd3824ed3fd 100644 --- a/source/blender/bmesh/intern/bmesh_interp.h +++ b/source/blender/bmesh/intern/bmesh_interp.h @@ -24,51 +24,63 @@ struct LinkNode; struct MemArena; -void BM_loop_interp_multires_ex( - BMesh *bm, BMLoop *l_dst, const BMFace *f_src, - const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset); -void BM_loop_interp_multires( - BMesh *bm, BMLoop *l_dst, const BMFace *f_src); +void BM_loop_interp_multires_ex(BMesh *bm, + BMLoop *l_dst, + const BMFace *f_src, + const float f_dst_center[3], + const float f_src_center[3], + const int cd_loop_mdisp_offset); +void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src); -void BM_face_interp_multires_ex( - BMesh *UNUSED(bm), BMFace *f_dst, const BMFace *f_src, - const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset); +void BM_face_interp_multires_ex(BMesh *UNUSED(bm), + BMFace *f_dst, + const BMFace *f_src, + const float f_dst_center[3], + const float f_src_center[3], + const int cd_loop_mdisp_offset); void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src); -void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src); +void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src); -void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac); -void BM_data_interp_from_edges(BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac); -void BM_data_interp_face_vert_edge(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v, BMEdge *e, const float fac); -void BM_data_layer_add(BMesh *bm, CustomData *data, int type); -void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name); -void BM_data_layer_free(BMesh *bm, CustomData *data, int type); -void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n); -void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n); +void BM_data_interp_from_verts( + BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac); +void BM_data_interp_from_edges( + BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac); +void BM_data_interp_face_vert_edge(BMesh *bm, + const BMVert *v_src_1, + const BMVert *v_src_2, + BMVert *v, + BMEdge *e, + const float fac); +void BM_data_layer_add(BMesh *bm, CustomData *data, int type); +void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name); +void BM_data_layer_free(BMesh *bm, CustomData *data, int type); +void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n); +void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n); float BM_elem_float_data_get(CustomData *cd, void *element, int type); -void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val); +void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val); -void BM_face_interp_from_face_ex( - BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex, - const void **blocks, const void **blocks_v, - float (*cos_2d)[2], float axis_mat[3][3]); -void BM_face_interp_from_face( - BMesh *bm, BMFace *f_dst, const BMFace *f_src, - const bool do_vertex); -void BM_loop_interp_from_face( - BMesh *bm, BMLoop *l_dst, const BMFace *f_src, - const bool do_vertex, const bool do_multires); +void BM_face_interp_from_face_ex(BMesh *bm, + BMFace *f_dst, + const BMFace *f_src, + const bool do_vertex, + const void **blocks, + const void **blocks_v, + float (*cos_2d)[2], + float axis_mat[3][3]); +void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex); +void BM_loop_interp_from_face( + BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires); -void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f); +void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f); struct LinkNode *BM_vert_loop_groups_data_layer_create( - BMesh *bm, BMVert *v, const int layer_n, - const float *loop_weights, struct MemArena *arena); -void BM_vert_loop_groups_data_layer_merge( - BMesh *bm, struct LinkNode *groups, const int layer_n); -void BM_vert_loop_groups_data_layer_merge_weights( - BMesh *bm, struct LinkNode *groups, const int layer_n, - const float *loop_weights); + BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, struct MemArena *arena); +void BM_vert_loop_groups_data_layer_merge(BMesh *bm, struct LinkNode *groups, const int layer_n); +void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm, + struct LinkNode *groups, + const int layer_n, + const float *loop_weights); #endif /* __BMESH_INTERP_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 31e0fc00f59..b1e20dd6058 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -31,20 +31,20 @@ #include "intern/bmesh_private.h" const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = { - '\0', - BM_VERT, /* BM_VERTS_OF_MESH */ - BM_EDGE, /* BM_EDGES_OF_MESH */ - BM_FACE, /* BM_FACES_OF_MESH */ - BM_EDGE, /* BM_EDGES_OF_VERT */ - BM_FACE, /* BM_FACES_OF_VERT */ - BM_LOOP, /* BM_LOOPS_OF_VERT */ - BM_VERT, /* BM_VERTS_OF_EDGE */ - BM_FACE, /* BM_FACES_OF_EDGE */ - BM_VERT, /* BM_VERTS_OF_FACE */ - BM_EDGE, /* BM_EDGES_OF_FACE */ - BM_LOOP, /* BM_LOOPS_OF_FACE */ - BM_LOOP, /* BM_LOOPS_OF_LOOP */ - BM_LOOP, /* BM_LOOPS_OF_EDGE */ + '\0', + BM_VERT, /* BM_VERTS_OF_MESH */ + BM_EDGE, /* BM_EDGES_OF_MESH */ + BM_FACE, /* BM_FACES_OF_MESH */ + BM_EDGE, /* BM_EDGES_OF_VERT */ + BM_FACE, /* BM_FACES_OF_VERT */ + BM_LOOP, /* BM_LOOPS_OF_VERT */ + BM_VERT, /* BM_VERTS_OF_EDGE */ + BM_FACE, /* BM_FACES_OF_EDGE */ + BM_VERT, /* BM_VERTS_OF_FACE */ + BM_EDGE, /* BM_EDGES_OF_FACE */ + BM_LOOP, /* BM_LOOPS_OF_FACE */ + BM_LOOP, /* BM_LOOPS_OF_LOOP */ + BM_LOOP, /* BM_LOOPS_OF_EDGE */ }; /** @@ -52,25 +52,25 @@ const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = { */ int BM_iter_mesh_count(const char itype, BMesh *bm) { - int count; + int count; - switch (itype) { - case BM_VERTS_OF_MESH: - count = bm->totvert; - break; - case BM_EDGES_OF_MESH: - count = bm->totedge; - break; - case BM_FACES_OF_MESH: - count = bm->totface; - break; - default: - count = 0; - BLI_assert(0); - break; - } + switch (itype) { + case BM_VERTS_OF_MESH: + count = bm->totvert; + break; + case BM_EDGES_OF_MESH: + count = bm->totedge; + break; + case BM_FACES_OF_MESH: + count = bm->totface; + break; + default: + count = 0; + BLI_assert(0); + break; + } - return count; + return count; } /** @@ -78,27 +78,26 @@ int BM_iter_mesh_count(const char itype, BMesh *bm) */ void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) { - BMIter iter; - void *val; - int i; + BMIter iter; + void *val; + int i; - /* sanity check */ - if (index < 0) { - return NULL; - } + /* sanity check */ + if (index < 0) { + return NULL; + } - val = BM_iter_new(&iter, bm, itype, data); + val = BM_iter_new(&iter, bm, itype, data); - i = 0; - while (i < index) { - val = BM_iter_step(&iter); - i++; - } + i = 0; + while (i < index) { + val = BM_iter_step(&iter); + i++; + } - return val; + return val; } - /** * \brief Iterator as Array * @@ -107,53 +106,55 @@ void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) */ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len) { - int i = 0; + int i = 0; - /* sanity check */ - if (len > 0) { - BMIter iter; - void *ele; + /* sanity check */ + if (len > 0) { + BMIter iter; + void *ele; - for (ele = BM_iter_new(&iter, bm, itype, data); ele; ele = BM_iter_step(&iter)) { - array[i] = ele; - i++; - if (i == len) { - return len; - } - } - } + for (ele = BM_iter_new(&iter, bm, itype, data); ele; ele = BM_iter_step(&iter)) { + array[i] = ele; + i++; + if (i == len) { + return len; + } + } + } - return i; + return i; } /** * \brief Operator Iterator as Array * * Sometimes its convenient to get the iterator as an array. */ -int BMO_iter_as_array( - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - void **array, const int len) +int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char restrictmask, + void **array, + const int len) { - int i = 0; + int i = 0; - /* sanity check */ - if (len > 0) { - BMOIter oiter; - void *ele; + /* sanity check */ + if (len > 0) { + BMOIter oiter; + void *ele; - for (ele = BMO_iter_new(&oiter, slot_args, slot_name, restrictmask); ele; ele = BMO_iter_step(&oiter)) { - array[i] = ele; - i++; - if (i == len) { - return len; - } - } - } + for (ele = BMO_iter_new(&oiter, slot_args, slot_name, restrictmask); ele; + ele = BMO_iter_step(&oiter)) { + array[i] = ele; + i++; + if (i == len) { + return len; + } + } + } - return i; + return i; } - /** * \brief Iterator as Array * @@ -164,143 +165,146 @@ int BMO_iter_as_array( * * Caller needs to free the array. */ -void *BM_iter_as_arrayN( - BMesh *bm, const char itype, void *data, int *r_len, - /* optional args to avoid an alloc (normally stack array) */ - void **stack_array, int stack_array_size) -{ - BMIter iter; - - BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array)); - - /* we can't rely on coun't being set */ - switch (itype) { - case BM_VERTS_OF_MESH: - iter.count = bm->totvert; - break; - case BM_EDGES_OF_MESH: - iter.count = bm->totedge; - break; - case BM_FACES_OF_MESH: - iter.count = bm->totface; - break; - default: - break; - } - - if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) { - BMElem *ele; - BMElem **array = iter.count > stack_array_size ? - MEM_mallocN(sizeof(ele) * iter.count, __func__) : - stack_array; - int i = 0; - - *r_len = iter.count; /* set before iterating */ - - while ((ele = BM_iter_step(&iter))) { - array[i++] = ele; - } - return array; - } - else { - *r_len = 0; - return NULL; - } -} - -void *BMO_iter_as_arrayN( - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - int *r_len, - /* optional args to avoid an alloc (normally stack array) */ - void **stack_array, int stack_array_size) -{ - BMOIter iter; - BMElem *ele; - int count = BMO_slot_buffer_count(slot_args, slot_name); - - BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array)); - - if ((ele = BMO_iter_new(&iter, slot_args, slot_name, restrictmask)) && count > 0) { - BMElem **array = count > stack_array_size ? - MEM_mallocN(sizeof(ele) * count, __func__) : - stack_array; - int i = 0; - - do { - array[i++] = ele; - } while ((ele = BMO_iter_step(&iter))); - BLI_assert(i <= count); - - if (i != count) { - if ((void **)array != stack_array) { - array = MEM_reallocN(array, sizeof(ele) * i); - } - } - *r_len = i; - return array; - } - else { - *r_len = 0; - return NULL; - } -} - -int BM_iter_mesh_bitmap_from_filter( - const char itype, BMesh *bm, - BLI_bitmap *bitmap, - bool (*test_fn)(BMElem *, void *user_data), - void *user_data) -{ - BMIter iter; - BMElem *ele; - int i; - int bitmap_enabled = 0; - - BM_ITER_MESH_INDEX (ele, &iter, bm, itype, i) { - if (test_fn(ele, user_data)) { - BLI_BITMAP_ENABLE(bitmap, i); - bitmap_enabled++; - } - else { - BLI_BITMAP_DISABLE(bitmap, i); - } - } - - return bitmap_enabled; +void *BM_iter_as_arrayN(BMesh *bm, + const char itype, + void *data, + int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, + int stack_array_size) +{ + BMIter iter; + + BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array)); + + /* we can't rely on coun't being set */ + switch (itype) { + case BM_VERTS_OF_MESH: + iter.count = bm->totvert; + break; + case BM_EDGES_OF_MESH: + iter.count = bm->totedge; + break; + case BM_FACES_OF_MESH: + iter.count = bm->totface; + break; + default: + break; + } + + if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) { + BMElem *ele; + BMElem **array = iter.count > stack_array_size ? + MEM_mallocN(sizeof(ele) * iter.count, __func__) : + stack_array; + int i = 0; + + *r_len = iter.count; /* set before iterating */ + + while ((ele = BM_iter_step(&iter))) { + array[i++] = ele; + } + return array; + } + else { + *r_len = 0; + return NULL; + } +} + +void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char restrictmask, + int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, + int stack_array_size) +{ + BMOIter iter; + BMElem *ele; + int count = BMO_slot_buffer_count(slot_args, slot_name); + + BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array)); + + if ((ele = BMO_iter_new(&iter, slot_args, slot_name, restrictmask)) && count > 0) { + BMElem **array = count > stack_array_size ? MEM_mallocN(sizeof(ele) * count, __func__) : + stack_array; + int i = 0; + + do { + array[i++] = ele; + } while ((ele = BMO_iter_step(&iter))); + BLI_assert(i <= count); + + if (i != count) { + if ((void **)array != stack_array) { + array = MEM_reallocN(array, sizeof(ele) * i); + } + } + *r_len = i; + return array; + } + else { + *r_len = 0; + return NULL; + } +} + +int BM_iter_mesh_bitmap_from_filter(const char itype, + BMesh *bm, + BLI_bitmap *bitmap, + bool (*test_fn)(BMElem *, void *user_data), + void *user_data) +{ + BMIter iter; + BMElem *ele; + int i; + int bitmap_enabled = 0; + + BM_ITER_MESH_INDEX (ele, &iter, bm, itype, i) { + if (test_fn(ele, user_data)) { + BLI_BITMAP_ENABLE(bitmap, i); + bitmap_enabled++; + } + else { + BLI_BITMAP_DISABLE(bitmap, i); + } + } + + return bitmap_enabled; } /** * Needed when we want to check faces, but return a loop aligned array. */ -int BM_iter_mesh_bitmap_from_filter_tessface( - BMesh *bm, - BLI_bitmap *bitmap, - bool (*test_fn)(BMFace *, void *user_data), - void *user_data) -{ - BMIter iter; - BMFace *f; - int i; - int j = 0; - int bitmap_enabled = 0; - - BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { - if (test_fn(f, user_data)) { - for (int tri = 2; tri < f->len; tri++) { - BLI_BITMAP_ENABLE(bitmap, j); - bitmap_enabled++; - j++; - } - } - else { - for (int tri = 2; tri < f->len; tri++) { - BLI_BITMAP_DISABLE(bitmap, j); - j++; - } - } - } - - return bitmap_enabled; +int BM_iter_mesh_bitmap_from_filter_tessface(BMesh *bm, + BLI_bitmap *bitmap, + bool (*test_fn)(BMFace *, void *user_data), + void *user_data) +{ + BMIter iter; + BMFace *f; + int i; + int j = 0; + int bitmap_enabled = 0; + + BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { + if (test_fn(f, user_data)) { + for (int tri = 2; tri < f->len; tri++) { + BLI_BITMAP_ENABLE(bitmap, j); + bitmap_enabled++; + j++; + } + } + else { + for (int tri = 2; tri < f->len; tri++) { + BLI_BITMAP_DISABLE(bitmap, j); + j++; + } + } + } + + return bitmap_enabled; } /** @@ -310,17 +314,17 @@ int BM_iter_mesh_bitmap_from_filter_tessface( */ int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value) { - BMIter iter; - BMElem *ele; - int count = 0; + BMIter iter; + BMElem *ele; + int count = 0; - BM_ITER_ELEM (ele, &iter, data, itype) { - if (BM_elem_flag_test_bool(ele, hflag) == value) { - count++; - } - } + BM_ITER_ELEM (ele, &iter, data, itype) { + if (BM_elem_flag_test_bool(ele, hflag) == value) { + count++; + } + } - return count; + return count; } /** @@ -329,52 +333,46 @@ int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, cons * Counts how many flagged / unflagged items are found in this element. */ int BMO_iter_elem_count_flag( - BMesh *bm, const char itype, void *data, - const short oflag, const bool value) -{ - BMIter iter; - int count = 0; - - /* loops have no header flags */ - BLI_assert(bm_iter_itype_htype_map[itype] != BM_LOOP); - - switch (bm_iter_itype_htype_map[itype]) { - case BM_VERT: - { - BMVert *ele; - BM_ITER_ELEM (ele, &iter, data, itype) { - if (BMO_vert_flag_test_bool(bm, ele, oflag) == value) { - count++; - } - } - break; - } - case BM_EDGE: - { - BMEdge *ele; - BM_ITER_ELEM (ele, &iter, data, itype) { - if (BMO_edge_flag_test_bool(bm, ele, oflag) == value) { - count++; - } - } - break; - } - case BM_FACE: - { - BMFace *ele; - BM_ITER_ELEM (ele, &iter, data, itype) { - if (BMO_face_flag_test_bool(bm, ele, oflag) == value) { - count++; - } - } - break; - } - - } - return count; + BMesh *bm, const char itype, void *data, const short oflag, const bool value) +{ + BMIter iter; + int count = 0; + + /* loops have no header flags */ + BLI_assert(bm_iter_itype_htype_map[itype] != BM_LOOP); + + switch (bm_iter_itype_htype_map[itype]) { + case BM_VERT: { + BMVert *ele; + BM_ITER_ELEM (ele, &iter, data, itype) { + if (BMO_vert_flag_test_bool(bm, ele, oflag) == value) { + count++; + } + } + break; + } + case BM_EDGE: { + BMEdge *ele; + BM_ITER_ELEM (ele, &iter, data, itype) { + if (BMO_edge_flag_test_bool(bm, ele, oflag) == value) { + count++; + } + } + break; + } + case BM_FACE: { + BMFace *ele; + BM_ITER_ELEM (ele, &iter, data, itype) { + if (BMO_face_flag_test_bool(bm, ele, oflag) == value) { + count++; + } + } + break; + } + } + return count; } - /** * \brief Mesh Iter Flag Count * @@ -382,17 +380,17 @@ int BMO_iter_elem_count_flag( */ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value) { - BMIter iter; - BMElem *ele; - int count = 0; + BMIter iter; + BMElem *ele; + int count = 0; - BM_ITER_MESH (ele, &iter, bm, itype) { - if (BM_elem_flag_test_bool(ele, hflag) == value) { - count++; - } - } + BM_ITER_MESH (ele, &iter, bm, itype) { + if (BM_elem_flag_test_bool(ele, hflag) == value) { + count++; + } + } - return count; + return count; } /** @@ -424,17 +422,17 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const void bmiter__elem_of_mesh_begin(struct BMIter__elem_of_mesh *iter) { #ifdef USE_IMMUTABLE_ASSERT - ((BMIter *)iter)->count = BLI_mempool_len(iter->pooliter.pool); + ((BMIter *)iter)->count = BLI_mempool_len(iter->pooliter.pool); #endif - BLI_mempool_iternew(iter->pooliter.pool, &iter->pooliter); + BLI_mempool_iternew(iter->pooliter.pool, &iter->pooliter); } void *bmiter__elem_of_mesh_step(struct BMIter__elem_of_mesh *iter) { #ifdef USE_IMMUTABLE_ASSERT - BLI_assert(((BMIter *)iter)->count <= BLI_mempool_len(iter->pooliter.pool)); + BLI_assert(((BMIter *)iter)->count <= BLI_mempool_len(iter->pooliter.pool)); #endif - return BLI_mempool_iterstep(&iter->pooliter); + return BLI_mempool_iterstep(&iter->pooliter); } #ifdef USE_IMMUTABLE_ASSERT @@ -445,274 +443,273 @@ void *bmiter__elem_of_mesh_step(struct BMIter__elem_of_mesh *iter) * EDGE OF VERT CALLBACKS */ -void bmiter__edge_of_vert_begin(struct BMIter__edge_of_vert *iter) +void bmiter__edge_of_vert_begin(struct BMIter__edge_of_vert *iter) { - if (iter->vdata->e) { - iter->e_first = iter->vdata->e; - iter->e_next = iter->vdata->e; - } - else { - iter->e_first = NULL; - iter->e_next = NULL; - } + if (iter->vdata->e) { + iter->e_first = iter->vdata->e; + iter->e_next = iter->vdata->e; + } + else { + iter->e_first = NULL; + iter->e_next = NULL; + } } -void *bmiter__edge_of_vert_step(struct BMIter__edge_of_vert *iter) +void *bmiter__edge_of_vert_step(struct BMIter__edge_of_vert *iter) { - BMEdge *e_curr = iter->e_next; + BMEdge *e_curr = iter->e_next; - if (iter->e_next) { - iter->e_next = bmesh_disk_edge_next(iter->e_next, iter->vdata); - if (iter->e_next == iter->e_first) { - iter->e_next = NULL; - } - } + if (iter->e_next) { + iter->e_next = bmesh_disk_edge_next(iter->e_next, iter->vdata); + if (iter->e_next == iter->e_first) { + iter->e_next = NULL; + } + } - return e_curr; + return e_curr; } /* * FACE OF VERT CALLBACKS */ -void bmiter__face_of_vert_begin(struct BMIter__face_of_vert *iter) +void bmiter__face_of_vert_begin(struct BMIter__face_of_vert *iter) { - ((BMIter *)iter)->count = bmesh_disk_facevert_count(iter->vdata); - if (((BMIter *)iter)->count) { - iter->l_first = bmesh_disk_faceloop_find_first(iter->vdata->e, iter->vdata); - iter->e_first = iter->l_first->e; - iter->e_next = iter->e_first; - iter->l_next = iter->l_first; - } - else { - iter->l_first = iter->l_next = NULL; - iter->e_first = iter->e_next = NULL; - } + ((BMIter *)iter)->count = bmesh_disk_facevert_count(iter->vdata); + if (((BMIter *)iter)->count) { + iter->l_first = bmesh_disk_faceloop_find_first(iter->vdata->e, iter->vdata); + iter->e_first = iter->l_first->e; + iter->e_next = iter->e_first; + iter->l_next = iter->l_first; + } + else { + iter->l_first = iter->l_next = NULL; + iter->e_first = iter->e_next = NULL; + } } -void *bmiter__face_of_vert_step(struct BMIter__face_of_vert *iter) +void *bmiter__face_of_vert_step(struct BMIter__face_of_vert *iter) { - BMLoop *l_curr = iter->l_next; + BMLoop *l_curr = iter->l_next; - if (((BMIter *)iter)->count && iter->l_next) { - ((BMIter *)iter)->count--; - iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata); - if (iter->l_next == iter->l_first) { - iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata); - iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata); - iter->l_next = iter->l_first; - } - } + if (((BMIter *)iter)->count && iter->l_next) { + ((BMIter *)iter)->count--; + iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata); + if (iter->l_next == iter->l_first) { + iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata); + iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata); + iter->l_next = iter->l_first; + } + } - if (!((BMIter *)iter)->count) { - iter->l_next = NULL; - } + if (!((BMIter *)iter)->count) { + iter->l_next = NULL; + } - return l_curr ? l_curr->f : NULL; + return l_curr ? l_curr->f : NULL; } - /* * LOOP OF VERT CALLBACKS */ -void bmiter__loop_of_vert_begin(struct BMIter__loop_of_vert *iter) +void bmiter__loop_of_vert_begin(struct BMIter__loop_of_vert *iter) { - ((BMIter *)iter)->count = bmesh_disk_facevert_count(iter->vdata); - if (((BMIter *)iter)->count) { - iter->l_first = bmesh_disk_faceloop_find_first(iter->vdata->e, iter->vdata); - iter->e_first = iter->l_first->e; - iter->e_next = iter->e_first; - iter->l_next = iter->l_first; - } - else { - iter->l_first = iter->l_next = NULL; - iter->e_first = iter->e_next = NULL; - } + ((BMIter *)iter)->count = bmesh_disk_facevert_count(iter->vdata); + if (((BMIter *)iter)->count) { + iter->l_first = bmesh_disk_faceloop_find_first(iter->vdata->e, iter->vdata); + iter->e_first = iter->l_first->e; + iter->e_next = iter->e_first; + iter->l_next = iter->l_first; + } + else { + iter->l_first = iter->l_next = NULL; + iter->e_first = iter->e_next = NULL; + } } -void *bmiter__loop_of_vert_step(struct BMIter__loop_of_vert *iter) +void *bmiter__loop_of_vert_step(struct BMIter__loop_of_vert *iter) { - BMLoop *l_curr = iter->l_next; + BMLoop *l_curr = iter->l_next; - if (((BMIter *)iter)->count) { - ((BMIter *)iter)->count--; - iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata); - if (iter->l_next == iter->l_first) { - iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata); - iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata); - iter->l_next = iter->l_first; - } - } + if (((BMIter *)iter)->count) { + ((BMIter *)iter)->count--; + iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata); + if (iter->l_next == iter->l_first) { + iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata); + iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata); + iter->l_next = iter->l_first; + } + } - if (!((BMIter *)iter)->count) { - iter->l_next = NULL; - } + if (!((BMIter *)iter)->count) { + iter->l_next = NULL; + } - /* NULL on finish */ - return l_curr; + /* NULL on finish */ + return l_curr; } /* * LOOP OF EDGE CALLBACKS */ -void bmiter__loop_of_edge_begin(struct BMIter__loop_of_edge *iter) +void bmiter__loop_of_edge_begin(struct BMIter__loop_of_edge *iter) { - iter->l_first = iter->l_next = iter->edata->l; + iter->l_first = iter->l_next = iter->edata->l; } -void *bmiter__loop_of_edge_step(struct BMIter__loop_of_edge *iter) +void *bmiter__loop_of_edge_step(struct BMIter__loop_of_edge *iter) { - BMLoop *l_curr = iter->l_next; + BMLoop *l_curr = iter->l_next; - if (iter->l_next) { - iter->l_next = iter->l_next->radial_next; - if (iter->l_next == iter->l_first) { - iter->l_next = NULL; - } - } + if (iter->l_next) { + iter->l_next = iter->l_next->radial_next; + if (iter->l_next == iter->l_first) { + iter->l_next = NULL; + } + } - /* NULL on finish */ - return l_curr; + /* NULL on finish */ + return l_curr; } /* * LOOP OF LOOP CALLBACKS */ -void bmiter__loop_of_loop_begin(struct BMIter__loop_of_loop *iter) +void bmiter__loop_of_loop_begin(struct BMIter__loop_of_loop *iter) { - iter->l_first = iter->ldata; - iter->l_next = iter->l_first->radial_next; + iter->l_first = iter->ldata; + iter->l_next = iter->l_first->radial_next; - if (iter->l_next == iter->l_first) { - iter->l_next = NULL; - } + if (iter->l_next == iter->l_first) { + iter->l_next = NULL; + } } -void *bmiter__loop_of_loop_step(struct BMIter__loop_of_loop *iter) +void *bmiter__loop_of_loop_step(struct BMIter__loop_of_loop *iter) { - BMLoop *l_curr = iter->l_next; + BMLoop *l_curr = iter->l_next; - if (iter->l_next) { - iter->l_next = iter->l_next->radial_next; - if (iter->l_next == iter->l_first) { - iter->l_next = NULL; - } - } + if (iter->l_next) { + iter->l_next = iter->l_next->radial_next; + if (iter->l_next == iter->l_first) { + iter->l_next = NULL; + } + } - /* NULL on finish */ - return l_curr; + /* NULL on finish */ + return l_curr; } /* * FACE OF EDGE CALLBACKS */ -void bmiter__face_of_edge_begin(struct BMIter__face_of_edge *iter) +void bmiter__face_of_edge_begin(struct BMIter__face_of_edge *iter) { - iter->l_first = iter->l_next = iter->edata->l; + iter->l_first = iter->l_next = iter->edata->l; } -void *bmiter__face_of_edge_step(struct BMIter__face_of_edge *iter) +void *bmiter__face_of_edge_step(struct BMIter__face_of_edge *iter) { - BMLoop *current = iter->l_next; + BMLoop *current = iter->l_next; - if (iter->l_next) { - iter->l_next = iter->l_next->radial_next; - if (iter->l_next == iter->l_first) { - iter->l_next = NULL; - } - } + if (iter->l_next) { + iter->l_next = iter->l_next->radial_next; + if (iter->l_next == iter->l_first) { + iter->l_next = NULL; + } + } - return current ? current->f : NULL; + return current ? current->f : NULL; } /* * VERTS OF EDGE CALLBACKS */ -void bmiter__vert_of_edge_begin(struct BMIter__vert_of_edge *iter) +void bmiter__vert_of_edge_begin(struct BMIter__vert_of_edge *iter) { - ((BMIter *)iter)->count = 0; + ((BMIter *)iter)->count = 0; } -void *bmiter__vert_of_edge_step(struct BMIter__vert_of_edge *iter) +void *bmiter__vert_of_edge_step(struct BMIter__vert_of_edge *iter) { - switch (((BMIter *)iter)->count++) { - case 0: - return iter->edata->v1; - case 1: - return iter->edata->v2; - default: - return NULL; - } + switch (((BMIter *)iter)->count++) { + case 0: + return iter->edata->v1; + case 1: + return iter->edata->v2; + default: + return NULL; + } } /* * VERT OF FACE CALLBACKS */ -void bmiter__vert_of_face_begin(struct BMIter__vert_of_face *iter) +void bmiter__vert_of_face_begin(struct BMIter__vert_of_face *iter) { - iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata); + iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata); } -void *bmiter__vert_of_face_step(struct BMIter__vert_of_face *iter) +void *bmiter__vert_of_face_step(struct BMIter__vert_of_face *iter) { - BMLoop *l_curr = iter->l_next; + BMLoop *l_curr = iter->l_next; - if (iter->l_next) { - iter->l_next = iter->l_next->next; - if (iter->l_next == iter->l_first) { - iter->l_next = NULL; - } - } + if (iter->l_next) { + iter->l_next = iter->l_next->next; + if (iter->l_next == iter->l_first) { + iter->l_next = NULL; + } + } - return l_curr ? l_curr->v : NULL; + return l_curr ? l_curr->v : NULL; } /* * EDGE OF FACE CALLBACKS */ -void bmiter__edge_of_face_begin(struct BMIter__edge_of_face *iter) +void bmiter__edge_of_face_begin(struct BMIter__edge_of_face *iter) { - iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata); + iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata); } -void *bmiter__edge_of_face_step(struct BMIter__edge_of_face *iter) +void *bmiter__edge_of_face_step(struct BMIter__edge_of_face *iter) { - BMLoop *l_curr = iter->l_next; + BMLoop *l_curr = iter->l_next; - if (iter->l_next) { - iter->l_next = iter->l_next->next; - if (iter->l_next == iter->l_first) { - iter->l_next = NULL; - } - } + if (iter->l_next) { + iter->l_next = iter->l_next->next; + if (iter->l_next == iter->l_first) { + iter->l_next = NULL; + } + } - return l_curr ? l_curr->e : NULL; + return l_curr ? l_curr->e : NULL; } /* * LOOP OF FACE CALLBACKS */ -void bmiter__loop_of_face_begin(struct BMIter__loop_of_face *iter) +void bmiter__loop_of_face_begin(struct BMIter__loop_of_face *iter) { - iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata); + iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata); } -void *bmiter__loop_of_face_step(struct BMIter__loop_of_face *iter) +void *bmiter__loop_of_face_step(struct BMIter__loop_of_face *iter) { - BMLoop *l_curr = iter->l_next; + BMLoop *l_curr = iter->l_next; - if (iter->l_next) { - iter->l_next = iter->l_next->next; - if (iter->l_next == iter->l_first) { - iter->l_next = NULL; - } - } + if (iter->l_next) { + iter->l_next = iter->l_next->next; + if (iter->l_next == iter->l_first) { + iter->l_next = NULL; + } + } - return l_curr; + return l_curr; } diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 73784dabea8..a809c9a3d32 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -48,27 +48,27 @@ * be sure to keep 'bm_iter_itype_htype_map' in sync with any changes */ typedef enum BMIterType { - BM_VERTS_OF_MESH = 1, - BM_EDGES_OF_MESH = 2, - BM_FACES_OF_MESH = 3, - /* these are topological iterators. */ - BM_EDGES_OF_VERT = 4, - BM_FACES_OF_VERT = 5, - BM_LOOPS_OF_VERT = 6, - BM_VERTS_OF_EDGE = 7, /* just v1, v2: added so py can use generalized sequencer wrapper */ - BM_FACES_OF_EDGE = 8, - BM_VERTS_OF_FACE = 9, - BM_EDGES_OF_FACE = 10, - BM_LOOPS_OF_FACE = 11, - /* returns elements from all boundaries, and returns - * the first element at the end to flag that we're entering - * a different face hole boundary*/ - // BM_ALL_LOOPS_OF_FACE = 12, - /* iterate through loops around this loop, which are fetched - * from the other faces in the radial cycle surrounding the - * input loop's edge.*/ - BM_LOOPS_OF_LOOP = 12, - BM_LOOPS_OF_EDGE = 13, + BM_VERTS_OF_MESH = 1, + BM_EDGES_OF_MESH = 2, + BM_FACES_OF_MESH = 3, + /* these are topological iterators. */ + BM_EDGES_OF_VERT = 4, + BM_FACES_OF_VERT = 5, + BM_LOOPS_OF_VERT = 6, + BM_VERTS_OF_EDGE = 7, /* just v1, v2: added so py can use generalized sequencer wrapper */ + BM_FACES_OF_EDGE = 8, + BM_VERTS_OF_FACE = 9, + BM_EDGES_OF_FACE = 10, + BM_LOOPS_OF_FACE = 11, + /* returns elements from all boundaries, and returns + * the first element at the end to flag that we're entering + * a different face hole boundary*/ + // BM_ALL_LOOPS_OF_FACE = 12, + /* iterate through loops around this loop, which are fetched + * from the other faces in the radial cycle surrounding the + * input loop's edge.*/ + BM_LOOPS_OF_LOOP = 12, + BM_LOOPS_OF_EDGE = 13, } BMIterType; #define BM_ITYPE_MAX 14 @@ -77,153 +77,157 @@ typedef enum BMIterType { extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX]; #define BM_ITER_MESH(ele, iter, bm, itype) \ - for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \ - ele; \ - BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter)) + for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); ele; \ + BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter)) #define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar) \ - for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; \ - ele; \ - BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++) + for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; ele; \ + BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++) /* a version of BM_ITER_MESH which keeps the next item in storage * so we can delete the current item, see bug [#36923] */ #ifdef DEBUG # define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \ - for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \ - ele ? ((void)((iter)->count = BM_iter_mesh_count(itype, bm)), \ - (void)(ele_next = BM_iter_step(iter)), 1) : 0; \ - BM_CHECK_TYPE_ELEM_ASSIGN(ele) = ele_next) + for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \ + ele ? ((void)((iter)->count = BM_iter_mesh_count(itype, bm)), \ + (void)(ele_next = BM_iter_step(iter)), \ + 1) : \ + 0; \ + BM_CHECK_TYPE_ELEM_ASSIGN(ele) = ele_next) #else # define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \ - for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \ - ele ? ((BM_CHECK_TYPE_ELEM_ASSIGN(ele_next) = BM_iter_step(iter)), 1) : 0; \ - ele = ele_next) + for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \ + ele ? ((BM_CHECK_TYPE_ELEM_ASSIGN(ele_next) = BM_iter_step(iter)), 1) : 0; \ + ele = ele_next) #endif - #define BM_ITER_ELEM(ele, iter, data, itype) \ - for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data); \ - ele; \ - BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter)) + for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data); ele; \ + BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter)) #define BM_ITER_ELEM_INDEX(ele, iter, data, itype, indexvar) \ - for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data), indexvar = 0; \ - ele; \ - BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++) + for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data), indexvar = 0; ele; \ + BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++) /* iterator type structs */ struct BMIter__elem_of_mesh { - BLI_mempool_iter pooliter; + BLI_mempool_iter pooliter; }; struct BMIter__edge_of_vert { - BMVert *vdata; - BMEdge *e_first, *e_next; + BMVert *vdata; + BMEdge *e_first, *e_next; }; struct BMIter__face_of_vert { - BMVert *vdata; - BMLoop *l_first, *l_next; - BMEdge *e_first, *e_next; + BMVert *vdata; + BMLoop *l_first, *l_next; + BMEdge *e_first, *e_next; }; struct BMIter__loop_of_vert { - BMVert *vdata; - BMLoop *l_first, *l_next; - BMEdge *e_first, *e_next; + BMVert *vdata; + BMLoop *l_first, *l_next; + BMEdge *e_first, *e_next; }; struct BMIter__loop_of_edge { - BMEdge *edata; - BMLoop *l_first, *l_next; + BMEdge *edata; + BMLoop *l_first, *l_next; }; struct BMIter__loop_of_loop { - BMLoop *ldata; - BMLoop *l_first, *l_next; + BMLoop *ldata; + BMLoop *l_first, *l_next; }; struct BMIter__face_of_edge { - BMEdge *edata; - BMLoop *l_first, *l_next; + BMEdge *edata; + BMLoop *l_first, *l_next; }; struct BMIter__vert_of_edge { - BMEdge *edata; + BMEdge *edata; }; struct BMIter__vert_of_face { - BMFace *pdata; - BMLoop *l_first, *l_next; + BMFace *pdata; + BMLoop *l_first, *l_next; }; struct BMIter__edge_of_face { - BMFace *pdata; - BMLoop *l_first, *l_next; + BMFace *pdata; + BMLoop *l_first, *l_next; }; struct BMIter__loop_of_face { - BMFace *pdata; - BMLoop *l_first, *l_next; + BMFace *pdata; + BMLoop *l_first, *l_next; }; -typedef void (*BMIter__begin_cb) (void *); -typedef void *(*BMIter__step_cb) (void *); +typedef void (*BMIter__begin_cb)(void *); +typedef void *(*BMIter__step_cb)(void *); /* Iterator Structure */ /* note: some of these vars are not used, * so they have been commented to save stack space since this struct is used all over */ typedef struct BMIter { - /* keep union first */ - union { - struct BMIter__elem_of_mesh elem_of_mesh; - - struct BMIter__edge_of_vert edge_of_vert; - struct BMIter__face_of_vert face_of_vert; - struct BMIter__loop_of_vert loop_of_vert; - struct BMIter__loop_of_edge loop_of_edge; - struct BMIter__loop_of_loop loop_of_loop; - struct BMIter__face_of_edge face_of_edge; - struct BMIter__vert_of_edge vert_of_edge; - struct BMIter__vert_of_face vert_of_face; - struct BMIter__edge_of_face edge_of_face; - struct BMIter__loop_of_face loop_of_face; - } data; - - BMIter__begin_cb begin; - BMIter__step_cb step; - - int count; /* note, only some iterators set this, don't rely on it */ - char itype; + /* keep union first */ + union { + struct BMIter__elem_of_mesh elem_of_mesh; + + struct BMIter__edge_of_vert edge_of_vert; + struct BMIter__face_of_vert face_of_vert; + struct BMIter__loop_of_vert loop_of_vert; + struct BMIter__loop_of_edge loop_of_edge; + struct BMIter__loop_of_loop loop_of_loop; + struct BMIter__face_of_edge face_of_edge; + struct BMIter__vert_of_edge vert_of_edge; + struct BMIter__vert_of_face vert_of_face; + struct BMIter__edge_of_face edge_of_face; + struct BMIter__loop_of_face loop_of_face; + } data; + + BMIter__begin_cb begin; + BMIter__step_cb step; + + int count; /* note, only some iterators set this, don't rely on it */ + char itype; } BMIter; -void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT; -int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); -void *BM_iter_as_arrayN( - BMesh *bm, const char itype, void *data, int *r_len, - void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT; -int BMO_iter_as_array( - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - void **array, const int len); -void *BMO_iter_as_arrayN( - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - int *r_len, - /* optional args to avoid an alloc (normally stack array) */ - void **stack_array, int stack_array_size); - -int BM_iter_mesh_bitmap_from_filter( - const char itype, BMesh *bm, - uint *bitmap, - bool (*test_fn)(BMElem *, void *user_data), - void *user_data); -int BM_iter_mesh_bitmap_from_filter_tessface( - BMesh *bm, - uint *bitmap, - bool (*test_fn)(BMFace *, void *user_data), - void *user_data); - -int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value); -int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, const short oflag, const bool value); -int BM_iter_mesh_count(const char itype, BMesh *bm); -int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value); +void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT; +int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); +void *BM_iter_as_arrayN(BMesh *bm, + const char itype, + void *data, + int *r_len, + void **stack_array, + int stack_array_size) ATTR_WARN_UNUSED_RESULT; +int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char restrictmask, + void **array, + const int len); +void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char restrictmask, + int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, + int stack_array_size); + +int BM_iter_mesh_bitmap_from_filter(const char itype, + BMesh *bm, + uint *bitmap, + bool (*test_fn)(BMElem *, void *user_data), + void *user_data); +int BM_iter_mesh_bitmap_from_filter_tessface(BMesh *bm, + uint *bitmap, + bool (*test_fn)(BMFace *, void *user_data), + void *user_data); + +int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value); +int BMO_iter_elem_count_flag( + BMesh *bm, const char itype, void *data, const short oflag, const bool value); +int BM_iter_mesh_count(const char itype, BMesh *bm); +int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value); /* private for bmesh_iterators_inline.c */ #define BMITER_CB_DEF(name) \ - struct BMIter__##name; \ - void bmiter__##name##_begin(struct BMIter__##name *iter); \ - void *bmiter__##name##_step(struct BMIter__##name *iter) + struct BMIter__##name; \ + void bmiter__##name##_begin(struct BMIter__##name *iter); \ + void *bmiter__##name##_step(struct BMIter__##name *iter) BMITER_CB_DEF(elem_of_mesh); BMITER_CB_DEF(edge_of_vert); @@ -242,11 +246,11 @@ BMITER_CB_DEF(loop_of_face); #include "intern/bmesh_iterators_inline.h" #define BM_ITER_CHECK_TYPE_DATA(data) \ - CHECK_TYPE_ANY(data, void *, BMFace *, BMEdge *, BMVert *, BMLoop *, BMElem *) + CHECK_TYPE_ANY(data, void *, BMFace *, BMEdge *, BMVert *, BMLoop *, BMElem *) #define BM_iter_new(iter, bm, itype, data) \ - (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_new(iter, bm, itype, data)) + (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_new(iter, bm, itype, data)) #define BM_iter_init(iter, bm, itype, data) \ - (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_init(iter, bm, itype, data)) + (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_init(iter, bm, itype, data)) #endif /* __BMESH_ITERATORS_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h index 30740a1bc90..ed3a9a5be09 100644 --- a/source/blender/bmesh/intern/bmesh_iterators_inline.h +++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h @@ -31,13 +31,11 @@ * * Calls an iterators step function to return the next element. */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE void *BM_iter_step(BMIter *iter) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void *BM_iter_step(BMIter *iter) { - return iter->step(iter); + return iter->step(iter); } - /** * \brief Iterator Init * @@ -48,112 +46,112 @@ BLI_INLINE void *BM_iter_step(BMIter *iter) ATTR_NONNULL(1) BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data) { - /* int argtype; */ - iter->itype = itype; + /* int argtype; */ + iter->itype = itype; - /* inlining optimizes out this switch when called with the defined type */ - switch ((BMIterType)itype) { - case BM_VERTS_OF_MESH: - BLI_assert(bm != NULL); - BLI_assert(data == NULL); - iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin; - iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step; - iter->data.elem_of_mesh.pooliter.pool = bm->vpool; - break; - case BM_EDGES_OF_MESH: - BLI_assert(bm != NULL); - BLI_assert(data == NULL); - iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin; - iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step; - iter->data.elem_of_mesh.pooliter.pool = bm->epool; - break; - case BM_FACES_OF_MESH: - BLI_assert(bm != NULL); - BLI_assert(data == NULL); - iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin; - iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step; - iter->data.elem_of_mesh.pooliter.pool = bm->fpool; - break; - case BM_EDGES_OF_VERT: - BLI_assert(data != NULL); - BLI_assert(((BMElem *)data)->head.htype == BM_VERT); - iter->begin = (BMIter__begin_cb)bmiter__edge_of_vert_begin; - iter->step = (BMIter__step_cb)bmiter__edge_of_vert_step; - iter->data.edge_of_vert.vdata = (BMVert *)data; - break; - case BM_FACES_OF_VERT: - BLI_assert(data != NULL); - BLI_assert(((BMElem *)data)->head.htype == BM_VERT); - iter->begin = (BMIter__begin_cb)bmiter__face_of_vert_begin; - iter->step = (BMIter__step_cb)bmiter__face_of_vert_step; - iter->data.face_of_vert.vdata = (BMVert *)data; - break; - case BM_LOOPS_OF_VERT: - BLI_assert(data != NULL); - BLI_assert(((BMElem *)data)->head.htype == BM_VERT); - iter->begin = (BMIter__begin_cb)bmiter__loop_of_vert_begin; - iter->step = (BMIter__step_cb)bmiter__loop_of_vert_step; - iter->data.loop_of_vert.vdata = (BMVert *)data; - break; - case BM_VERTS_OF_EDGE: - BLI_assert(data != NULL); - BLI_assert(((BMElem *)data)->head.htype == BM_EDGE); - iter->begin = (BMIter__begin_cb)bmiter__vert_of_edge_begin; - iter->step = (BMIter__step_cb)bmiter__vert_of_edge_step; - iter->data.vert_of_edge.edata = (BMEdge *)data; - break; - case BM_FACES_OF_EDGE: - BLI_assert(data != NULL); - BLI_assert(((BMElem *)data)->head.htype == BM_EDGE); - iter->begin = (BMIter__begin_cb)bmiter__face_of_edge_begin; - iter->step = (BMIter__step_cb)bmiter__face_of_edge_step; - iter->data.face_of_edge.edata = (BMEdge *)data; - break; - case BM_VERTS_OF_FACE: - BLI_assert(data != NULL); - BLI_assert(((BMElem *)data)->head.htype == BM_FACE); - iter->begin = (BMIter__begin_cb)bmiter__vert_of_face_begin; - iter->step = (BMIter__step_cb)bmiter__vert_of_face_step; - iter->data.vert_of_face.pdata = (BMFace *)data; - break; - case BM_EDGES_OF_FACE: - BLI_assert(data != NULL); - BLI_assert(((BMElem *)data)->head.htype == BM_FACE); - iter->begin = (BMIter__begin_cb)bmiter__edge_of_face_begin; - iter->step = (BMIter__step_cb)bmiter__edge_of_face_step; - iter->data.edge_of_face.pdata = (BMFace *)data; - break; - case BM_LOOPS_OF_FACE: - BLI_assert(data != NULL); - BLI_assert(((BMElem *)data)->head.htype == BM_FACE); - iter->begin = (BMIter__begin_cb)bmiter__loop_of_face_begin; - iter->step = (BMIter__step_cb)bmiter__loop_of_face_step; - iter->data.loop_of_face.pdata = (BMFace *)data; - break; - case BM_LOOPS_OF_LOOP: - BLI_assert(data != NULL); - BLI_assert(((BMElem *)data)->head.htype == BM_LOOP); - iter->begin = (BMIter__begin_cb)bmiter__loop_of_loop_begin; - iter->step = (BMIter__step_cb)bmiter__loop_of_loop_step; - iter->data.loop_of_loop.ldata = (BMLoop *)data; - break; - case BM_LOOPS_OF_EDGE: - BLI_assert(data != NULL); - BLI_assert(((BMElem *)data)->head.htype == BM_EDGE); - iter->begin = (BMIter__begin_cb)bmiter__loop_of_edge_begin; - iter->step = (BMIter__step_cb)bmiter__loop_of_edge_step; - iter->data.loop_of_edge.edata = (BMEdge *)data; - break; - default: - /* should never happen */ - BLI_assert(0); - return false; - break; - } + /* inlining optimizes out this switch when called with the defined type */ + switch ((BMIterType)itype) { + case BM_VERTS_OF_MESH: + BLI_assert(bm != NULL); + BLI_assert(data == NULL); + iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin; + iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step; + iter->data.elem_of_mesh.pooliter.pool = bm->vpool; + break; + case BM_EDGES_OF_MESH: + BLI_assert(bm != NULL); + BLI_assert(data == NULL); + iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin; + iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step; + iter->data.elem_of_mesh.pooliter.pool = bm->epool; + break; + case BM_FACES_OF_MESH: + BLI_assert(bm != NULL); + BLI_assert(data == NULL); + iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin; + iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step; + iter->data.elem_of_mesh.pooliter.pool = bm->fpool; + break; + case BM_EDGES_OF_VERT: + BLI_assert(data != NULL); + BLI_assert(((BMElem *)data)->head.htype == BM_VERT); + iter->begin = (BMIter__begin_cb)bmiter__edge_of_vert_begin; + iter->step = (BMIter__step_cb)bmiter__edge_of_vert_step; + iter->data.edge_of_vert.vdata = (BMVert *)data; + break; + case BM_FACES_OF_VERT: + BLI_assert(data != NULL); + BLI_assert(((BMElem *)data)->head.htype == BM_VERT); + iter->begin = (BMIter__begin_cb)bmiter__face_of_vert_begin; + iter->step = (BMIter__step_cb)bmiter__face_of_vert_step; + iter->data.face_of_vert.vdata = (BMVert *)data; + break; + case BM_LOOPS_OF_VERT: + BLI_assert(data != NULL); + BLI_assert(((BMElem *)data)->head.htype == BM_VERT); + iter->begin = (BMIter__begin_cb)bmiter__loop_of_vert_begin; + iter->step = (BMIter__step_cb)bmiter__loop_of_vert_step; + iter->data.loop_of_vert.vdata = (BMVert *)data; + break; + case BM_VERTS_OF_EDGE: + BLI_assert(data != NULL); + BLI_assert(((BMElem *)data)->head.htype == BM_EDGE); + iter->begin = (BMIter__begin_cb)bmiter__vert_of_edge_begin; + iter->step = (BMIter__step_cb)bmiter__vert_of_edge_step; + iter->data.vert_of_edge.edata = (BMEdge *)data; + break; + case BM_FACES_OF_EDGE: + BLI_assert(data != NULL); + BLI_assert(((BMElem *)data)->head.htype == BM_EDGE); + iter->begin = (BMIter__begin_cb)bmiter__face_of_edge_begin; + iter->step = (BMIter__step_cb)bmiter__face_of_edge_step; + iter->data.face_of_edge.edata = (BMEdge *)data; + break; + case BM_VERTS_OF_FACE: + BLI_assert(data != NULL); + BLI_assert(((BMElem *)data)->head.htype == BM_FACE); + iter->begin = (BMIter__begin_cb)bmiter__vert_of_face_begin; + iter->step = (BMIter__step_cb)bmiter__vert_of_face_step; + iter->data.vert_of_face.pdata = (BMFace *)data; + break; + case BM_EDGES_OF_FACE: + BLI_assert(data != NULL); + BLI_assert(((BMElem *)data)->head.htype == BM_FACE); + iter->begin = (BMIter__begin_cb)bmiter__edge_of_face_begin; + iter->step = (BMIter__step_cb)bmiter__edge_of_face_step; + iter->data.edge_of_face.pdata = (BMFace *)data; + break; + case BM_LOOPS_OF_FACE: + BLI_assert(data != NULL); + BLI_assert(((BMElem *)data)->head.htype == BM_FACE); + iter->begin = (BMIter__begin_cb)bmiter__loop_of_face_begin; + iter->step = (BMIter__step_cb)bmiter__loop_of_face_step; + iter->data.loop_of_face.pdata = (BMFace *)data; + break; + case BM_LOOPS_OF_LOOP: + BLI_assert(data != NULL); + BLI_assert(((BMElem *)data)->head.htype == BM_LOOP); + iter->begin = (BMIter__begin_cb)bmiter__loop_of_loop_begin; + iter->step = (BMIter__step_cb)bmiter__loop_of_loop_step; + iter->data.loop_of_loop.ldata = (BMLoop *)data; + break; + case BM_LOOPS_OF_EDGE: + BLI_assert(data != NULL); + BLI_assert(((BMElem *)data)->head.htype == BM_EDGE); + iter->begin = (BMIter__begin_cb)bmiter__loop_of_edge_begin; + iter->step = (BMIter__step_cb)bmiter__loop_of_edge_step; + iter->data.loop_of_edge.edata = (BMEdge *)data; + break; + default: + /* should never happen */ + BLI_assert(0); + return false; + break; + } - iter->begin(iter); + iter->begin(iter); - return true; + return true; } /** @@ -164,15 +162,15 @@ BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *da * upon its type and then calls BMeshIter_step() * to return the first element of the iterator. */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *data) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE + void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *data) { - if (LIKELY(BM_iter_init(iter, bm, itype, data))) { - return BM_iter_step(iter); - } - else { - return NULL; - } + if (LIKELY(BM_iter_init(iter, bm, itype, data))) { + return BM_iter_step(iter); + } + else { + return NULL; + } } /** @@ -186,27 +184,30 @@ BLI_INLINE void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *da #ifdef __BLI_TASK_H__ ATTR_NONNULL(1) -BLI_INLINE void BM_iter_parallel( - BMesh *bm, const char itype, TaskParallelMempoolFunc func, void *userdata, const bool use_threading) +BLI_INLINE void BM_iter_parallel(BMesh *bm, + const char itype, + TaskParallelMempoolFunc func, + void *userdata, + const bool use_threading) { - /* inlining optimizes out this switch when called with the defined type */ - switch ((BMIterType)itype) { - case BM_VERTS_OF_MESH: - BLI_task_parallel_mempool(bm->vpool, userdata, func, use_threading); - break; - case BM_EDGES_OF_MESH: - BLI_task_parallel_mempool(bm->epool, userdata, func, use_threading); - break; - case BM_FACES_OF_MESH: - BLI_task_parallel_mempool(bm->fpool, userdata, func, use_threading); - break; - default: - /* should never happen */ - BLI_assert(0); - break; - } + /* inlining optimizes out this switch when called with the defined type */ + switch ((BMIterType)itype) { + case BM_VERTS_OF_MESH: + BLI_task_parallel_mempool(bm->vpool, userdata, func, use_threading); + break; + case BM_EDGES_OF_MESH: + BLI_task_parallel_mempool(bm->epool, userdata, func, use_threading); + break; + case BM_FACES_OF_MESH: + BLI_task_parallel_mempool(bm->fpool, userdata, func, use_threading); + break; + default: + /* should never happen */ + BLI_assert(0); + break; + } } -#endif /* __BLI_TASK_H__ */ +#endif /* __BLI_TASK_H__ */ #endif /* __BMESH_ITERATORS_INLINE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index 3b2e43b89ad..16a534b5e56 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -45,79 +45,78 @@ #include "BLI_strict_flags.h" - struct BMLogEntry { - struct BMLogEntry *next, *prev; - - /* The following GHashes map from an element ID to one of the log - * types above */ - - /* Elements that were in the previous entry, but have been - * deleted */ - GHash *deleted_verts; - GHash *deleted_faces; - /* Elements that were not in the previous entry, but are in the - * result of this entry */ - GHash *added_verts; - GHash *added_faces; - - /* Vertices whose coordinates, mask value, or hflag have changed */ - GHash *modified_verts; - GHash *modified_faces; - - BLI_mempool *pool_verts; - BLI_mempool *pool_faces; - - /* This is only needed for dropping BMLogEntries while still in - * dynamic-topology mode, as that should release vert/face IDs - * back to the BMLog but no BMLog pointer is available at that - * time. - * - * This field is not guaranteed to be valid, any use of it should - * check for NULL. */ - BMLog *log; + struct BMLogEntry *next, *prev; + + /* The following GHashes map from an element ID to one of the log + * types above */ + + /* Elements that were in the previous entry, but have been + * deleted */ + GHash *deleted_verts; + GHash *deleted_faces; + /* Elements that were not in the previous entry, but are in the + * result of this entry */ + GHash *added_verts; + GHash *added_faces; + + /* Vertices whose coordinates, mask value, or hflag have changed */ + GHash *modified_verts; + GHash *modified_faces; + + BLI_mempool *pool_verts; + BLI_mempool *pool_faces; + + /* This is only needed for dropping BMLogEntries while still in + * dynamic-topology mode, as that should release vert/face IDs + * back to the BMLog but no BMLog pointer is available at that + * time. + * + * This field is not guaranteed to be valid, any use of it should + * check for NULL. */ + BMLog *log; }; struct BMLog { - /* Tree of free IDs */ - struct RangeTreeUInt *unused_ids; - - /* Mapping from unique IDs to vertices and faces - * - * Each vertex and face in the log gets a unique uinteger - * assigned. That ID is taken from the set managed by the - * unused_ids range tree. - * - * The ID is needed because element pointers will change as they - * are created and deleted. - */ - GHash *id_to_elem; - GHash *elem_to_id; - - /* All BMLogEntrys, ordered from earliest to most recent */ - ListBase entries; - - /* The current log entry from entries list - * - * If null, then the original mesh from before any of the log - * entries is current (i.e. there is nothing left to undo.) - * - * If equal to the last entry in the entries list, then all log - * entries have been applied (i.e. there is nothing left to redo.) - */ - BMLogEntry *current_entry; + /* Tree of free IDs */ + struct RangeTreeUInt *unused_ids; + + /* Mapping from unique IDs to vertices and faces + * + * Each vertex and face in the log gets a unique uinteger + * assigned. That ID is taken from the set managed by the + * unused_ids range tree. + * + * The ID is needed because element pointers will change as they + * are created and deleted. + */ + GHash *id_to_elem; + GHash *elem_to_id; + + /* All BMLogEntrys, ordered from earliest to most recent */ + ListBase entries; + + /* The current log entry from entries list + * + * If null, then the original mesh from before any of the log + * entries is current (i.e. there is nothing left to undo.) + * + * If equal to the last entry in the entries list, then all log + * entries have been applied (i.e. there is nothing left to redo.) + */ + BMLogEntry *current_entry; }; typedef struct { - float co[3]; - short no[3]; - char hflag; - float mask; + float co[3]; + short no[3]; + char hflag; + float mask; } BMLogVert; typedef struct { - uint v_ids[3]; - char hflag; + uint v_ids[3]; + char hflag; } BMLogFace; /************************* Get/set element IDs ************************/ @@ -129,52 +128,51 @@ typedef struct { /* Get the vertex's unique ID from the log */ static uint bm_log_vert_id_get(BMLog *log, BMVert *v) { - BLI_assert(BLI_ghash_haskey(log->elem_to_id, v)); - return POINTER_AS_UINT(BLI_ghash_lookup(log->elem_to_id, v)); + BLI_assert(BLI_ghash_haskey(log->elem_to_id, v)); + return POINTER_AS_UINT(BLI_ghash_lookup(log->elem_to_id, v)); } /* Set the vertex's unique ID in the log */ static void bm_log_vert_id_set(BMLog *log, BMVert *v, uint id) { - void *vid = POINTER_FROM_UINT(id); + void *vid = POINTER_FROM_UINT(id); - BLI_ghash_reinsert(log->id_to_elem, vid, v, NULL, NULL); - BLI_ghash_reinsert(log->elem_to_id, v, vid, NULL, NULL); + BLI_ghash_reinsert(log->id_to_elem, vid, v, NULL, NULL); + BLI_ghash_reinsert(log->elem_to_id, v, vid, NULL, NULL); } /* Get a vertex from its unique ID */ static BMVert *bm_log_vert_from_id(BMLog *log, uint id) { - void *key = POINTER_FROM_UINT(id); - BLI_assert(BLI_ghash_haskey(log->id_to_elem, key)); - return BLI_ghash_lookup(log->id_to_elem, key); + void *key = POINTER_FROM_UINT(id); + BLI_assert(BLI_ghash_haskey(log->id_to_elem, key)); + return BLI_ghash_lookup(log->id_to_elem, key); } /* Get the face's unique ID from the log */ static uint bm_log_face_id_get(BMLog *log, BMFace *f) { - BLI_assert(BLI_ghash_haskey(log->elem_to_id, f)); - return POINTER_AS_UINT(BLI_ghash_lookup(log->elem_to_id, f)); + BLI_assert(BLI_ghash_haskey(log->elem_to_id, f)); + return POINTER_AS_UINT(BLI_ghash_lookup(log->elem_to_id, f)); } /* Set the face's unique ID in the log */ static void bm_log_face_id_set(BMLog *log, BMFace *f, uint id) { - void *fid = POINTER_FROM_UINT(id); + void *fid = POINTER_FROM_UINT(id); - BLI_ghash_reinsert(log->id_to_elem, fid, f, NULL, NULL); - BLI_ghash_reinsert(log->elem_to_id, f, fid, NULL, NULL); + BLI_ghash_reinsert(log->id_to_elem, fid, f, NULL, NULL); + BLI_ghash_reinsert(log->elem_to_id, f, fid, NULL, NULL); } /* Get a face from its unique ID */ static BMFace *bm_log_face_from_id(BMLog *log, uint id) { - void *key = POINTER_FROM_UINT(id); - BLI_assert(BLI_ghash_haskey(log->id_to_elem, key)); - return BLI_ghash_lookup(log->id_to_elem, key); + void *key = POINTER_FROM_UINT(id); + BLI_assert(BLI_ghash_haskey(log->id_to_elem, key)); + return BLI_ghash_lookup(log->id_to_elem, key); } - /************************ BMLogVert / BMLogFace ***********************/ /* Get a vertex's paint-mask value @@ -182,12 +180,12 @@ static BMFace *bm_log_face_from_id(BMLog *log, uint id) * Returns zero if no paint-mask layer is present */ static float vert_mask_get(BMVert *v, const int cd_vert_mask_offset) { - if (cd_vert_mask_offset != -1) { - return BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); - } - else { - return 0.0f; - } + if (cd_vert_mask_offset != -1) { + return BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); + } + else { + return 0.0f; + } } /* Set a vertex's paint-mask value @@ -195,208 +193,206 @@ static float vert_mask_get(BMVert *v, const int cd_vert_mask_offset) * Has no effect is no paint-mask layer is present */ static void vert_mask_set(BMVert *v, const float new_mask, const int cd_vert_mask_offset) { - if (cd_vert_mask_offset != -1) { - BM_ELEM_CD_SET_FLOAT(v, cd_vert_mask_offset, new_mask); - } + if (cd_vert_mask_offset != -1) { + BM_ELEM_CD_SET_FLOAT(v, cd_vert_mask_offset, new_mask); + } } /* Update a BMLogVert with data from a BMVert */ static void bm_log_vert_bmvert_copy(BMLogVert *lv, BMVert *v, const int cd_vert_mask_offset) { - copy_v3_v3(lv->co, v->co); - normal_float_to_short_v3(lv->no, v->no); - lv->mask = vert_mask_get(v, cd_vert_mask_offset); - lv->hflag = v->head.hflag; + copy_v3_v3(lv->co, v->co); + normal_float_to_short_v3(lv->no, v->no); + lv->mask = vert_mask_get(v, cd_vert_mask_offset); + lv->hflag = v->head.hflag; } /* Allocate and initialize a BMLogVert */ static BMLogVert *bm_log_vert_alloc(BMLog *log, BMVert *v, const int cd_vert_mask_offset) { - BMLogEntry *entry = log->current_entry; - BMLogVert *lv = BLI_mempool_alloc(entry->pool_verts); + BMLogEntry *entry = log->current_entry; + BMLogVert *lv = BLI_mempool_alloc(entry->pool_verts); - bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset); + bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset); - return lv; + return lv; } /* Allocate and initialize a BMLogFace */ static BMLogFace *bm_log_face_alloc(BMLog *log, BMFace *f) { - BMLogEntry *entry = log->current_entry; - BMLogFace *lf = BLI_mempool_alloc(entry->pool_faces); - BMVert *v[3]; + BMLogEntry *entry = log->current_entry; + BMLogFace *lf = BLI_mempool_alloc(entry->pool_faces); + BMVert *v[3]; - BLI_assert(f->len == 3); + BLI_assert(f->len == 3); - // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); - BM_face_as_array_vert_tri(f, v); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + BM_face_as_array_vert_tri(f, v); - lf->v_ids[0] = bm_log_vert_id_get(log, v[0]); - lf->v_ids[1] = bm_log_vert_id_get(log, v[1]); - lf->v_ids[2] = bm_log_vert_id_get(log, v[2]); + lf->v_ids[0] = bm_log_vert_id_get(log, v[0]); + lf->v_ids[1] = bm_log_vert_id_get(log, v[1]); + lf->v_ids[2] = bm_log_vert_id_get(log, v[2]); - lf->hflag = f->head.hflag; - return lf; + lf->hflag = f->head.hflag; + return lf; } - /************************ Helpers for undo/redo ***********************/ static void bm_log_verts_unmake(BMesh *bm, BMLog *log, GHash *verts) { - const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); + const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); - GHashIterator gh_iter; - GHASH_ITER (gh_iter, verts) { - void *key = BLI_ghashIterator_getKey(&gh_iter); - BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter); - uint id = POINTER_AS_UINT(key); - BMVert *v = bm_log_vert_from_id(log, id); + GHashIterator gh_iter; + GHASH_ITER (gh_iter, verts) { + void *key = BLI_ghashIterator_getKey(&gh_iter); + BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter); + uint id = POINTER_AS_UINT(key); + BMVert *v = bm_log_vert_from_id(log, id); - /* Ensure the log has the final values of the vertex before - * deleting it */ - bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset); + /* Ensure the log has the final values of the vertex before + * deleting it */ + bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset); - BM_vert_kill(bm, v); - } + BM_vert_kill(bm, v); + } } static void bm_log_faces_unmake(BMesh *bm, BMLog *log, GHash *faces) { - GHashIterator gh_iter; - GHASH_ITER (gh_iter, faces) { - void *key = BLI_ghashIterator_getKey(&gh_iter); - uint id = POINTER_AS_UINT(key); - BMFace *f = bm_log_face_from_id(log, id); - BMEdge *e_tri[3]; - BMLoop *l_iter; - int i; - - l_iter = BM_FACE_FIRST_LOOP(f); - for (i = 0; i < 3; i++, l_iter = l_iter->next) { - e_tri[i] = l_iter->e; - } - - /* Remove any unused edges */ - BM_face_kill(bm, f); - for (i = 0; i < 3; i++) { - if (BM_edge_is_wire(e_tri[i])) { - BM_edge_kill(bm, e_tri[i]); - } - } - } + GHashIterator gh_iter; + GHASH_ITER (gh_iter, faces) { + void *key = BLI_ghashIterator_getKey(&gh_iter); + uint id = POINTER_AS_UINT(key); + BMFace *f = bm_log_face_from_id(log, id); + BMEdge *e_tri[3]; + BMLoop *l_iter; + int i; + + l_iter = BM_FACE_FIRST_LOOP(f); + for (i = 0; i < 3; i++, l_iter = l_iter->next) { + e_tri[i] = l_iter->e; + } + + /* Remove any unused edges */ + BM_face_kill(bm, f); + for (i = 0; i < 3; i++) { + if (BM_edge_is_wire(e_tri[i])) { + BM_edge_kill(bm, e_tri[i]); + } + } + } } static void bm_log_verts_restore(BMesh *bm, BMLog *log, GHash *verts) { - const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); - - GHashIterator gh_iter; - GHASH_ITER (gh_iter, verts) { - void *key = BLI_ghashIterator_getKey(&gh_iter); - BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter); - BMVert *v = BM_vert_create(bm, lv->co, NULL, BM_CREATE_NOP); - vert_mask_set(v, lv->mask, cd_vert_mask_offset); - v->head.hflag = lv->hflag; - normal_short_to_float_v3(v->no, lv->no); - bm_log_vert_id_set(log, v, POINTER_AS_UINT(key)); - } + const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); + + GHashIterator gh_iter; + GHASH_ITER (gh_iter, verts) { + void *key = BLI_ghashIterator_getKey(&gh_iter); + BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter); + BMVert *v = BM_vert_create(bm, lv->co, NULL, BM_CREATE_NOP); + vert_mask_set(v, lv->mask, cd_vert_mask_offset); + v->head.hflag = lv->hflag; + normal_short_to_float_v3(v->no, lv->no); + bm_log_vert_id_set(log, v, POINTER_AS_UINT(key)); + } } static void bm_log_faces_restore(BMesh *bm, BMLog *log, GHash *faces) { - GHashIterator gh_iter; - GHASH_ITER (gh_iter, faces) { - void *key = BLI_ghashIterator_getKey(&gh_iter); - BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter); - BMVert *v[3] = {bm_log_vert_from_id(log, lf->v_ids[0]), - bm_log_vert_from_id(log, lf->v_ids[1]), - bm_log_vert_from_id(log, lf->v_ids[2])}; - BMFace *f; - - f = BM_face_create_verts(bm, v, 3, NULL, BM_CREATE_NOP, true); - f->head.hflag = lf->hflag; - bm_log_face_id_set(log, f, POINTER_AS_UINT(key)); - } + GHashIterator gh_iter; + GHASH_ITER (gh_iter, faces) { + void *key = BLI_ghashIterator_getKey(&gh_iter); + BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter); + BMVert *v[3] = {bm_log_vert_from_id(log, lf->v_ids[0]), + bm_log_vert_from_id(log, lf->v_ids[1]), + bm_log_vert_from_id(log, lf->v_ids[2])}; + BMFace *f; + + f = BM_face_create_verts(bm, v, 3, NULL, BM_CREATE_NOP, true); + f->head.hflag = lf->hflag; + bm_log_face_id_set(log, f, POINTER_AS_UINT(key)); + } } static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts) { - const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); - - GHashIterator gh_iter; - GHASH_ITER (gh_iter, verts) { - void *key = BLI_ghashIterator_getKey(&gh_iter); - BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter); - uint id = POINTER_AS_UINT(key); - BMVert *v = bm_log_vert_from_id(log, id); - float mask; - short normal[3]; - - swap_v3_v3(v->co, lv->co); - copy_v3_v3_short(normal, lv->no); - normal_float_to_short_v3(lv->no, v->no); - normal_short_to_float_v3(v->no, normal); - SWAP(char, v->head.hflag, lv->hflag); - mask = lv->mask; - lv->mask = vert_mask_get(v, cd_vert_mask_offset); - vert_mask_set(v, mask, cd_vert_mask_offset); - } + const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); + + GHashIterator gh_iter; + GHASH_ITER (gh_iter, verts) { + void *key = BLI_ghashIterator_getKey(&gh_iter); + BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter); + uint id = POINTER_AS_UINT(key); + BMVert *v = bm_log_vert_from_id(log, id); + float mask; + short normal[3]; + + swap_v3_v3(v->co, lv->co); + copy_v3_v3_short(normal, lv->no); + normal_float_to_short_v3(lv->no, v->no); + normal_short_to_float_v3(v->no, normal); + SWAP(char, v->head.hflag, lv->hflag); + mask = lv->mask; + lv->mask = vert_mask_get(v, cd_vert_mask_offset); + vert_mask_set(v, mask, cd_vert_mask_offset); + } } static void bm_log_face_values_swap(BMLog *log, GHash *faces) { - GHashIterator gh_iter; - GHASH_ITER (gh_iter, faces) { - void *key = BLI_ghashIterator_getKey(&gh_iter); - BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter); - uint id = POINTER_AS_UINT(key); - BMFace *f = bm_log_face_from_id(log, id); - - SWAP(char, f->head.hflag, lf->hflag); - } + GHashIterator gh_iter; + GHASH_ITER (gh_iter, faces) { + void *key = BLI_ghashIterator_getKey(&gh_iter); + BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter); + uint id = POINTER_AS_UINT(key); + BMFace *f = bm_log_face_from_id(log, id); + + SWAP(char, f->head.hflag, lf->hflag); + } } - /**********************************************************************/ /* Assign unique IDs to all vertices and faces already in the BMesh */ static void bm_log_assign_ids(BMesh *bm, BMLog *log) { - BMIter iter; - BMVert *v; - BMFace *f; - - /* Generate vertex IDs */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - uint id = range_tree_uint_take_any(log->unused_ids); - bm_log_vert_id_set(log, v, id); - } - - /* Generate face IDs */ - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - uint id = range_tree_uint_take_any(log->unused_ids); - bm_log_face_id_set(log, f, id); - } + BMIter iter; + BMVert *v; + BMFace *f; + + /* Generate vertex IDs */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + uint id = range_tree_uint_take_any(log->unused_ids); + bm_log_vert_id_set(log, v, id); + } + + /* Generate face IDs */ + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + uint id = range_tree_uint_take_any(log->unused_ids); + bm_log_face_id_set(log, f, id); + } } /* Allocate an empty log entry */ static BMLogEntry *bm_log_entry_create(void) { - BMLogEntry *entry = MEM_callocN(sizeof(BMLogEntry), __func__); + BMLogEntry *entry = MEM_callocN(sizeof(BMLogEntry), __func__); - entry->deleted_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); - entry->deleted_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); - entry->added_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); - entry->added_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); - entry->modified_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); - entry->modified_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); + entry->deleted_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); + entry->deleted_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); + entry->added_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); + entry->added_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); + entry->modified_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); + entry->modified_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__); - entry->pool_verts = BLI_mempool_create(sizeof(BMLogVert), 0, 64, BLI_MEMPOOL_NOP); - entry->pool_faces = BLI_mempool_create(sizeof(BMLogFace), 0, 64, BLI_MEMPOOL_NOP); + entry->pool_verts = BLI_mempool_create(sizeof(BMLogVert), 0, 64, BLI_MEMPOOL_NOP); + entry->pool_faces = BLI_mempool_create(sizeof(BMLogFace), 0, 64, BLI_MEMPOOL_NOP); - return entry; + return entry; } /* Free the data in a log entry @@ -404,34 +400,34 @@ static BMLogEntry *bm_log_entry_create(void) * Note: does not free the log entry itself */ static void bm_log_entry_free(BMLogEntry *entry) { - BLI_ghash_free(entry->deleted_verts, NULL, NULL); - BLI_ghash_free(entry->deleted_faces, NULL, NULL); - BLI_ghash_free(entry->added_verts, NULL, NULL); - BLI_ghash_free(entry->added_faces, NULL, NULL); - BLI_ghash_free(entry->modified_verts, NULL, NULL); - BLI_ghash_free(entry->modified_faces, NULL, NULL); - - BLI_mempool_destroy(entry->pool_verts); - BLI_mempool_destroy(entry->pool_faces); + BLI_ghash_free(entry->deleted_verts, NULL, NULL); + BLI_ghash_free(entry->deleted_faces, NULL, NULL); + BLI_ghash_free(entry->added_verts, NULL, NULL); + BLI_ghash_free(entry->added_faces, NULL, NULL); + BLI_ghash_free(entry->modified_verts, NULL, NULL); + BLI_ghash_free(entry->modified_faces, NULL, NULL); + + BLI_mempool_destroy(entry->pool_verts); + BLI_mempool_destroy(entry->pool_faces); } static void bm_log_id_ghash_retake(RangeTreeUInt *unused_ids, GHash *id_ghash) { - GHashIterator gh_iter; + GHashIterator gh_iter; - GHASH_ITER (gh_iter, id_ghash) { - void *key = BLI_ghashIterator_getKey(&gh_iter); - uint id = POINTER_AS_UINT(key); + GHASH_ITER (gh_iter, id_ghash) { + void *key = BLI_ghashIterator_getKey(&gh_iter); + uint id = POINTER_AS_UINT(key); - range_tree_uint_retake(unused_ids, id); - } + range_tree_uint_retake(unused_ids, id); + } } static int uint_compare(const void *a_v, const void *b_v) { - const uint *a = a_v; - const uint *b = b_v; - return (*a) < (*b); + const uint *a = a_v; + const uint *b = b_v; + return (*a) < (*b); } /* Remap IDs to contiguous indices @@ -444,30 +440,30 @@ static int uint_compare(const void *a_v, const void *b_v) */ static GHash *bm_log_compress_ids_to_indices(uint *ids, uint totid) { - GHash *map = BLI_ghash_int_new_ex(__func__, totid); - uint i; + GHash *map = BLI_ghash_int_new_ex(__func__, totid); + uint i; - qsort(ids, totid, sizeof(*ids), uint_compare); + qsort(ids, totid, sizeof(*ids), uint_compare); - for (i = 0; i < totid; i++) { - void *key = POINTER_FROM_UINT(ids[i]); - void *val = POINTER_FROM_UINT(i); - BLI_ghash_insert(map, key, val); - } + for (i = 0; i < totid; i++) { + void *key = POINTER_FROM_UINT(ids[i]); + void *val = POINTER_FROM_UINT(i); + BLI_ghash_insert(map, key, val); + } - return map; + return map; } /* Release all ID keys in id_ghash */ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash) { - GHashIterator gh_iter; + GHashIterator gh_iter; - GHASH_ITER (gh_iter, id_ghash) { - void *key = BLI_ghashIterator_getKey(&gh_iter); - uint id = POINTER_AS_UINT(key); - range_tree_uint_release(log->unused_ids, id); - } + GHASH_ITER (gh_iter, id_ghash) { + void *key = BLI_ghashIterator_getKey(&gh_iter); + uint id = POINTER_AS_UINT(key); + range_tree_uint_release(log->unused_ids, id); + } } /***************************** Public API *****************************/ @@ -475,42 +471,41 @@ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash) /* Allocate, initialize, and assign a new BMLog */ BMLog *BM_log_create(BMesh *bm) { - BMLog *log = MEM_callocN(sizeof(*log), __func__); - const uint reserve_num = (uint)(bm->totvert + bm->totface); + BMLog *log = MEM_callocN(sizeof(*log), __func__); + const uint reserve_num = (uint)(bm->totvert + bm->totface); - log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1); - log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num); - log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, reserve_num); + log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1); + log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num); + log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, reserve_num); - /* Assign IDs to all existing vertices and faces */ - bm_log_assign_ids(bm, log); + /* Assign IDs to all existing vertices and faces */ + bm_log_assign_ids(bm, log); - return log; + return log; } void BM_log_cleanup_entry(BMLogEntry *entry) { - BMLog *log = entry->log; - - if (log) { - /* Take all used IDs */ - bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts); - bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces); - bm_log_id_ghash_retake(log->unused_ids, entry->added_verts); - bm_log_id_ghash_retake(log->unused_ids, entry->added_faces); - bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts); - bm_log_id_ghash_retake(log->unused_ids, entry->modified_faces); - - /* delete entries to avoid releasing ids in node cleanup */ - BLI_ghash_clear(entry->deleted_verts, NULL, NULL); - BLI_ghash_clear(entry->deleted_faces, NULL, NULL); - BLI_ghash_clear(entry->added_verts, NULL, NULL); - BLI_ghash_clear(entry->added_faces, NULL, NULL); - BLI_ghash_clear(entry->modified_verts, NULL, NULL); - } + BMLog *log = entry->log; + + if (log) { + /* Take all used IDs */ + bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts); + bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces); + bm_log_id_ghash_retake(log->unused_ids, entry->added_verts); + bm_log_id_ghash_retake(log->unused_ids, entry->added_faces); + bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts); + bm_log_id_ghash_retake(log->unused_ids, entry->modified_faces); + + /* delete entries to avoid releasing ids in node cleanup */ + BLI_ghash_clear(entry->deleted_verts, NULL, NULL); + BLI_ghash_clear(entry->deleted_faces, NULL, NULL); + BLI_ghash_clear(entry->added_verts, NULL, NULL); + BLI_ghash_clear(entry->added_faces, NULL, NULL); + BLI_ghash_clear(entry->modified_verts, NULL, NULL); + } } - /* Allocate and initialize a new BMLog using existing BMLogEntries * * The 'entry' should be the last entry in the BMLog. Its prev pointer @@ -521,127 +516,127 @@ void BM_log_cleanup_entry(BMLogEntry *entry) */ BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry) { - BMLog *log = BM_log_create(bm); - - if (entry->prev) { - log->current_entry = entry; - } - else { - log->current_entry = NULL; - } - - /* Let BMLog manage the entry list again */ - log->entries.first = log->entries.last = entry; - - { - while (entry->prev) { - entry = entry->prev; - log->entries.first = entry; - } - entry = log->entries.last; - while (entry->next) { - entry = entry->next; - log->entries.last = entry; - } - } - - for (entry = log->entries.first; entry; entry = entry->next) { - entry->log = log; - - /* Take all used IDs */ - bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts); - bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces); - bm_log_id_ghash_retake(log->unused_ids, entry->added_verts); - bm_log_id_ghash_retake(log->unused_ids, entry->added_faces); - bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts); - bm_log_id_ghash_retake(log->unused_ids, entry->modified_faces); - } - - return log; + BMLog *log = BM_log_create(bm); + + if (entry->prev) { + log->current_entry = entry; + } + else { + log->current_entry = NULL; + } + + /* Let BMLog manage the entry list again */ + log->entries.first = log->entries.last = entry; + + { + while (entry->prev) { + entry = entry->prev; + log->entries.first = entry; + } + entry = log->entries.last; + while (entry->next) { + entry = entry->next; + log->entries.last = entry; + } + } + + for (entry = log->entries.first; entry; entry = entry->next) { + entry->log = log; + + /* Take all used IDs */ + bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts); + bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces); + bm_log_id_ghash_retake(log->unused_ids, entry->added_verts); + bm_log_id_ghash_retake(log->unused_ids, entry->added_faces); + bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts); + bm_log_id_ghash_retake(log->unused_ids, entry->modified_faces); + } + + return log; } /* Free all the data in a BMLog including the log itself */ void BM_log_free(BMLog *log) { - BMLogEntry *entry; + BMLogEntry *entry; - if (log->unused_ids) { - range_tree_uint_free(log->unused_ids); - } + if (log->unused_ids) { + range_tree_uint_free(log->unused_ids); + } - if (log->id_to_elem) { - BLI_ghash_free(log->id_to_elem, NULL, NULL); - } + if (log->id_to_elem) { + BLI_ghash_free(log->id_to_elem, NULL, NULL); + } - if (log->elem_to_id) { - BLI_ghash_free(log->elem_to_id, NULL, NULL); - } + if (log->elem_to_id) { + BLI_ghash_free(log->elem_to_id, NULL, NULL); + } - /* Clear the BMLog references within each entry, but do not free - * the entries themselves */ - for (entry = log->entries.first; entry; entry = entry->next) { - entry->log = NULL; - } + /* Clear the BMLog references within each entry, but do not free + * the entries themselves */ + for (entry = log->entries.first; entry; entry = entry->next) { + entry->log = NULL; + } - MEM_freeN(log); + MEM_freeN(log); } /* Get the number of log entries */ int BM_log_length(const BMLog *log) { - return BLI_listbase_count(&log->entries); + return BLI_listbase_count(&log->entries); } /* Apply a consistent ordering to BMesh vertices */ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log) { - uint *varr; - uint *farr; - - GHash *id_to_idx; - - BMIter bm_iter; - BMVert *v; - BMFace *f; - - uint i; - - /* Put all vertex IDs into an array */ - varr = MEM_mallocN(sizeof(int) * (size_t)bm->totvert, __func__); - BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) { - varr[i] = bm_log_vert_id_get(log, v); - } - - /* Put all face IDs into an array */ - farr = MEM_mallocN(sizeof(int) * (size_t)bm->totface, __func__); - BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) { - farr[i] = bm_log_face_id_get(log, f); - } - - /* Create BMVert index remap array */ - id_to_idx = bm_log_compress_ids_to_indices(varr, (uint)bm->totvert); - BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) { - const unsigned id = bm_log_vert_id_get(log, v); - const void *key = POINTER_FROM_UINT(id); - const void *val = BLI_ghash_lookup(id_to_idx, key); - varr[i] = POINTER_AS_UINT(val); - } - BLI_ghash_free(id_to_idx, NULL, NULL); - - /* Create BMFace index remap array */ - id_to_idx = bm_log_compress_ids_to_indices(farr, (uint)bm->totface); - BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) { - const unsigned id = bm_log_face_id_get(log, f); - const void *key = POINTER_FROM_UINT(id); - const void *val = BLI_ghash_lookup(id_to_idx, key); - farr[i] = POINTER_AS_UINT(val); - } - BLI_ghash_free(id_to_idx, NULL, NULL); - - BM_mesh_remap(bm, varr, NULL, farr); - - MEM_freeN(varr); - MEM_freeN(farr); + uint *varr; + uint *farr; + + GHash *id_to_idx; + + BMIter bm_iter; + BMVert *v; + BMFace *f; + + uint i; + + /* Put all vertex IDs into an array */ + varr = MEM_mallocN(sizeof(int) * (size_t)bm->totvert, __func__); + BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) { + varr[i] = bm_log_vert_id_get(log, v); + } + + /* Put all face IDs into an array */ + farr = MEM_mallocN(sizeof(int) * (size_t)bm->totface, __func__); + BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) { + farr[i] = bm_log_face_id_get(log, f); + } + + /* Create BMVert index remap array */ + id_to_idx = bm_log_compress_ids_to_indices(varr, (uint)bm->totvert); + BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) { + const unsigned id = bm_log_vert_id_get(log, v); + const void *key = POINTER_FROM_UINT(id); + const void *val = BLI_ghash_lookup(id_to_idx, key); + varr[i] = POINTER_AS_UINT(val); + } + BLI_ghash_free(id_to_idx, NULL, NULL); + + /* Create BMFace index remap array */ + id_to_idx = bm_log_compress_ids_to_indices(farr, (uint)bm->totface); + BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) { + const unsigned id = bm_log_face_id_get(log, f); + const void *key = POINTER_FROM_UINT(id); + const void *val = BLI_ghash_lookup(id_to_idx, key); + farr[i] = POINTER_AS_UINT(val); + } + BLI_ghash_free(id_to_idx, NULL, NULL); + + BM_mesh_remap(bm, varr, NULL, farr); + + MEM_freeN(varr); + MEM_freeN(farr); } /* Start a new log entry and update the log entry list @@ -656,29 +651,29 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log) */ BMLogEntry *BM_log_entry_add(BMLog *log) { - /* WARNING: this is now handled by the UndoSystem: BKE_UNDOSYS_TYPE_SCULPT - * freeing here causes unnecessary complications. */ - BMLogEntry *entry; + /* WARNING: this is now handled by the UndoSystem: BKE_UNDOSYS_TYPE_SCULPT + * freeing here causes unnecessary complications. */ + BMLogEntry *entry; #if 0 - /* Delete any entries after the current one */ - entry = log->current_entry; - if (entry) { - BMLogEntry *next; - for (entry = entry->next; entry; entry = next) { - next = entry->next; - bm_log_entry_free(entry); - BLI_freelinkN(&log->entries, entry); - } - } + /* Delete any entries after the current one */ + entry = log->current_entry; + if (entry) { + BMLogEntry *next; + for (entry = entry->next; entry; entry = next) { + next = entry->next; + bm_log_entry_free(entry); + BLI_freelinkN(&log->entries, entry); + } + } #endif - /* Create and append the new entry */ - entry = bm_log_entry_create(); - BLI_addtail(&log->entries, entry); - entry->log = log; - log->current_entry = entry; + /* Create and append the new entry */ + entry = bm_log_entry_create(); + BLI_addtail(&log->entries, entry); + entry->log = log; + log->current_entry = entry; - return entry; + return entry; } /* Remove an entry from the log @@ -692,68 +687,68 @@ BMLogEntry *BM_log_entry_add(BMLog *log) */ void BM_log_entry_drop(BMLogEntry *entry) { - BMLog *log = entry->log; - - if (!log) { - /* Unlink */ - BLI_assert(!(entry->prev && entry->next)); - if (entry->prev) { - entry->prev->next = NULL; - } - else if (entry->next) { - entry->next->prev = NULL; - } - - bm_log_entry_free(entry); - MEM_freeN(entry); - return; - } - - if (!entry->prev) { - /* Release IDs of elements that are deleted by this - * entry. Since the entry is at the beginning of the undo - * stack, and it's being deleted, those elements can never be - * restored. Their IDs can go back into the pool. */ - - /* This would never happen usually since first entry of log is - * usually dyntopo enable, which, when reverted will free the log - * completely. However, it is possible have a stroke instead of - * dyntopo enable as first entry if nodes have been cleaned up - * after sculpting on a different object than A, B. - * - * The steps are: - * A dyntopo enable - sculpt - * B dyntopo enable - sculpt - undo (A objects operators get cleaned up) - * A sculpt (now A's log has a sculpt operator as first entry) - * - * Causing a cleanup at this point will call the code below, however - * this will invalidate the state of the log since the deleted vertices - * have been reclaimed already on step 2 (see BM_log_cleanup_entry) - * - * Also, design wise, a first entry should not have any deleted vertices since it - * should not have anything to delete them -from- - */ - //bm_log_id_ghash_release(log, entry->deleted_faces); - //bm_log_id_ghash_release(log, entry->deleted_verts); - } - else if (!entry->next) { - /* Release IDs of elements that are added by this entry. Since - * the entry is at the end of the undo stack, and it's being - * deleted, those elements can never be restored. Their IDs - * can go back into the pool. */ - bm_log_id_ghash_release(log, entry->added_faces); - bm_log_id_ghash_release(log, entry->added_verts); - } - else { - BLI_assert(!"Cannot drop BMLogEntry from middle"); - } - - if (log->current_entry == entry) { - log->current_entry = entry->prev; - } - - bm_log_entry_free(entry); - BLI_freelinkN(&log->entries, entry); + BMLog *log = entry->log; + + if (!log) { + /* Unlink */ + BLI_assert(!(entry->prev && entry->next)); + if (entry->prev) { + entry->prev->next = NULL; + } + else if (entry->next) { + entry->next->prev = NULL; + } + + bm_log_entry_free(entry); + MEM_freeN(entry); + return; + } + + if (!entry->prev) { + /* Release IDs of elements that are deleted by this + * entry. Since the entry is at the beginning of the undo + * stack, and it's being deleted, those elements can never be + * restored. Their IDs can go back into the pool. */ + + /* This would never happen usually since first entry of log is + * usually dyntopo enable, which, when reverted will free the log + * completely. However, it is possible have a stroke instead of + * dyntopo enable as first entry if nodes have been cleaned up + * after sculpting on a different object than A, B. + * + * The steps are: + * A dyntopo enable - sculpt + * B dyntopo enable - sculpt - undo (A objects operators get cleaned up) + * A sculpt (now A's log has a sculpt operator as first entry) + * + * Causing a cleanup at this point will call the code below, however + * this will invalidate the state of the log since the deleted vertices + * have been reclaimed already on step 2 (see BM_log_cleanup_entry) + * + * Also, design wise, a first entry should not have any deleted vertices since it + * should not have anything to delete them -from- + */ + //bm_log_id_ghash_release(log, entry->deleted_faces); + //bm_log_id_ghash_release(log, entry->deleted_verts); + } + else if (!entry->next) { + /* Release IDs of elements that are added by this entry. Since + * the entry is at the end of the undo stack, and it's being + * deleted, those elements can never be restored. Their IDs + * can go back into the pool. */ + bm_log_id_ghash_release(log, entry->added_faces); + bm_log_id_ghash_release(log, entry->added_verts); + } + else { + BLI_assert(!"Cannot drop BMLogEntry from middle"); + } + + if (log->current_entry == entry) { + log->current_entry = entry->prev; + } + + bm_log_entry_free(entry); + BLI_freelinkN(&log->entries, entry); } /* Undo one BMLogEntry @@ -761,23 +756,23 @@ void BM_log_entry_drop(BMLogEntry *entry) * Has no effect if there's nothing left to undo */ void BM_log_undo(BMesh *bm, BMLog *log) { - BMLogEntry *entry = log->current_entry; + BMLogEntry *entry = log->current_entry; - if (entry) { - log->current_entry = entry->prev; + if (entry) { + log->current_entry = entry->prev; - /* Delete added faces and verts */ - bm_log_faces_unmake(bm, log, entry->added_faces); - bm_log_verts_unmake(bm, log, entry->added_verts); + /* Delete added faces and verts */ + bm_log_faces_unmake(bm, log, entry->added_faces); + bm_log_verts_unmake(bm, log, entry->added_verts); - /* Restore deleted verts and faces */ - bm_log_verts_restore(bm, log, entry->deleted_verts); - bm_log_faces_restore(bm, log, entry->deleted_faces); + /* Restore deleted verts and faces */ + bm_log_verts_restore(bm, log, entry->deleted_verts); + bm_log_faces_restore(bm, log, entry->deleted_faces); - /* Restore vertex coordinates, mask, and hflag */ - bm_log_vert_values_swap(bm, log, entry->modified_verts); - bm_log_face_values_swap(log, entry->modified_faces); - } + /* Restore vertex coordinates, mask, and hflag */ + bm_log_vert_values_swap(bm, log, entry->modified_verts); + bm_log_face_values_swap(log, entry->modified_faces); + } } /* Redo one BMLogEntry @@ -785,36 +780,36 @@ void BM_log_undo(BMesh *bm, BMLog *log) * Has no effect if there's nothing left to redo */ void BM_log_redo(BMesh *bm, BMLog *log) { - BMLogEntry *entry = log->current_entry; - - if (!entry) { - /* Currently at the beginning of the undo stack, move to first entry */ - entry = log->entries.first; - } - else if (entry && entry->next) { - /* Move to next undo entry */ - entry = entry->next; - } - else { - /* Currently at the end of the undo stack, nothing left to redo */ - return; - } - - log->current_entry = entry; - - if (entry) { - /* Re-delete previously deleted faces and verts */ - bm_log_faces_unmake(bm, log, entry->deleted_faces); - bm_log_verts_unmake(bm, log, entry->deleted_verts); - - /* Restore previously added verts and faces */ - bm_log_verts_restore(bm, log, entry->added_verts); - bm_log_faces_restore(bm, log, entry->added_faces); - - /* Restore vertex coordinates, mask, and hflag */ - bm_log_vert_values_swap(bm, log, entry->modified_verts); - bm_log_face_values_swap(log, entry->modified_faces); - } + BMLogEntry *entry = log->current_entry; + + if (!entry) { + /* Currently at the beginning of the undo stack, move to first entry */ + entry = log->entries.first; + } + else if (entry && entry->next) { + /* Move to next undo entry */ + entry = entry->next; + } + else { + /* Currently at the end of the undo stack, nothing left to redo */ + return; + } + + log->current_entry = entry; + + if (entry) { + /* Re-delete previously deleted faces and verts */ + bm_log_faces_unmake(bm, log, entry->deleted_faces); + bm_log_verts_unmake(bm, log, entry->deleted_verts); + + /* Restore previously added verts and faces */ + bm_log_verts_restore(bm, log, entry->added_verts); + bm_log_faces_restore(bm, log, entry->added_faces); + + /* Restore vertex coordinates, mask, and hflag */ + bm_log_vert_values_swap(bm, log, entry->modified_verts); + bm_log_face_values_swap(log, entry->modified_faces); + } } /* Log a vertex before it is modified @@ -842,23 +837,22 @@ void BM_log_redo(BMesh *bm, BMLog *log) */ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_offset) { - BMLogEntry *entry = log->current_entry; - BMLogVert *lv; - uint v_id = bm_log_vert_id_get(log, v); - void *key = POINTER_FROM_UINT(v_id); - void **val_p; - - /* Find or create the BMLogVert entry */ - if ((lv = BLI_ghash_lookup(entry->added_verts, key))) { - bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset); - } - else if (!BLI_ghash_ensure_p(entry->modified_verts, key, &val_p)) { - lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset); - *val_p = lv; - } + BMLogEntry *entry = log->current_entry; + BMLogVert *lv; + uint v_id = bm_log_vert_id_get(log, v); + void *key = POINTER_FROM_UINT(v_id); + void **val_p; + + /* Find or create the BMLogVert entry */ + if ((lv = BLI_ghash_lookup(entry->added_verts, key))) { + bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset); + } + else if (!BLI_ghash_ensure_p(entry->modified_verts, key, &val_p)) { + lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset); + *val_p = lv; + } } - /* Log a new vertex as added to the BMesh * * The new vertex gets a unique ID assigned. It is then added to a map @@ -867,16 +861,15 @@ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_o */ void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset) { - BMLogVert *lv; - uint v_id = range_tree_uint_take_any(log->unused_ids); - void *key = POINTER_FROM_UINT(v_id); + BMLogVert *lv; + uint v_id = range_tree_uint_take_any(log->unused_ids); + void *key = POINTER_FROM_UINT(v_id); - bm_log_vert_id_set(log, v, v_id); - lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset); - BLI_ghash_insert(log->current_entry->added_verts, key, lv); + bm_log_vert_id_set(log, v, v_id); + lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset); + BLI_ghash_insert(log->current_entry->added_verts, key, lv); } - /* Log a face before it is modified * * This is intended to handle only header flags and we always @@ -884,12 +877,12 @@ void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset) */ void BM_log_face_modified(BMLog *log, BMFace *f) { - BMLogFace *lf; - uint f_id = bm_log_face_id_get(log, f); - void *key = POINTER_FROM_UINT(f_id); + BMLogFace *lf; + uint f_id = bm_log_face_id_get(log, f); + void *key = POINTER_FROM_UINT(f_id); - lf = bm_log_face_alloc(log, f); - BLI_ghash_insert(log->current_entry->modified_faces, key, lf); + lf = bm_log_face_alloc(log, f); + BLI_ghash_insert(log->current_entry->modified_faces, key, lf); } /* Log a new face as added to the BMesh @@ -900,16 +893,16 @@ void BM_log_face_modified(BMLog *log, BMFace *f) */ void BM_log_face_added(BMLog *log, BMFace *f) { - BMLogFace *lf; - uint f_id = range_tree_uint_take_any(log->unused_ids); - void *key = POINTER_FROM_UINT(f_id); + BMLogFace *lf; + uint f_id = range_tree_uint_take_any(log->unused_ids); + void *key = POINTER_FROM_UINT(f_id); - /* Only triangles are supported for now */ - BLI_assert(f->len == 3); + /* Only triangles are supported for now */ + BLI_assert(f->len == 3); - bm_log_face_id_set(log, f, f_id); - lf = bm_log_face_alloc(log, f); - BLI_ghash_insert(log->current_entry->added_faces, key, lf); + bm_log_face_id_set(log, f, f_id); + lf = bm_log_face_alloc(log, f); + BLI_ghash_insert(log->current_entry->added_faces, key, lf); } /* Log a vertex as removed from the BMesh @@ -930,30 +923,30 @@ void BM_log_face_added(BMLog *log, BMFace *f) */ void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset) { - BMLogEntry *entry = log->current_entry; - uint v_id = bm_log_vert_id_get(log, v); - void *key = POINTER_FROM_UINT(v_id); - - /* if it has a key, it shouldn't be NULL */ - BLI_assert(!!BLI_ghash_lookup(entry->added_verts, key) == - !!BLI_ghash_haskey(entry->added_verts, key)); - - if (BLI_ghash_remove(entry->added_verts, key, NULL, NULL)) { - range_tree_uint_release(log->unused_ids, v_id); - } - else { - BMLogVert *lv, *lv_mod; - - lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset); - BLI_ghash_insert(entry->deleted_verts, key, lv); - - /* If the vertex was modified before deletion, ensure that the - * original vertex values are stored */ - if ((lv_mod = BLI_ghash_lookup(entry->modified_verts, key))) { - (*lv) = (*lv_mod); - BLI_ghash_remove(entry->modified_verts, key, NULL, NULL); - } - } + BMLogEntry *entry = log->current_entry; + uint v_id = bm_log_vert_id_get(log, v); + void *key = POINTER_FROM_UINT(v_id); + + /* if it has a key, it shouldn't be NULL */ + BLI_assert(!!BLI_ghash_lookup(entry->added_verts, key) == + !!BLI_ghash_haskey(entry->added_verts, key)); + + if (BLI_ghash_remove(entry->added_verts, key, NULL, NULL)) { + range_tree_uint_release(log->unused_ids, v_id); + } + else { + BMLogVert *lv, *lv_mod; + + lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset); + BLI_ghash_insert(entry->deleted_verts, key, lv); + + /* If the vertex was modified before deletion, ensure that the + * original vertex values are stored */ + if ((lv_mod = BLI_ghash_lookup(entry->modified_verts, key))) { + (*lv) = (*lv_mod); + BLI_ghash_remove(entry->modified_verts, key, NULL, NULL); + } + } } /* Log a face as removed from the BMesh @@ -971,70 +964,70 @@ void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset) */ void BM_log_face_removed(BMLog *log, BMFace *f) { - BMLogEntry *entry = log->current_entry; - uint f_id = bm_log_face_id_get(log, f); - void *key = POINTER_FROM_UINT(f_id); - - /* if it has a key, it shouldn't be NULL */ - BLI_assert(!!BLI_ghash_lookup(entry->added_faces, key) == - !!BLI_ghash_haskey(entry->added_faces, key)); - - if (BLI_ghash_remove(entry->added_faces, key, NULL, NULL)) { - range_tree_uint_release(log->unused_ids, f_id); - } - else { - BMLogFace *lf; - - lf = bm_log_face_alloc(log, f); - BLI_ghash_insert(entry->deleted_faces, key, lf); - } + BMLogEntry *entry = log->current_entry; + uint f_id = bm_log_face_id_get(log, f); + void *key = POINTER_FROM_UINT(f_id); + + /* if it has a key, it shouldn't be NULL */ + BLI_assert(!!BLI_ghash_lookup(entry->added_faces, key) == + !!BLI_ghash_haskey(entry->added_faces, key)); + + if (BLI_ghash_remove(entry->added_faces, key, NULL, NULL)) { + range_tree_uint_release(log->unused_ids, f_id); + } + else { + BMLogFace *lf; + + lf = bm_log_face_alloc(log, f); + BLI_ghash_insert(entry->deleted_faces, key, lf); + } } /* Log all vertices/faces in the BMesh as added */ void BM_log_all_added(BMesh *bm, BMLog *log) { - const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); - BMIter bm_iter; - BMVert *v; - BMFace *f; - - /* avoid unnecessary resizing on initialization */ - if (BLI_ghash_len(log->current_entry->added_verts) == 0) { - BLI_ghash_reserve(log->current_entry->added_verts, (uint)bm->totvert); - } - - if (BLI_ghash_len(log->current_entry->added_faces) == 0) { - BLI_ghash_reserve(log->current_entry->added_faces, (uint)bm->totface); - } - - /* Log all vertices as newly created */ - BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) { - BM_log_vert_added(log, v, cd_vert_mask_offset); - } - - /* Log all faces as newly created */ - BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) { - BM_log_face_added(log, f); - } + const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); + BMIter bm_iter; + BMVert *v; + BMFace *f; + + /* avoid unnecessary resizing on initialization */ + if (BLI_ghash_len(log->current_entry->added_verts) == 0) { + BLI_ghash_reserve(log->current_entry->added_verts, (uint)bm->totvert); + } + + if (BLI_ghash_len(log->current_entry->added_faces) == 0) { + BLI_ghash_reserve(log->current_entry->added_faces, (uint)bm->totface); + } + + /* Log all vertices as newly created */ + BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) { + BM_log_vert_added(log, v, cd_vert_mask_offset); + } + + /* Log all faces as newly created */ + BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) { + BM_log_face_added(log, f); + } } /* Log all vertices/faces in the BMesh as removed */ void BM_log_before_all_removed(BMesh *bm, BMLog *log) { - const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); - BMIter bm_iter; - BMVert *v; - BMFace *f; - - /* Log deletion of all faces */ - BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) { - BM_log_face_removed(log, f); - } - - /* Log deletion of all vertices */ - BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) { - BM_log_vert_removed(log, v, cd_vert_mask_offset); - } + const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); + BMIter bm_iter; + BMVert *v; + BMFace *f; + + /* Log deletion of all faces */ + BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) { + BM_log_face_removed(log, f); + } + + /* Log deletion of all vertices */ + BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) { + BM_log_vert_removed(log, v, cd_vert_mask_offset); + } } /* Get the logged coordinates of a vertex @@ -1042,17 +1035,17 @@ void BM_log_before_all_removed(BMesh *bm, BMLog *log) * Does not modify the log or the vertex */ const float *BM_log_original_vert_co(BMLog *log, BMVert *v) { - BMLogEntry *entry = log->current_entry; - const BMLogVert *lv; - unsigned v_id = bm_log_vert_id_get(log, v); - void *key = POINTER_FROM_UINT(v_id); + BMLogEntry *entry = log->current_entry; + const BMLogVert *lv; + unsigned v_id = bm_log_vert_id_get(log, v); + void *key = POINTER_FROM_UINT(v_id); - BLI_assert(entry); + BLI_assert(entry); - BLI_assert(BLI_ghash_haskey(entry->modified_verts, key)); + BLI_assert(BLI_ghash_haskey(entry->modified_verts, key)); - lv = BLI_ghash_lookup(entry->modified_verts, key); - return lv->co; + lv = BLI_ghash_lookup(entry->modified_verts, key); + return lv->co; } /* Get the logged normal of a vertex @@ -1060,17 +1053,17 @@ const float *BM_log_original_vert_co(BMLog *log, BMVert *v) * Does not modify the log or the vertex */ const short *BM_log_original_vert_no(BMLog *log, BMVert *v) { - BMLogEntry *entry = log->current_entry; - const BMLogVert *lv; - unsigned v_id = bm_log_vert_id_get(log, v); - void *key = POINTER_FROM_UINT(v_id); + BMLogEntry *entry = log->current_entry; + const BMLogVert *lv; + unsigned v_id = bm_log_vert_id_get(log, v); + void *key = POINTER_FROM_UINT(v_id); - BLI_assert(entry); + BLI_assert(entry); - BLI_assert(BLI_ghash_haskey(entry->modified_verts, key)); + BLI_assert(BLI_ghash_haskey(entry->modified_verts, key)); - lv = BLI_ghash_lookup(entry->modified_verts, key); - return lv->no; + lv = BLI_ghash_lookup(entry->modified_verts, key); + return lv->no; } /* Get the logged mask of a vertex @@ -1078,35 +1071,33 @@ const short *BM_log_original_vert_no(BMLog *log, BMVert *v) * Does not modify the log or the vertex */ float BM_log_original_mask(BMLog *log, BMVert *v) { - BMLogEntry *entry = log->current_entry; - const BMLogVert *lv; - unsigned v_id = bm_log_vert_id_get(log, v); - void *key = POINTER_FROM_UINT(v_id); + BMLogEntry *entry = log->current_entry; + const BMLogVert *lv; + unsigned v_id = bm_log_vert_id_get(log, v); + void *key = POINTER_FROM_UINT(v_id); - BLI_assert(entry); + BLI_assert(entry); - BLI_assert(BLI_ghash_haskey(entry->modified_verts, key)); + BLI_assert(BLI_ghash_haskey(entry->modified_verts, key)); - lv = BLI_ghash_lookup(entry->modified_verts, key); - return lv->mask; + lv = BLI_ghash_lookup(entry->modified_verts, key); + return lv->mask; } -void BM_log_original_vert_data( - BMLog *log, BMVert *v, - const float **r_co, const short **r_no) +void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const short **r_no) { - BMLogEntry *entry = log->current_entry; - const BMLogVert *lv; - unsigned v_id = bm_log_vert_id_get(log, v); - void *key = POINTER_FROM_UINT(v_id); + BMLogEntry *entry = log->current_entry; + const BMLogVert *lv; + unsigned v_id = bm_log_vert_id_get(log, v); + void *key = POINTER_FROM_UINT(v_id); - BLI_assert(entry); + BLI_assert(entry); - BLI_assert(BLI_ghash_haskey(entry->modified_verts, key)); + BLI_assert(BLI_ghash_haskey(entry->modified_verts, key)); - lv = BLI_ghash_lookup(entry->modified_verts, key); - *r_co = lv->co; - *r_no = lv->no; + lv = BLI_ghash_lookup(entry->modified_verts, key); + *r_co = lv->co; + *r_no = lv->no; } /************************ Debugging and Testing ***********************/ @@ -1114,13 +1105,13 @@ void BM_log_original_vert_data( /* For internal use only (unit testing) */ BMLogEntry *BM_log_current_entry(BMLog *log) { - return log->current_entry; + return log->current_entry; } /* For internal use only (unit testing) */ RangeTreeUInt *BM_log_unused_ids(BMLog *log) { - return log->unused_ids; + return log->unused_ids; } #if 0 @@ -1129,16 +1120,16 @@ RangeTreeUInt *BM_log_unused_ids(BMLog *log) * Keep around for debugging */ void bm_log_print(const BMLog *log, const char *description) { - const BMLogEntry *entry; - const char *current = " <-- current"; - int i; - - printf("%s:\n", description); - printf(" % 2d: [ initial ]%s\n", 0, - (!log->current_entry) ? current : ""); - for (entry = log->entries.first, i = 1; entry; entry = entry->next, i++) { - printf(" % 2d: [%p]%s\n", i, entry, - (entry == log->current_entry) ? current : ""); - } + const BMLogEntry *entry; + const char *current = " <-- current"; + int i; + + printf("%s:\n", description); + printf(" % 2d: [ initial ]%s\n", 0, + (!log->current_entry) ? current : ""); + for (entry = log->entries.first, i = 1; entry; entry = entry->next, i++) { + printf(" % 2d: [%p]%s\n", i, entry, + (entry == log->current_entry) ? current : ""); + } } #endif diff --git a/source/blender/bmesh/intern/bmesh_log.h b/source/blender/bmesh/intern/bmesh_log.h index 8643e07c622..25c58132802 100644 --- a/source/blender/bmesh/intern/bmesh_log.h +++ b/source/blender/bmesh/intern/bmesh_log.h @@ -93,9 +93,7 @@ const short *BM_log_original_vert_no(BMLog *log, BMVert *v); float BM_log_original_mask(BMLog *log, BMVert *v); /* Get the logged data of a vertex (avoid multiple lookups) */ -void BM_log_original_vert_data( - BMLog *log, BMVert *v, - const float **r_co, const short **r_no); +void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const short **r_no); /* For internal use only (unit testing) */ BMLogEntry *BM_log_current_entry(BMLog *log); diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 53d9b4b1b56..f8ec69b6fe9 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -42,30 +42,28 @@ static void recount_totsels(BMesh *bm) { - const char iter_types[3] = {BM_VERTS_OF_MESH, - BM_EDGES_OF_MESH, - BM_FACES_OF_MESH}; - int *tots[3]; - int i; - - /* recount (tot * sel) variables */ - bm->totvertsel = bm->totedgesel = bm->totfacesel = 0; - tots[0] = &bm->totvertsel; - tots[1] = &bm->totedgesel; - tots[2] = &bm->totfacesel; - - for (i = 0; i < 3; i++) { - BMIter iter; - BMElem *ele; - int count = 0; - - BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - count += 1; - } - } - *tots[i] = count; - } + const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH}; + int *tots[3]; + int i; + + /* recount (tot * sel) variables */ + bm->totvertsel = bm->totedgesel = bm->totfacesel = 0; + tots[0] = &bm->totvertsel; + tots[1] = &bm->totedgesel; + tots[2] = &bm->totfacesel; + + for (i = 0; i < 3; i++) { + BMIter iter; + BMElem *ele; + int count = 0; + + BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + count += 1; + } + } + *tots[i] = count; + } } /** \name BMesh helper functions for selection & hide flushing. @@ -73,88 +71,88 @@ static void recount_totsels(BMesh *bm) static bool bm_vert_is_edge_select_any_other(const BMVert *v, const BMEdge *e_first) { - const BMEdge *e_iter = e_first; - - /* start by stepping over the current edge */ - while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first) { - if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) { - return true; - } - } - return false; + const BMEdge *e_iter = e_first; + + /* start by stepping over the current edge */ + while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first) { + if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) { + return true; + } + } + return false; } #if 0 static bool bm_vert_is_edge_select_any(const BMVert *v) { - if (v->e) { - const BMEdge *e_iter, *e_first; - e_iter = e_first = v->e; - do { - if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) { - return true; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - } - return false; + if (v->e) { + const BMEdge *e_iter, *e_first; + e_iter = e_first = v->e; + do { + if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) { + return true; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } + return false; } #endif static bool bm_vert_is_edge_visible_any(const BMVert *v) { - if (v->e) { - const BMEdge *e_iter, *e_first; - e_iter = e_first = v->e; - do { - if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) { - return true; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - } - return false; + if (v->e) { + const BMEdge *e_iter, *e_first; + e_iter = e_first = v->e; + do { + if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) { + return true; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } + return false; } static bool bm_edge_is_face_select_any_other(BMLoop *l_first) { - const BMLoop *l_iter = l_first; - - /* start by stepping over the current face */ - while ((l_iter = l_iter->radial_next) != l_first) { - if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) { - return true; - } - } - return false; + const BMLoop *l_iter = l_first; + + /* start by stepping over the current face */ + while ((l_iter = l_iter->radial_next) != l_first) { + if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) { + return true; + } + } + return false; } #if 0 static bool bm_edge_is_face_select_any(const BMEdge *e) { - if (e->l) { - const BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) { - return true; - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - return false; + if (e->l) { + const BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) { + return true; + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + return false; } #endif static bool bm_edge_is_face_visible_any(const BMEdge *e) { - if (e->l) { - const BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) { - return true; - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - return false; + if (e->l) { + const BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) { + return true; + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + return false; } /** \} */ @@ -169,67 +167,67 @@ static bool bm_edge_is_face_visible_any(const BMEdge *e) */ void BM_mesh_select_mode_clean_ex(BMesh *bm, const short selectmode) { - if (selectmode & SCE_SELECT_VERTEX) { - /* pass */ - } - else if (selectmode & SCE_SELECT_EDGE) { - BMIter iter; - - if (bm->totvertsel) { - BMVert *v; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BM_elem_flag_disable(v, BM_ELEM_SELECT); - } - bm->totvertsel = 0; - } - - if (bm->totedgesel) { - BMEdge *e; - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - BM_vert_select_set(bm, e->v1, true); - BM_vert_select_set(bm, e->v2, true); - } - } - } - } - else if (selectmode & SCE_SELECT_FACE) { - BMIter iter; - - if (bm->totvertsel) { - BMVert *v; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BM_elem_flag_disable(v, BM_ELEM_SELECT); - } - bm->totvertsel = 0; - } - - if (bm->totedgesel) { - BMEdge *e; - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - BM_elem_flag_disable(e, BM_ELEM_SELECT); - } - bm->totedgesel = 0; - } - - if (bm->totfacesel) { - BMFace *f; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_edge_select_set(bm, l_iter->e, true); - } while ((l_iter = l_iter->next) != l_first); - } - } - } - } + if (selectmode & SCE_SELECT_VERTEX) { + /* pass */ + } + else if (selectmode & SCE_SELECT_EDGE) { + BMIter iter; + + if (bm->totvertsel) { + BMVert *v; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_elem_flag_disable(v, BM_ELEM_SELECT); + } + bm->totvertsel = 0; + } + + if (bm->totedgesel) { + BMEdge *e; + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + BM_vert_select_set(bm, e->v1, true); + BM_vert_select_set(bm, e->v2, true); + } + } + } + } + else if (selectmode & SCE_SELECT_FACE) { + BMIter iter; + + if (bm->totvertsel) { + BMVert *v; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_elem_flag_disable(v, BM_ELEM_SELECT); + } + bm->totvertsel = 0; + } + + if (bm->totedgesel) { + BMEdge *e; + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BM_elem_flag_disable(e, BM_ELEM_SELECT); + } + bm->totedgesel = 0; + } + + if (bm->totfacesel) { + BMFace *f; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BM_edge_select_set(bm, l_iter->e, true); + } while ((l_iter = l_iter->next) != l_first); + } + } + } + } } void BM_mesh_select_mode_clean(BMesh *bm) { - BM_mesh_select_mode_clean_ex(bm, bm->selectmode); + BM_mesh_select_mode_clean_ex(bm, bm->selectmode); } /** @@ -241,74 +239,72 @@ void BM_mesh_select_mode_clean(BMesh *bm) */ void BM_mesh_select_mode_flush_ex(BMesh *bm, const short selectmode) { - BMEdge *e; - BMLoop *l_iter; - BMLoop *l_first; - BMFace *f; - - BMIter eiter; - BMIter fiter; - - if (selectmode & SCE_SELECT_VERTEX) { - /* both loops only set edge/face flags and read off verts */ - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && - BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && - !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) - { - BM_elem_flag_enable(e, BM_ELEM_SELECT); - } - else { - BM_elem_flag_disable(e, BM_ELEM_SELECT); - } - } - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - bool ok = true; - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { - ok = false; - break; - } - } while ((l_iter = l_iter->next) != l_first); - } - else { - ok = false; - } - - BM_elem_flag_set(f, BM_ELEM_SELECT, ok); - } - } - else if (selectmode & SCE_SELECT_EDGE) { - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - bool ok = true; - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (!BM_elem_flag_test(l_iter->e, BM_ELEM_SELECT)) { - ok = false; - break; - } - } while ((l_iter = l_iter->next) != l_first); - } - else { - ok = false; - } - - BM_elem_flag_set(f, BM_ELEM_SELECT, ok); - } - } - - /* Remove any deselected elements from the BMEditSelection */ - BM_select_history_validate(bm); - - recount_totsels(bm); + BMEdge *e; + BMLoop *l_iter; + BMLoop *l_first; + BMFace *f; + + BMIter eiter; + BMIter fiter; + + if (selectmode & SCE_SELECT_VERTEX) { + /* both loops only set edge/face flags and read off verts */ + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && + !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + BM_elem_flag_enable(e, BM_ELEM_SELECT); + } + else { + BM_elem_flag_disable(e, BM_ELEM_SELECT); + } + } + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + bool ok = true; + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { + ok = false; + break; + } + } while ((l_iter = l_iter->next) != l_first); + } + else { + ok = false; + } + + BM_elem_flag_set(f, BM_ELEM_SELECT, ok); + } + } + else if (selectmode & SCE_SELECT_EDGE) { + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + bool ok = true; + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (!BM_elem_flag_test(l_iter->e, BM_ELEM_SELECT)) { + ok = false; + break; + } + } while ((l_iter = l_iter->next) != l_first); + } + else { + ok = false; + } + + BM_elem_flag_set(f, BM_ELEM_SELECT, ok); + } + } + + /* Remove any deselected elements from the BMEditSelection */ + BM_select_history_validate(bm); + + recount_totsels(bm); } void BM_mesh_select_mode_flush(BMesh *bm) { - BM_mesh_select_mode_flush_ex(bm, bm->selectmode); + BM_mesh_select_mode_flush_ex(bm, bm->selectmode); } /** @@ -316,82 +312,78 @@ void BM_mesh_select_mode_flush(BMesh *bm) */ void BM_mesh_deselect_flush(BMesh *bm) { - BMIter eiter; - BMEdge *e; - - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - if (!BM_elem_flag_test(e->v1, BM_ELEM_SELECT) || - !BM_elem_flag_test(e->v2, BM_ELEM_SELECT)) - { - BM_elem_flag_disable(e, BM_ELEM_SELECT); - } - } - - if (e->l && !BM_elem_flag_test(e, BM_ELEM_SELECT)) { - BMLoop *l_iter; - BMLoop *l_first; - - l_iter = l_first = e->l; - do { - BM_elem_flag_disable(l_iter->f, BM_ELEM_SELECT); - } while ((l_iter = l_iter->radial_next) != l_first); - } - } - } - - /* Remove any deselected elements from the BMEditSelection */ - BM_select_history_validate(bm); - - recount_totsels(bm); + BMIter eiter; + BMEdge *e; + + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + if (!BM_elem_flag_test(e->v1, BM_ELEM_SELECT) || + !BM_elem_flag_test(e->v2, BM_ELEM_SELECT)) { + BM_elem_flag_disable(e, BM_ELEM_SELECT); + } + } + + if (e->l && !BM_elem_flag_test(e, BM_ELEM_SELECT)) { + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = e->l; + do { + BM_elem_flag_disable(l_iter->f, BM_ELEM_SELECT); + } while ((l_iter = l_iter->radial_next) != l_first); + } + } + } + + /* Remove any deselected elements from the BMEditSelection */ + BM_select_history_validate(bm); + + recount_totsels(bm); } - /** * mode independent flushing up/down */ void BM_mesh_select_flush(BMesh *bm) { - BMEdge *e; - BMLoop *l_iter; - BMLoop *l_first; - BMFace *f; - - BMIter eiter; - BMIter fiter; - - bool ok; - - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && - BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && - !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) - { - BM_elem_flag_enable(e, BM_ELEM_SELECT); - } - } - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - ok = true; - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { - ok = false; - break; - } - } while ((l_iter = l_iter->next) != l_first); - } - else { - ok = false; - } - - if (ok) { - BM_elem_flag_enable(f, BM_ELEM_SELECT); - } - } - - recount_totsels(bm); + BMEdge *e; + BMLoop *l_iter; + BMLoop *l_first; + BMFace *f; + + BMIter eiter; + BMIter fiter; + + bool ok; + + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && + !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + BM_elem_flag_enable(e, BM_ELEM_SELECT); + } + } + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + ok = true; + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { + ok = false; + break; + } + } while ((l_iter = l_iter->next) != l_first); + } + else { + ok = false; + } + + if (ok) { + BM_elem_flag_enable(f, BM_ELEM_SELECT); + } + } + + recount_totsels(bm); } /** @@ -402,24 +394,24 @@ void BM_mesh_select_flush(BMesh *bm) */ void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select) { - BLI_assert(v->head.htype == BM_VERT); - - if (BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - return; - } - - if (select) { - if (!BM_elem_flag_test(v, BM_ELEM_SELECT)) { - BM_elem_flag_enable(v, BM_ELEM_SELECT); - bm->totvertsel += 1; - } - } - else { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - bm->totvertsel -= 1; - BM_elem_flag_disable(v, BM_ELEM_SELECT); - } - } + BLI_assert(v->head.htype == BM_VERT); + + if (BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + return; + } + + if (select) { + if (!BM_elem_flag_test(v, BM_ELEM_SELECT)) { + BM_elem_flag_enable(v, BM_ELEM_SELECT); + bm->totvertsel += 1; + } + } + else { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + bm->totvertsel -= 1; + BM_elem_flag_disable(v, BM_ELEM_SELECT); + } + } } /** @@ -429,43 +421,42 @@ void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select) */ void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select) { - BLI_assert(e->head.htype == BM_EDGE); - - if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - return; - } - - if (select) { - if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) { - BM_elem_flag_enable(e, BM_ELEM_SELECT); - bm->totedgesel += 1; - } - BM_vert_select_set(bm, e->v1, true); - BM_vert_select_set(bm, e->v2, true); - } - else { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - BM_elem_flag_disable(e, BM_ELEM_SELECT); - bm->totedgesel -= 1; - } - - if ((bm->selectmode & SCE_SELECT_VERTEX) == 0) { - int i; - - /* check if the vert is used by a selected edge */ - for (i = 0; i < 2; i++) { - BMVert *v = *((&e->v1) + i); - if (bm_vert_is_edge_select_any_other(v, e) == false) { - BM_vert_select_set(bm, v, false); - } - } - } - else { - BM_vert_select_set(bm, e->v1, false); - BM_vert_select_set(bm, e->v2, false); - } - - } + BLI_assert(e->head.htype == BM_EDGE); + + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + return; + } + + if (select) { + if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) { + BM_elem_flag_enable(e, BM_ELEM_SELECT); + bm->totedgesel += 1; + } + BM_vert_select_set(bm, e->v1, true); + BM_vert_select_set(bm, e->v2, true); + } + else { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + BM_elem_flag_disable(e, BM_ELEM_SELECT); + bm->totedgesel -= 1; + } + + if ((bm->selectmode & SCE_SELECT_VERTEX) == 0) { + int i; + + /* check if the vert is used by a selected edge */ + for (i = 0; i < 2; i++) { + BMVert *v = *((&e->v1) + i); + if (bm_vert_is_edge_select_any_other(v, e) == false) { + BM_vert_select_set(bm, v, false); + } + } + } + else { + BM_vert_select_set(bm, e->v1, false); + BM_vert_select_set(bm, e->v2, false); + } + } } /** @@ -476,77 +467,77 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select) */ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select) { - BMLoop *l_iter; - BMLoop *l_first; - - BLI_assert(f->head.htype == BM_FACE); - - if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - return; - } - - if (select) { - if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_elem_flag_enable(f, BM_ELEM_SELECT); - bm->totfacesel += 1; - } - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_vert_select_set(bm, l_iter->v, true); - BM_edge_select_set(bm, l_iter->e, true); - } while ((l_iter = l_iter->next) != l_first); - } - else { - - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_elem_flag_disable(f, BM_ELEM_SELECT); - bm->totfacesel -= 1; - } - /** - * \note This allows a temporarily invalid state - where for eg - * an edge bay be de-selected, but an adjacent face remains selected. - * - * Rely on #BM_mesh_select_mode_flush to correct these cases. - * - * \note flushing based on mode, see T46494 - */ - if (bm->selectmode & SCE_SELECT_VERTEX) { - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_vert_select_set(bm, l_iter->v, false); - BM_edge_select_set_noflush(bm, l_iter->e, false); - } while ((l_iter = l_iter->next) != l_first); - } - else { - /** - * \note use #BM_edge_select_set_noflush, - * vertex flushing is handled last. - */ - if (bm->selectmode & SCE_SELECT_EDGE) { - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_edge_select_set_noflush(bm, l_iter->e, false); - } while ((l_iter = l_iter->next) != l_first); - } - else { - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (bm_edge_is_face_select_any_other(l_iter) == false) { - BM_edge_select_set_noflush(bm, l_iter->e, false); - } - } while ((l_iter = l_iter->next) != l_first); - } - - /* flush down to verts */ - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (bm_vert_is_edge_select_any_other(l_iter->v, l_iter->e) == false) { - BM_vert_select_set(bm, l_iter->v, false); - } - } while ((l_iter = l_iter->next) != l_first); - } - } + BMLoop *l_iter; + BMLoop *l_first; + + BLI_assert(f->head.htype == BM_FACE); + + if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + return; + } + + if (select) { + if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) { + BM_elem_flag_enable(f, BM_ELEM_SELECT); + bm->totfacesel += 1; + } + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BM_vert_select_set(bm, l_iter->v, true); + BM_edge_select_set(bm, l_iter->e, true); + } while ((l_iter = l_iter->next) != l_first); + } + else { + + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + BM_elem_flag_disable(f, BM_ELEM_SELECT); + bm->totfacesel -= 1; + } + /** + * \note This allows a temporarily invalid state - where for eg + * an edge bay be de-selected, but an adjacent face remains selected. + * + * Rely on #BM_mesh_select_mode_flush to correct these cases. + * + * \note flushing based on mode, see T46494 + */ + if (bm->selectmode & SCE_SELECT_VERTEX) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BM_vert_select_set(bm, l_iter->v, false); + BM_edge_select_set_noflush(bm, l_iter->e, false); + } while ((l_iter = l_iter->next) != l_first); + } + else { + /** + * \note use #BM_edge_select_set_noflush, + * vertex flushing is handled last. + */ + if (bm->selectmode & SCE_SELECT_EDGE) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BM_edge_select_set_noflush(bm, l_iter->e, false); + } while ((l_iter = l_iter->next) != l_first); + } + else { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (bm_edge_is_face_select_any_other(l_iter) == false) { + BM_edge_select_set_noflush(bm, l_iter->e, false); + } + } while ((l_iter = l_iter->next) != l_first); + } + + /* flush down to verts */ + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (bm_vert_is_edge_select_any_other(l_iter->v, l_iter->e) == false) { + BM_vert_select_set(bm, l_iter->v, false); + } + } while ((l_iter = l_iter->next) != l_first); + } + } } /** \name Non flushing versions element selection. @@ -554,46 +545,46 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select) void BM_edge_select_set_noflush(BMesh *bm, BMEdge *e, const bool select) { - BLI_assert(e->head.htype == BM_EDGE); - - if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - return; - } - - if (select) { - if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) { - BM_elem_flag_enable(e, BM_ELEM_SELECT); - bm->totedgesel += 1; - } - } - else { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - BM_elem_flag_disable(e, BM_ELEM_SELECT); - bm->totedgesel -= 1; - } - } + BLI_assert(e->head.htype == BM_EDGE); + + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + return; + } + + if (select) { + if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) { + BM_elem_flag_enable(e, BM_ELEM_SELECT); + bm->totedgesel += 1; + } + } + else { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + BM_elem_flag_disable(e, BM_ELEM_SELECT); + bm->totedgesel -= 1; + } + } } void BM_face_select_set_noflush(BMesh *bm, BMFace *f, const bool select) { - BLI_assert(f->head.htype == BM_FACE); - - if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - return; - } - - if (select) { - if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_elem_flag_enable(f, BM_ELEM_SELECT); - bm->totfacesel += 1; - } - } - else { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_elem_flag_disable(f, BM_ELEM_SELECT); - bm->totfacesel -= 1; - } - } + BLI_assert(f->head.htype == BM_FACE); + + if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + return; + } + + if (select) { + if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) { + BM_elem_flag_enable(f, BM_ELEM_SELECT); + bm->totfacesel += 1; + } + } + else { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + BM_elem_flag_disable(f, BM_ELEM_SELECT); + bm->totfacesel -= 1; + } + } } /** \} */ @@ -606,109 +597,117 @@ void BM_face_select_set_noflush(BMesh *bm, BMFace *f, const bool select) */ void BM_mesh_select_mode_set(BMesh *bm, int selectmode) { - BMIter iter; - BMElem *ele; + BMIter iter; + BMElem *ele; - bm->selectmode = selectmode; + bm->selectmode = selectmode; - if (bm->selectmode & SCE_SELECT_VERTEX) { - /* disabled because selection flushing handles these */ + if (bm->selectmode & SCE_SELECT_VERTEX) { + /* disabled because selection flushing handles these */ #if 0 - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - BM_elem_flag_disable(ele, BM_ELEM_SELECT); - } - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - BM_elem_flag_disable(ele, BM_ELEM_SELECT); - } + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + BM_elem_flag_disable(ele, BM_ELEM_SELECT); + } + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + BM_elem_flag_disable(ele, BM_ELEM_SELECT); + } #endif - BM_mesh_select_mode_flush(bm); - } - else if (bm->selectmode & SCE_SELECT_EDGE) { - /* disabled because selection flushing handles these */ + BM_mesh_select_mode_flush(bm); + } + else if (bm->selectmode & SCE_SELECT_EDGE) { + /* disabled because selection flushing handles these */ #if 0 - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - BM_elem_flag_disable(ele, BM_ELEM_SELECT); - } + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + BM_elem_flag_disable(ele, BM_ELEM_SELECT); + } #endif - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - BM_edge_select_set(bm, (BMEdge *)ele, true); - } - } - BM_mesh_select_mode_flush(bm); - } - else if (bm->selectmode & SCE_SELECT_FACE) { - /* disabled because selection flushing handles these */ + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + BM_edge_select_set(bm, (BMEdge *)ele, true); + } + } + BM_mesh_select_mode_flush(bm); + } + else if (bm->selectmode & SCE_SELECT_FACE) { + /* disabled because selection flushing handles these */ #if 0 - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - BM_elem_flag_disable(ele, BM_ELEM_SELECT); - } + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + BM_elem_flag_disable(ele, BM_ELEM_SELECT); + } #endif - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - BM_face_select_set(bm, (BMFace *)ele, true); - } - } - BM_mesh_select_mode_flush(bm); - } + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + BM_face_select_set(bm, (BMFace *)ele, true); + } + } + BM_mesh_select_mode_flush(bm); + } } /** * counts number of elements with flag enabled/disabled */ -static int bm_mesh_flag_count( - BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool test_for_enabled) +static int bm_mesh_flag_count(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide, + const bool test_for_enabled) { - BMElem *ele; - BMIter iter; - int tot = 0; - - BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); - - if (htype & BM_VERT) { - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) { - continue; - } - if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - tot++; - } - } - } - if (htype & BM_EDGE) { - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) { - continue; - } - if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - tot++; - } - } - } - if (htype & BM_FACE) { - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) { - continue; - } - if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - tot++; - } - } - } - - return tot; + BMElem *ele; + BMIter iter; + int tot = 0; + + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + + if (htype & BM_VERT) { + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) { + continue; + } + if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { + tot++; + } + } + } + if (htype & BM_EDGE) { + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) { + continue; + } + if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { + tot++; + } + } + } + if (htype & BM_FACE) { + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) { + continue; + } + if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { + tot++; + } + } + } + + return tot; } -int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, const bool respecthide) +int BM_mesh_elem_hflag_count_enabled(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide) { - return bm_mesh_flag_count(bm, htype, hflag, respecthide, true); + return bm_mesh_flag_count(bm, htype, hflag, respecthide, true); } -int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, const bool respecthide) +int BM_mesh_elem_hflag_count_disabled(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide) { - return bm_mesh_flag_count(bm, htype, hflag, respecthide, false); + return bm_mesh_flag_count(bm, htype, hflag, respecthide, false); } /** @@ -717,105 +716,105 @@ int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hf */ void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select) { - switch (ele->head.htype) { - case BM_VERT: - BM_vert_select_set(bm, (BMVert *)ele, select); - break; - case BM_EDGE: - BM_edge_select_set(bm, (BMEdge *)ele, select); - break; - case BM_FACE: - BM_face_select_set(bm, (BMFace *)ele, select); - break; - default: - BLI_assert(0); - break; - } + switch (ele->head.htype) { + case BM_VERT: + BM_vert_select_set(bm, (BMVert *)ele, select); + break; + case BM_EDGE: + BM_edge_select_set(bm, (BMEdge *)ele, select); + break; + case BM_FACE: + BM_face_select_set(bm, (BMFace *)ele, select); + break; + default: + BLI_assert(0); + break; + } } /* this replaces the active flag used in uv/face mode */ void BM_mesh_active_face_set(BMesh *bm, BMFace *efa) { - bm->act_face = efa; + bm->act_face = efa; } BMFace *BM_mesh_active_face_get(BMesh *bm, const bool is_sloppy, const bool is_selected) { - if (bm->act_face && (!is_selected || BM_elem_flag_test(bm->act_face, BM_ELEM_SELECT))) { - return bm->act_face; - } - else if (is_sloppy) { - BMIter iter; - BMFace *f = NULL; - BMEditSelection *ese; - - /* Find the latest non-hidden face from the BMEditSelection */ - ese = bm->selected.last; - for ( ; ese; ese = ese->prev) { - if (ese->htype == BM_FACE) { - f = (BMFace *)ese->ele; - - if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - f = NULL; - } - else if (is_selected && !BM_elem_flag_test(f, BM_ELEM_SELECT)) { - f = NULL; - } - else { - break; - } - } - } - /* Last attempt: try to find any selected face */ - if (f == NULL) { - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - break; - } - } - } - return f; /* can still be null */ - } - return NULL; + if (bm->act_face && (!is_selected || BM_elem_flag_test(bm->act_face, BM_ELEM_SELECT))) { + return bm->act_face; + } + else if (is_sloppy) { + BMIter iter; + BMFace *f = NULL; + BMEditSelection *ese; + + /* Find the latest non-hidden face from the BMEditSelection */ + ese = bm->selected.last; + for (; ese; ese = ese->prev) { + if (ese->htype == BM_FACE) { + f = (BMFace *)ese->ele; + + if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + f = NULL; + } + else if (is_selected && !BM_elem_flag_test(f, BM_ELEM_SELECT)) { + f = NULL; + } + else { + break; + } + } + } + /* Last attempt: try to find any selected face */ + if (f == NULL) { + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + break; + } + } + } + return f; /* can still be null */ + } + return NULL; } BMEdge *BM_mesh_active_edge_get(BMesh *bm) { - if (bm->selected.last) { - BMEditSelection *ese = bm->selected.last; + if (bm->selected.last) { + BMEditSelection *ese = bm->selected.last; - if (ese && ese->htype == BM_EDGE) { - return (BMEdge *)ese->ele; - } - } + if (ese && ese->htype == BM_EDGE) { + return (BMEdge *)ese->ele; + } + } - return NULL; + return NULL; } BMVert *BM_mesh_active_vert_get(BMesh *bm) { - if (bm->selected.last) { - BMEditSelection *ese = bm->selected.last; + if (bm->selected.last) { + BMEditSelection *ese = bm->selected.last; - if (ese && ese->htype == BM_VERT) { - return (BMVert *)ese->ele; - } - } + if (ese && ese->htype == BM_VERT) { + return (BMVert *)ese->ele; + } + } - return NULL; + return NULL; } BMElem *BM_mesh_active_elem_get(BMesh *bm) { - if (bm->selected.last) { - BMEditSelection *ese = bm->selected.last; + if (bm->selected.last) { + BMEditSelection *ese = bm->selected.last; - if (ese) { - return ese->ele; - } - } + if (ese) { + return ese->ele; + } + } - return NULL; + return NULL; } /** @@ -829,47 +828,46 @@ BMElem *BM_mesh_active_elem_get(BMesh *bm) */ void BM_editselection_center(BMEditSelection *ese, float r_center[3]) { - if (ese->htype == BM_VERT) { - BMVert *eve = (BMVert *)ese->ele; - copy_v3_v3(r_center, eve->co); - } - else if (ese->htype == BM_EDGE) { - BMEdge *eed = (BMEdge *)ese->ele; - mid_v3_v3v3(r_center, eed->v1->co, eed->v2->co); - } - else if (ese->htype == BM_FACE) { - BMFace *efa = (BMFace *)ese->ele; - BM_face_calc_center_median(efa, r_center); - } + if (ese->htype == BM_VERT) { + BMVert *eve = (BMVert *)ese->ele; + copy_v3_v3(r_center, eve->co); + } + else if (ese->htype == BM_EDGE) { + BMEdge *eed = (BMEdge *)ese->ele; + mid_v3_v3v3(r_center, eed->v1->co, eed->v2->co); + } + else if (ese->htype == BM_FACE) { + BMFace *efa = (BMFace *)ese->ele; + BM_face_calc_center_median(efa, r_center); + } } void BM_editselection_normal(BMEditSelection *ese, float r_normal[3]) { - if (ese->htype == BM_VERT) { - BMVert *eve = (BMVert *)ese->ele; - copy_v3_v3(r_normal, eve->no); - } - else if (ese->htype == BM_EDGE) { - BMEdge *eed = (BMEdge *)ese->ele; - float plane[3]; /* need a plane to correct the normal */ - float vec[3]; /* temp vec storage */ - - add_v3_v3v3(r_normal, eed->v1->no, eed->v2->no); - sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); - - /* the 2 vertex normals will be close but not at rightangles to the edge - * for rotate about edge we want them to be at right angles, so we need to - * do some extra calculation to correct the vert normals, - * we need the plane for this */ - cross_v3_v3v3(vec, r_normal, plane); - cross_v3_v3v3(r_normal, plane, vec); - normalize_v3(r_normal); - - } - else if (ese->htype == BM_FACE) { - BMFace *efa = (BMFace *)ese->ele; - copy_v3_v3(r_normal, efa->no); - } + if (ese->htype == BM_VERT) { + BMVert *eve = (BMVert *)ese->ele; + copy_v3_v3(r_normal, eve->no); + } + else if (ese->htype == BM_EDGE) { + BMEdge *eed = (BMEdge *)ese->ele; + float plane[3]; /* need a plane to correct the normal */ + float vec[3]; /* temp vec storage */ + + add_v3_v3v3(r_normal, eed->v1->no, eed->v2->no); + sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); + + /* the 2 vertex normals will be close but not at rightangles to the edge + * for rotate about edge we want them to be at right angles, so we need to + * do some extra calculation to correct the vert normals, + * we need the plane for this */ + cross_v3_v3v3(vec, r_normal, plane); + cross_v3_v3v3(r_normal, plane, vec); + normalize_v3(r_normal); + } + else if (ese->htype == BM_FACE) { + BMFace *efa = (BMFace *)ese->ele; + copy_v3_v3(r_normal, efa->no); + } } /* Calculate a plane that is rightangles to the edge/vert/faces normal @@ -877,137 +875,142 @@ void BM_editselection_normal(BMEditSelection *ese, float r_normal[3]) * because this is used for the gizmos Y axis. */ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]) { - if (ese->htype == BM_VERT) { - BMVert *eve = (BMVert *)ese->ele; - float vec[3] = {0.0f, 0.0f, 0.0f}; - - if (ese->prev) { /* use previously selected data to make a useful vertex plane */ - BM_editselection_center(ese->prev, vec); - sub_v3_v3v3(r_plane, vec, eve->co); - } - else { - /* make a fake plane thats at rightangles to the normal - * we cant make a crossvec from a vec thats the same as the vec - * unlikely but possible, so make sure if the normal is (0, 0, 1) - * that vec isn't the same or in the same direction even. */ - if (eve->no[0] < 0.5f) { vec[0] = 1.0f; } - else if (eve->no[1] < 0.5f) { vec[1] = 1.0f; } - else { vec[2] = 1.0f; } - cross_v3_v3v3(r_plane, eve->no, vec); - } - normalize_v3(r_plane); - } - else if (ese->htype == BM_EDGE) { - BMEdge *eed = (BMEdge *)ese->ele; - - if (BM_edge_is_boundary(eed)) { - sub_v3_v3v3(r_plane, eed->l->v->co, eed->l->next->v->co); - } - else { - /* the plane is simple, it runs along the edge - * however selecting different edges can swap the direction of the y axis. - * this makes it less likely for the y axis of the gizmo - * (running along the edge).. to flip less often. - * at least its more predictable */ - if (eed->v2->co[1] > eed->v1->co[1]) { /* check which to do first */ - sub_v3_v3v3(r_plane, eed->v2->co, eed->v1->co); - } - else { - sub_v3_v3v3(r_plane, eed->v1->co, eed->v2->co); - } - } - - normalize_v3(r_plane); - } - else if (ese->htype == BM_FACE) { - BMFace *efa = (BMFace *)ese->ele; - BM_face_calc_tangent_auto(efa, r_plane); - } + if (ese->htype == BM_VERT) { + BMVert *eve = (BMVert *)ese->ele; + float vec[3] = {0.0f, 0.0f, 0.0f}; + + if (ese->prev) { /* use previously selected data to make a useful vertex plane */ + BM_editselection_center(ese->prev, vec); + sub_v3_v3v3(r_plane, vec, eve->co); + } + else { + /* make a fake plane thats at rightangles to the normal + * we cant make a crossvec from a vec thats the same as the vec + * unlikely but possible, so make sure if the normal is (0, 0, 1) + * that vec isn't the same or in the same direction even. */ + if (eve->no[0] < 0.5f) { + vec[0] = 1.0f; + } + else if (eve->no[1] < 0.5f) { + vec[1] = 1.0f; + } + else { + vec[2] = 1.0f; + } + cross_v3_v3v3(r_plane, eve->no, vec); + } + normalize_v3(r_plane); + } + else if (ese->htype == BM_EDGE) { + BMEdge *eed = (BMEdge *)ese->ele; + + if (BM_edge_is_boundary(eed)) { + sub_v3_v3v3(r_plane, eed->l->v->co, eed->l->next->v->co); + } + else { + /* the plane is simple, it runs along the edge + * however selecting different edges can swap the direction of the y axis. + * this makes it less likely for the y axis of the gizmo + * (running along the edge).. to flip less often. + * at least its more predictable */ + if (eed->v2->co[1] > eed->v1->co[1]) { /* check which to do first */ + sub_v3_v3v3(r_plane, eed->v2->co, eed->v1->co); + } + else { + sub_v3_v3v3(r_plane, eed->v1->co, eed->v2->co); + } + } + + normalize_v3(r_plane); + } + else if (ese->htype == BM_FACE) { + BMFace *efa = (BMFace *)ese->ele; + BM_face_calc_tangent_auto(efa, r_plane); + } } static BMEditSelection *bm_select_history_create(BMHeader *ele) { - BMEditSelection *ese = (BMEditSelection *) MEM_callocN(sizeof(BMEditSelection), "BMEdit Selection"); - ese->htype = ele->htype; - ese->ele = (BMElem *)ele; - return ese; + BMEditSelection *ese = (BMEditSelection *)MEM_callocN(sizeof(BMEditSelection), + "BMEdit Selection"); + ese->htype = ele->htype; + ese->ele = (BMElem *)ele; + return ese; } /* --- macro wrapped funcs --- */ bool _bm_select_history_check(BMesh *bm, const BMHeader *ele) { - return (BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele)) != NULL); + return (BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele)) != NULL); } bool _bm_select_history_remove(BMesh *bm, BMHeader *ele) { - BMEditSelection *ese = BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele)); - if (ese) { - BLI_freelinkN(&bm->selected, ese); - return true; - } - else { - return false; - } + BMEditSelection *ese = BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele)); + if (ese) { + BLI_freelinkN(&bm->selected, ese); + return true; + } + else { + return false; + } } void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele) { - BMEditSelection *ese = bm_select_history_create(ele); - BLI_addtail(&(bm->selected), ese); + BMEditSelection *ese = bm_select_history_create(ele); + BLI_addtail(&(bm->selected), ese); } void _bm_select_history_store_head_notest(BMesh *bm, BMHeader *ele) { - BMEditSelection *ese = bm_select_history_create(ele); - BLI_addhead(&(bm->selected), ese); + BMEditSelection *ese = bm_select_history_create(ele); + BLI_addhead(&(bm->selected), ese); } void _bm_select_history_store(BMesh *bm, BMHeader *ele) { - if (!BM_select_history_check(bm, (BMElem *)ele)) { - BM_select_history_store_notest(bm, (BMElem *)ele); - } + if (!BM_select_history_check(bm, (BMElem *)ele)) { + BM_select_history_store_notest(bm, (BMElem *)ele); + } } void _bm_select_history_store_head(BMesh *bm, BMHeader *ele) { - if (!BM_select_history_check(bm, (BMElem *)ele)) { - BM_select_history_store_head_notest(bm, (BMElem *)ele); - } + if (!BM_select_history_check(bm, (BMElem *)ele)) { + BM_select_history_store_head_notest(bm, (BMElem *)ele); + } } void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele) { - BMEditSelection *ese = bm_select_history_create(ele); - BLI_insertlinkafter(&(bm->selected), ese_ref, ese); + BMEditSelection *ese = bm_select_history_create(ele); + BLI_insertlinkafter(&(bm->selected), ese_ref, ese); } void _bm_select_history_store_after(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele) { - if (!BM_select_history_check(bm, (BMElem *)ele)) { - BM_select_history_store_after_notest(bm, ese_ref, (BMElem *)ele); - } + if (!BM_select_history_check(bm, (BMElem *)ele)) { + BM_select_history_store_after_notest(bm, ese_ref, (BMElem *)ele); + } } /* --- end macro wrapped funcs --- */ - void BM_select_history_clear(BMesh *bm) { - BLI_freelistN(&bm->selected); + BLI_freelistN(&bm->selected); } - void BM_select_history_validate(BMesh *bm) { - BMEditSelection *ese, *ese_next; - - for (ese = bm->selected.first; ese; ese = ese_next) { - ese_next = ese->next; - if (!BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) { - BLI_freelinkN(&(bm->selected), ese); - } - } + BMEditSelection *ese, *ese_next; + + for (ese = bm->selected.first; ese; ese = ese_next) { + ese_next = ese->next; + if (!BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) { + BLI_freelinkN(&(bm->selected), ese); + } + } } /** @@ -1015,37 +1018,38 @@ void BM_select_history_validate(BMesh *bm) */ bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese) { - BMEditSelection *ese_last = bm->selected.last; - BMFace *efa = BM_mesh_active_face_get(bm, false, false); - - ese->next = ese->prev = NULL; - - if (ese_last) { - if (ese_last->htype == BM_FACE) { /* if there is an active face, use it over the last selected face */ - if (efa) { - ese->ele = (BMElem *)efa; - } - else { - ese->ele = ese_last->ele; - } - ese->htype = BM_FACE; - } - else { - ese->ele = ese_last->ele; - ese->htype = ese_last->htype; - } - } - else if (efa) { - /* no edit-selection, fallback to active face */ - ese->ele = (BMElem *)efa; - ese->htype = BM_FACE; - } - else { - ese->ele = NULL; - return false; - } - - return true; + BMEditSelection *ese_last = bm->selected.last; + BMFace *efa = BM_mesh_active_face_get(bm, false, false); + + ese->next = ese->prev = NULL; + + if (ese_last) { + if (ese_last->htype == + BM_FACE) { /* if there is an active face, use it over the last selected face */ + if (efa) { + ese->ele = (BMElem *)efa; + } + else { + ese->ele = ese_last->ele; + } + ese->htype = BM_FACE; + } + else { + ese->ele = ese_last->ele; + ese->htype = ese_last->htype; + } + } + else if (efa) { + /* no edit-selection, fallback to active face */ + ese->ele = (BMElem *)efa; + ese->htype = BM_FACE; + } + else { + ese->ele = NULL; + return false; + } + + return true; } /** @@ -1053,220 +1057,225 @@ bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese) */ GHash *BM_select_history_map_create(BMesh *bm) { - BMEditSelection *ese; - GHash *map; + BMEditSelection *ese; + GHash *map; - if (BLI_listbase_is_empty(&bm->selected)) { - return NULL; - } + if (BLI_listbase_is_empty(&bm->selected)) { + return NULL; + } - map = BLI_ghash_ptr_new(__func__); + map = BLI_ghash_ptr_new(__func__); - for (ese = bm->selected.first; ese; ese = ese->next) { - BLI_ghash_insert(map, ese->ele, ese); - } + for (ese = bm->selected.first; ese; ese = ese->next) { + BLI_ghash_insert(map, ese->ele, ese); + } - return map; + return map; } /** * Map arguments may all be the same pointer. */ void BM_select_history_merge_from_targetmap( - BMesh *bm, - GHash *vert_map, - GHash *edge_map, - GHash *face_map, - const bool use_chain) + BMesh *bm, GHash *vert_map, GHash *edge_map, GHash *face_map, const bool use_chain) { #ifdef DEBUG - for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) { - BLI_assert(BM_ELEM_API_FLAG_TEST(ese->ele, _FLAG_OVERLAP) == 0); - } + for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) { + BLI_assert(BM_ELEM_API_FLAG_TEST(ese->ele, _FLAG_OVERLAP) == 0); + } #endif - for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) { - BM_ELEM_API_FLAG_ENABLE(ese->ele, _FLAG_OVERLAP); - - /* Only loop when (use_chain == true). */ - GHash *map = NULL; - switch (ese->ele->head.htype) { - case BM_VERT: map = vert_map; break; - case BM_EDGE: map = edge_map; break; - case BM_FACE: map = face_map; break; - default: BMESH_ASSERT(0); break; - } - if (map != NULL) { - BMElem *ele_dst = ese->ele; - while (true) { - BMElem *ele_dst_next = BLI_ghash_lookup(map, ele_dst); - BLI_assert(ele_dst != ele_dst_next); - if (ele_dst_next == NULL) { - break; - } - ele_dst = ele_dst_next; - /* Break loop on circular reference (should never happen). */ - if (UNLIKELY(ele_dst == ese->ele)) { - BLI_assert(0); - break; - } - if (use_chain == false) { - break; - } - } - ese->ele = ele_dst; - } - } - - /* Remove overlapping duplicates. */ - for (BMEditSelection *ese = bm->selected.first, *ese_next; ese; ese = ese_next) { - ese_next = ese->next; - if (BM_ELEM_API_FLAG_TEST(ese->ele, _FLAG_OVERLAP)) { - BM_ELEM_API_FLAG_DISABLE(ese->ele, _FLAG_OVERLAP); - } - else { - BLI_freelinkN(&bm->selected, ese); - } - } + for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) { + BM_ELEM_API_FLAG_ENABLE(ese->ele, _FLAG_OVERLAP); + + /* Only loop when (use_chain == true). */ + GHash *map = NULL; + switch (ese->ele->head.htype) { + case BM_VERT: + map = vert_map; + break; + case BM_EDGE: + map = edge_map; + break; + case BM_FACE: + map = face_map; + break; + default: + BMESH_ASSERT(0); + break; + } + if (map != NULL) { + BMElem *ele_dst = ese->ele; + while (true) { + BMElem *ele_dst_next = BLI_ghash_lookup(map, ele_dst); + BLI_assert(ele_dst != ele_dst_next); + if (ele_dst_next == NULL) { + break; + } + ele_dst = ele_dst_next; + /* Break loop on circular reference (should never happen). */ + if (UNLIKELY(ele_dst == ese->ele)) { + BLI_assert(0); + break; + } + if (use_chain == false) { + break; + } + } + ese->ele = ele_dst; + } + } + + /* Remove overlapping duplicates. */ + for (BMEditSelection *ese = bm->selected.first, *ese_next; ese; ese = ese_next) { + ese_next = ese->next; + if (BM_ELEM_API_FLAG_TEST(ese->ele, _FLAG_OVERLAP)) { + BM_ELEM_API_FLAG_DISABLE(ese->ele, _FLAG_OVERLAP); + } + else { + BLI_freelinkN(&bm->selected, ese); + } + } } -void BM_mesh_elem_hflag_disable_test( - BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test) +void BM_mesh_elem_hflag_disable_test(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide, + const bool overwrite, + const char hflag_test) { - const char iter_types[3] = {BM_VERTS_OF_MESH, - BM_EDGES_OF_MESH, - BM_FACES_OF_MESH}; - - const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE}; - - const char hflag_nosel = hflag & ~BM_ELEM_SELECT; - - int i; - - BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); - - if (hflag & BM_ELEM_SELECT) { - BM_select_history_clear(bm); - } - - if ((htype == (BM_VERT | BM_EDGE | BM_FACE)) && - (hflag == BM_ELEM_SELECT) && - (respecthide == false) && - (hflag_test == 0)) - { - /* fast path for deselect all, avoid topology loops - * since we know all will be de-selected anyway. */ - for (i = 0; i < 3; i++) { - BMIter iter; - BMElem *ele; - - ele = BM_iter_new(&iter, bm, iter_types[i], NULL); - for ( ; ele; ele = BM_iter_step(&iter)) { - BM_elem_flag_disable(ele, BM_ELEM_SELECT); - } - } - - bm->totvertsel = bm->totedgesel = bm->totfacesel = 0; - } - else { - for (i = 0; i < 3; i++) { - BMIter iter; - BMElem *ele; - - if (htype & flag_types[i]) { - ele = BM_iter_new(&iter, bm, iter_types[i], NULL); - for ( ; ele; ele = BM_iter_step(&iter)) { - - if (UNLIKELY(respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN))) { - /* pass */ - } - else if (!hflag_test || BM_elem_flag_test(ele, hflag_test)) { - if (hflag & BM_ELEM_SELECT) { - BM_elem_select_set(bm, ele, false); - } - BM_elem_flag_disable(ele, hflag); - } - else if (overwrite) { - /* no match! */ - if (hflag & BM_ELEM_SELECT) { - BM_elem_select_set(bm, ele, true); - } - BM_elem_flag_enable(ele, hflag_nosel); - } - } - } - } - } + const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH}; + + const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE}; + + const char hflag_nosel = hflag & ~BM_ELEM_SELECT; + + int i; + + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + + if (hflag & BM_ELEM_SELECT) { + BM_select_history_clear(bm); + } + + if ((htype == (BM_VERT | BM_EDGE | BM_FACE)) && (hflag == BM_ELEM_SELECT) && + (respecthide == false) && (hflag_test == 0)) { + /* fast path for deselect all, avoid topology loops + * since we know all will be de-selected anyway. */ + for (i = 0; i < 3; i++) { + BMIter iter; + BMElem *ele; + + ele = BM_iter_new(&iter, bm, iter_types[i], NULL); + for (; ele; ele = BM_iter_step(&iter)) { + BM_elem_flag_disable(ele, BM_ELEM_SELECT); + } + } + + bm->totvertsel = bm->totedgesel = bm->totfacesel = 0; + } + else { + for (i = 0; i < 3; i++) { + BMIter iter; + BMElem *ele; + + if (htype & flag_types[i]) { + ele = BM_iter_new(&iter, bm, iter_types[i], NULL); + for (; ele; ele = BM_iter_step(&iter)) { + + if (UNLIKELY(respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN))) { + /* pass */ + } + else if (!hflag_test || BM_elem_flag_test(ele, hflag_test)) { + if (hflag & BM_ELEM_SELECT) { + BM_elem_select_set(bm, ele, false); + } + BM_elem_flag_disable(ele, hflag); + } + else if (overwrite) { + /* no match! */ + if (hflag & BM_ELEM_SELECT) { + BM_elem_select_set(bm, ele, true); + } + BM_elem_flag_enable(ele, hflag_nosel); + } + } + } + } + } } -void BM_mesh_elem_hflag_enable_test( - BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test) +void BM_mesh_elem_hflag_enable_test(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide, + const bool overwrite, + const char hflag_test) { - const char iter_types[3] = {BM_VERTS_OF_MESH, - BM_EDGES_OF_MESH, - BM_FACES_OF_MESH}; - - const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE}; - - /* use the nosel version when setting so under no - * condition may a hidden face become selected. - * Applying other flags to hidden faces is OK. */ - const char hflag_nosel = hflag & ~BM_ELEM_SELECT; - - BMIter iter; - BMElem *ele; - int i; - - BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); - - /* note, better not attempt a fast path for selection as done with de-select - * because hidden geometry and different selection modes can give different results, - * we could of course check for no hidden faces and then use quicker method but its not worth it. */ - - for (i = 0; i < 3; i++) { - if (htype & flag_types[i]) { - ele = BM_iter_new(&iter, bm, iter_types[i], NULL); - for ( ; ele; ele = BM_iter_step(&iter)) { - - if (UNLIKELY(respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN))) { - /* pass */ - } - else if (!hflag_test || BM_elem_flag_test(ele, hflag_test)) { - /* match! */ - if (hflag & BM_ELEM_SELECT) { - BM_elem_select_set(bm, ele, true); - } - BM_elem_flag_enable(ele, hflag_nosel); - } - else if (overwrite) { - /* no match! */ - if (hflag & BM_ELEM_SELECT) { - BM_elem_select_set(bm, ele, false); - } - BM_elem_flag_disable(ele, hflag); - } - } - } - } + const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH}; + + const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE}; + + /* use the nosel version when setting so under no + * condition may a hidden face become selected. + * Applying other flags to hidden faces is OK. */ + const char hflag_nosel = hflag & ~BM_ELEM_SELECT; + + BMIter iter; + BMElem *ele; + int i; + + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + + /* note, better not attempt a fast path for selection as done with de-select + * because hidden geometry and different selection modes can give different results, + * we could of course check for no hidden faces and then use quicker method but its not worth it. */ + + for (i = 0; i < 3; i++) { + if (htype & flag_types[i]) { + ele = BM_iter_new(&iter, bm, iter_types[i], NULL); + for (; ele; ele = BM_iter_step(&iter)) { + + if (UNLIKELY(respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN))) { + /* pass */ + } + else if (!hflag_test || BM_elem_flag_test(ele, hflag_test)) { + /* match! */ + if (hflag & BM_ELEM_SELECT) { + BM_elem_select_set(bm, ele, true); + } + BM_elem_flag_enable(ele, hflag_nosel); + } + else if (overwrite) { + /* no match! */ + if (hflag & BM_ELEM_SELECT) { + BM_elem_select_set(bm, ele, false); + } + BM_elem_flag_disable(ele, hflag); + } + } + } + } } -void BM_mesh_elem_hflag_disable_all( - BMesh *bm, const char htype, const char hflag, - const bool respecthide) +void BM_mesh_elem_hflag_disable_all(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide) { - /* call with 0 hflag_test */ - BM_mesh_elem_hflag_disable_test(bm, htype, hflag, respecthide, false, 0); + /* call with 0 hflag_test */ + BM_mesh_elem_hflag_disable_test(bm, htype, hflag, respecthide, false, 0); } -void BM_mesh_elem_hflag_enable_all( - BMesh *bm, const char htype, const char hflag, - const bool respecthide) +void BM_mesh_elem_hflag_enable_all(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide) { - /* call with 0 hflag_test */ - BM_mesh_elem_hflag_enable_test(bm, htype, hflag, respecthide, false, 0); + /* call with 0 hflag_test */ + BM_mesh_elem_hflag_enable_test(bm, htype, hflag, respecthide, false, 0); } /***************** Mesh Hiding stuff *********** */ @@ -1277,7 +1286,7 @@ void BM_mesh_elem_hflag_enable_all( */ static void vert_flush_hide_set(BMVert *v) { - BM_elem_flag_set(v, BM_ELEM_HIDDEN, !bm_vert_is_edge_visible_any(v)); + BM_elem_flag_set(v, BM_ELEM_HIDDEN, !bm_vert_is_edge_visible_any(v)); } /** @@ -1286,124 +1295,124 @@ static void vert_flush_hide_set(BMVert *v) */ static void edge_flush_hide_set(BMEdge *e) { - BM_elem_flag_set(e, BM_ELEM_HIDDEN, !bm_edge_is_face_visible_any(e)); + BM_elem_flag_set(e, BM_ELEM_HIDDEN, !bm_edge_is_face_visible_any(e)); } void BM_vert_hide_set(BMVert *v, const bool hide) { - /* vert hiding: vert + surrounding edges and faces */ - BLI_assert(v->head.htype == BM_VERT); - if (hide) { - BLI_assert(!BM_elem_flag_test(v, BM_ELEM_SELECT)); - } - - BM_elem_flag_set(v, BM_ELEM_HIDDEN, hide); - - if (v->e) { - BMEdge *e_iter, *e_first; - e_iter = e_first = v->e; - do { - BM_elem_flag_set(e_iter, BM_ELEM_HIDDEN, hide); - if (e_iter->l) { - const BMLoop *l_radial_iter, *l_radial_first; - l_radial_iter = l_radial_first = e_iter->l; - do { - BM_elem_flag_set(l_radial_iter->f, BM_ELEM_HIDDEN, hide); - } while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first); - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - } + /* vert hiding: vert + surrounding edges and faces */ + BLI_assert(v->head.htype == BM_VERT); + if (hide) { + BLI_assert(!BM_elem_flag_test(v, BM_ELEM_SELECT)); + } + + BM_elem_flag_set(v, BM_ELEM_HIDDEN, hide); + + if (v->e) { + BMEdge *e_iter, *e_first; + e_iter = e_first = v->e; + do { + BM_elem_flag_set(e_iter, BM_ELEM_HIDDEN, hide); + if (e_iter->l) { + const BMLoop *l_radial_iter, *l_radial_first; + l_radial_iter = l_radial_first = e_iter->l; + do { + BM_elem_flag_set(l_radial_iter->f, BM_ELEM_HIDDEN, hide); + } while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first); + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } } void BM_edge_hide_set(BMEdge *e, const bool hide) { - BLI_assert(e->head.htype == BM_EDGE); - if (hide) { - BLI_assert(!BM_elem_flag_test(e, BM_ELEM_SELECT)); - } - - /* edge hiding: faces around the edge */ - if (e->l) { - const BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - BM_elem_flag_set(l_iter->f, BM_ELEM_HIDDEN, hide); - } while ((l_iter = l_iter->radial_next) != l_first); - } - - BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide); - - /* hide vertices if necessary */ - if (hide) { - vert_flush_hide_set(e->v1); - vert_flush_hide_set(e->v2); - } - else { - BM_elem_flag_disable(e->v1, BM_ELEM_HIDDEN); - BM_elem_flag_disable(e->v2, BM_ELEM_HIDDEN); - } + BLI_assert(e->head.htype == BM_EDGE); + if (hide) { + BLI_assert(!BM_elem_flag_test(e, BM_ELEM_SELECT)); + } + + /* edge hiding: faces around the edge */ + if (e->l) { + const BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + BM_elem_flag_set(l_iter->f, BM_ELEM_HIDDEN, hide); + } while ((l_iter = l_iter->radial_next) != l_first); + } + + BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide); + + /* hide vertices if necessary */ + if (hide) { + vert_flush_hide_set(e->v1); + vert_flush_hide_set(e->v2); + } + else { + BM_elem_flag_disable(e->v1, BM_ELEM_HIDDEN); + BM_elem_flag_disable(e->v2, BM_ELEM_HIDDEN); + } } void BM_face_hide_set(BMFace *f, const bool hide) { - BLI_assert(f->head.htype == BM_FACE); - if (hide) { - BLI_assert(!BM_elem_flag_test(f, BM_ELEM_SELECT)); - } - - BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide); - - if (hide) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter; - - l_iter = l_first; - do { - edge_flush_hide_set(l_iter->e); - } while ((l_iter = l_iter->next) != l_first); - - l_iter = l_first; - do { - vert_flush_hide_set(l_iter->v); - } while ((l_iter = l_iter->next) != l_first); - } - else { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter; - - l_iter = l_first; - do { - BM_elem_flag_disable(l_iter->e, BM_ELEM_HIDDEN); - BM_elem_flag_disable(l_iter->v, BM_ELEM_HIDDEN); - } while ((l_iter = l_iter->next) != l_first); - } + BLI_assert(f->head.htype == BM_FACE); + if (hide) { + BLI_assert(!BM_elem_flag_test(f, BM_ELEM_SELECT)); + } + + BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide); + + if (hide) { + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter; + + l_iter = l_first; + do { + edge_flush_hide_set(l_iter->e); + } while ((l_iter = l_iter->next) != l_first); + + l_iter = l_first; + do { + vert_flush_hide_set(l_iter->v); + } while ((l_iter = l_iter->next) != l_first); + } + else { + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter; + + l_iter = l_first; + do { + BM_elem_flag_disable(l_iter->e, BM_ELEM_HIDDEN); + BM_elem_flag_disable(l_iter->v, BM_ELEM_HIDDEN); + } while ((l_iter = l_iter->next) != l_first); + } } void _bm_elem_hide_set(BMesh *bm, BMHeader *head, const bool hide) { - /* Follow convention of always deselecting before - * hiding an element */ - switch (head->htype) { - case BM_VERT: - if (hide) { - BM_vert_select_set(bm, (BMVert *)head, false); - } - BM_vert_hide_set((BMVert *)head, hide); - break; - case BM_EDGE: - if (hide) { - BM_edge_select_set(bm, (BMEdge *)head, false); - } - BM_edge_hide_set((BMEdge *)head, hide); - break; - case BM_FACE: - if (hide) { - BM_face_select_set(bm, (BMFace *)head, false); - } - BM_face_hide_set((BMFace *)head, hide); - break; - default: - BMESH_ASSERT(0); - break; - } + /* Follow convention of always deselecting before + * hiding an element */ + switch (head->htype) { + case BM_VERT: + if (hide) { + BM_vert_select_set(bm, (BMVert *)head, false); + } + BM_vert_hide_set((BMVert *)head, hide); + break; + case BM_EDGE: + if (hide) { + BM_edge_select_set(bm, (BMEdge *)head, false); + } + BM_edge_hide_set((BMEdge *)head, hide); + break; + case BM_FACE: + if (hide) { + BM_face_select_set(bm, (BMFace *)head, false); + } + BM_face_hide_set((BMFace *)head, hide); + break; + default: + BMESH_ASSERT(0); + break; + } } diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h index a7416b484d7..06314a7a388 100644 --- a/source/blender/bmesh/intern/bmesh_marking.h +++ b/source/blender/bmesh/intern/bmesh_marking.h @@ -22,9 +22,9 @@ */ typedef struct BMEditSelection { - struct BMEditSelection *next, *prev; - BMElem *ele; - char htype; + struct BMEditSelection *next, *prev; + BMElem *ele; + char htype; } BMEditSelection; /* geometry hiding code */ @@ -37,19 +37,27 @@ void BM_face_hide_set(BMFace *f, const bool hide); /* Selection code */ void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select); -void BM_mesh_elem_hflag_enable_test( - BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test); -void BM_mesh_elem_hflag_disable_test( - BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test); - -void BM_mesh_elem_hflag_enable_all( - BMesh *bm, const char htype, const char hflag, - const bool respecthide); -void BM_mesh_elem_hflag_disable_all( - BMesh *bm, const char htype, const char hflag, - const bool respecthide); +void BM_mesh_elem_hflag_enable_test(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide, + const bool overwrite, + const char hflag_test); +void BM_mesh_elem_hflag_disable_test(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide, + const bool overwrite, + const char hflag_test); + +void BM_mesh_elem_hflag_enable_all(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide); +void BM_mesh_elem_hflag_disable_all(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide); /* individual element select functions, BM_elem_select_set is a shortcut for these * that automatically detects which one to use*/ @@ -71,37 +79,46 @@ void BM_mesh_select_mode_flush(BMesh *bm); void BM_mesh_deselect_flush(BMesh *bm); void BM_mesh_select_flush(BMesh *bm); -int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, const bool respecthide); -int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, const bool respecthide); +int BM_mesh_elem_hflag_count_enabled(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide); +int BM_mesh_elem_hflag_count_disabled(BMesh *bm, + const char htype, + const char hflag, + const bool respecthide); /* edit selection stuff */ -void BM_mesh_active_face_set(BMesh *bm, BMFace *f); +void BM_mesh_active_face_set(BMesh *bm, BMFace *f); BMFace *BM_mesh_active_face_get(BMesh *bm, const bool is_sloppy, const bool is_selected); BMEdge *BM_mesh_active_edge_get(BMesh *bm); BMVert *BM_mesh_active_vert_get(BMesh *bm); BMElem *BM_mesh_active_elem_get(BMesh *bm); -void BM_editselection_center(BMEditSelection *ese, float r_center[3]); -void BM_editselection_normal(BMEditSelection *ese, float r_normal[3]); -void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]); +void BM_editselection_center(BMEditSelection *ese, float r_center[3]); +void BM_editselection_normal(BMEditSelection *ese, float r_normal[3]); +void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]); -#define BM_select_history_check(bm, ele) _bm_select_history_check(bm, &(ele)->head) -#define BM_select_history_remove(bm, ele) _bm_select_history_remove(bm, &(ele)->head) +#define BM_select_history_check(bm, ele) _bm_select_history_check(bm, &(ele)->head) +#define BM_select_history_remove(bm, ele) _bm_select_history_remove(bm, &(ele)->head) #define BM_select_history_store_notest(bm, ele) _bm_select_history_store_notest(bm, &(ele)->head) -#define BM_select_history_store(bm, ele) _bm_select_history_store(bm, &(ele)->head) -#define BM_select_history_store_head_notest(bm, ele) _bm_select_history_store_head_notest(bm, &(ele)->head) -#define BM_select_history_store_head(bm, ele) _bm_select_history_store_head(bm, &(ele)->head) -#define BM_select_history_store_after_notest(bm, ese_ref, ele) _bm_select_history_store_after_notest(bm, ese_ref, &(ele)->head) -#define BM_select_history_store_after(bm, ese, ese_ref) _bm_select_history_store_after(bm, ese_ref, &(ele)->head) - -bool _bm_select_history_check(BMesh *bm, const BMHeader *ele); -bool _bm_select_history_remove(BMesh *bm, BMHeader *ele); +#define BM_select_history_store(bm, ele) _bm_select_history_store(bm, &(ele)->head) +#define BM_select_history_store_head_notest(bm, ele) \ + _bm_select_history_store_head_notest(bm, &(ele)->head) +#define BM_select_history_store_head(bm, ele) _bm_select_history_store_head(bm, &(ele)->head) +#define BM_select_history_store_after_notest(bm, ese_ref, ele) \ + _bm_select_history_store_after_notest(bm, ese_ref, &(ele)->head) +#define BM_select_history_store_after(bm, ese, ese_ref) \ + _bm_select_history_store_after(bm, ese_ref, &(ele)->head) + +bool _bm_select_history_check(BMesh *bm, const BMHeader *ele); +bool _bm_select_history_remove(BMesh *bm, BMHeader *ele); void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele); -void _bm_select_history_store(BMesh *bm, BMHeader *ele); +void _bm_select_history_store(BMesh *bm, BMHeader *ele); void _bm_select_history_store_head_notest(BMesh *bm, BMHeader *ele); -void _bm_select_history_store_head(BMesh *bm, BMHeader *ele); -void _bm_select_history_store_after(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele); -void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele); +void _bm_select_history_store_head(BMesh *bm, BMHeader *ele); +void _bm_select_history_store_after(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele); +void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele); void BM_select_history_validate(BMesh *bm); void BM_select_history_clear(BMesh *bm); @@ -109,12 +126,16 @@ bool BM_select_history_active_get(BMesh *bm, struct BMEditSelection *ese); struct GHash *BM_select_history_map_create(BMesh *bm); void BM_select_history_merge_from_targetmap( - BMesh *bm, GHash *vert_map, GHash *edge_map, GHash *face_map, const bool use_chain); + BMesh *bm, GHash *vert_map, GHash *edge_map, GHash *face_map, const bool use_chain); -#define BM_SELECT_HISTORY_BACKUP(bm) { \ - ListBase _bm_prev_selected = (bm)->selected; BLI_listbase_clear(&(bm)->selected) +#define BM_SELECT_HISTORY_BACKUP(bm) \ + { \ + ListBase _bm_prev_selected = (bm)->selected; \ + BLI_listbase_clear(&(bm)->selected) #define BM_SELECT_HISTORY_RESTORE(bm) \ - (bm)->selected = _bm_prev_selected; } (void)0 + (bm)->selected = _bm_prev_selected; \ + } \ + (void)0 #endif /* __BMESH_MARKING_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 460b7ce8dae..8d445d428b2 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -45,106 +45,103 @@ const BMAllocTemplate bm_mesh_allocsize_default = {512, 1024, 2048, 512}; const BMAllocTemplate bm_mesh_chunksize_default = {512, 1024, 2048, 512}; -static void bm_mempool_init_ex( - const BMAllocTemplate *allocsize, const bool use_toolflags, - BLI_mempool **r_vpool, BLI_mempool **r_epool, BLI_mempool **r_lpool, BLI_mempool **r_fpool) +static void bm_mempool_init_ex(const BMAllocTemplate *allocsize, + const bool use_toolflags, + BLI_mempool **r_vpool, + BLI_mempool **r_epool, + BLI_mempool **r_lpool, + BLI_mempool **r_fpool) { - size_t vert_size, edge_size, loop_size, face_size; - - if (use_toolflags == true) { - vert_size = sizeof(BMVert_OFlag); - edge_size = sizeof(BMEdge_OFlag); - loop_size = sizeof(BMLoop); - face_size = sizeof(BMFace_OFlag); - } - else { - vert_size = sizeof(BMVert); - edge_size = sizeof(BMEdge); - loop_size = sizeof(BMLoop); - face_size = sizeof(BMFace); - } - - if (r_vpool) { - *r_vpool = BLI_mempool_create( - vert_size, allocsize->totvert, - bm_mesh_chunksize_default.totvert, BLI_MEMPOOL_ALLOW_ITER); - } - if (r_epool) { - *r_epool = BLI_mempool_create( - edge_size, allocsize->totedge, - bm_mesh_chunksize_default.totedge, BLI_MEMPOOL_ALLOW_ITER); - } - if (r_lpool) { - *r_lpool = BLI_mempool_create( - loop_size, allocsize->totloop, - bm_mesh_chunksize_default.totloop, BLI_MEMPOOL_NOP); - } - if (r_fpool) { - *r_fpool = BLI_mempool_create( - face_size, allocsize->totface, - bm_mesh_chunksize_default.totface, BLI_MEMPOOL_ALLOW_ITER); - } + size_t vert_size, edge_size, loop_size, face_size; + + if (use_toolflags == true) { + vert_size = sizeof(BMVert_OFlag); + edge_size = sizeof(BMEdge_OFlag); + loop_size = sizeof(BMLoop); + face_size = sizeof(BMFace_OFlag); + } + else { + vert_size = sizeof(BMVert); + edge_size = sizeof(BMEdge); + loop_size = sizeof(BMLoop); + face_size = sizeof(BMFace); + } + + if (r_vpool) { + *r_vpool = BLI_mempool_create( + vert_size, allocsize->totvert, bm_mesh_chunksize_default.totvert, BLI_MEMPOOL_ALLOW_ITER); + } + if (r_epool) { + *r_epool = BLI_mempool_create( + edge_size, allocsize->totedge, bm_mesh_chunksize_default.totedge, BLI_MEMPOOL_ALLOW_ITER); + } + if (r_lpool) { + *r_lpool = BLI_mempool_create( + loop_size, allocsize->totloop, bm_mesh_chunksize_default.totloop, BLI_MEMPOOL_NOP); + } + if (r_fpool) { + *r_fpool = BLI_mempool_create( + face_size, allocsize->totface, bm_mesh_chunksize_default.totface, BLI_MEMPOOL_ALLOW_ITER); + } } static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize, const bool use_toolflags) { - bm_mempool_init_ex( - allocsize, use_toolflags, - &bm->vpool, &bm->epool, &bm->lpool, &bm->fpool); + bm_mempool_init_ex(allocsize, use_toolflags, &bm->vpool, &bm->epool, &bm->lpool, &bm->fpool); #ifdef USE_BMESH_HOLES - bm->looplistpool = BLI_mempool_create(sizeof(BMLoopList), 512, 512, BLI_MEMPOOL_NOP); + bm->looplistpool = BLI_mempool_create(sizeof(BMLoopList), 512, 512, BLI_MEMPOOL_NOP); #endif } void BM_mesh_elem_toolflags_ensure(BMesh *bm) { - BLI_assert(bm->use_toolflags); - - if (bm->vtoolflagpool && bm->etoolflagpool && bm->ftoolflagpool) { - return; - } - - bm->vtoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totvert, 512, BLI_MEMPOOL_NOP); - bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totedge, 512, BLI_MEMPOOL_NOP); - bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totface, 512, BLI_MEMPOOL_NOP); - - BMIter iter; - BMVert_OFlag *v_olfag; - BLI_mempool *toolflagpool = bm->vtoolflagpool; - BM_ITER_MESH (v_olfag, &iter, bm, BM_VERTS_OF_MESH) { - v_olfag->oflags = BLI_mempool_calloc(toolflagpool); - } - - BMEdge_OFlag *e_olfag; - toolflagpool = bm->etoolflagpool; - BM_ITER_MESH (e_olfag, &iter, bm, BM_EDGES_OF_MESH) { - e_olfag->oflags = BLI_mempool_calloc(toolflagpool); - } - - BMFace_OFlag *f_olfag; - toolflagpool = bm->ftoolflagpool; - BM_ITER_MESH (f_olfag, &iter, bm, BM_FACES_OF_MESH) { - f_olfag->oflags = BLI_mempool_calloc(toolflagpool); - } - - bm->totflags = 1; + BLI_assert(bm->use_toolflags); + + if (bm->vtoolflagpool && bm->etoolflagpool && bm->ftoolflagpool) { + return; + } + + bm->vtoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totvert, 512, BLI_MEMPOOL_NOP); + bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totedge, 512, BLI_MEMPOOL_NOP); + bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totface, 512, BLI_MEMPOOL_NOP); + + BMIter iter; + BMVert_OFlag *v_olfag; + BLI_mempool *toolflagpool = bm->vtoolflagpool; + BM_ITER_MESH (v_olfag, &iter, bm, BM_VERTS_OF_MESH) { + v_olfag->oflags = BLI_mempool_calloc(toolflagpool); + } + + BMEdge_OFlag *e_olfag; + toolflagpool = bm->etoolflagpool; + BM_ITER_MESH (e_olfag, &iter, bm, BM_EDGES_OF_MESH) { + e_olfag->oflags = BLI_mempool_calloc(toolflagpool); + } + + BMFace_OFlag *f_olfag; + toolflagpool = bm->ftoolflagpool; + BM_ITER_MESH (f_olfag, &iter, bm, BM_FACES_OF_MESH) { + f_olfag->oflags = BLI_mempool_calloc(toolflagpool); + } + + bm->totflags = 1; } void BM_mesh_elem_toolflags_clear(BMesh *bm) { - if (bm->vtoolflagpool) { - BLI_mempool_destroy(bm->vtoolflagpool); - bm->vtoolflagpool = NULL; - } - if (bm->etoolflagpool) { - BLI_mempool_destroy(bm->etoolflagpool); - bm->etoolflagpool = NULL; - } - if (bm->ftoolflagpool) { - BLI_mempool_destroy(bm->ftoolflagpool); - bm->ftoolflagpool = NULL; - } + if (bm->vtoolflagpool) { + BLI_mempool_destroy(bm->vtoolflagpool); + bm->vtoolflagpool = NULL; + } + if (bm->etoolflagpool) { + BLI_mempool_destroy(bm->etoolflagpool); + bm->etoolflagpool = NULL; + } + if (bm->ftoolflagpool) { + BLI_mempool_destroy(bm->ftoolflagpool); + bm->ftoolflagpool = NULL; + } } /** @@ -156,27 +153,25 @@ void BM_mesh_elem_toolflags_clear(BMesh *bm) * * \note ob is needed by multires */ -BMesh *BM_mesh_create( - const BMAllocTemplate *allocsize, - const struct BMeshCreateParams *params) +BMesh *BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params) { - /* allocate the structure */ - BMesh *bm = MEM_callocN(sizeof(BMesh), __func__); + /* allocate the structure */ + BMesh *bm = MEM_callocN(sizeof(BMesh), __func__); - /* allocate the memory pools for the mesh elements */ - bm_mempool_init(bm, allocsize, params->use_toolflags); + /* allocate the memory pools for the mesh elements */ + bm_mempool_init(bm, allocsize, params->use_toolflags); - /* allocate one flag pool that we don't get rid of. */ - bm->use_toolflags = params->use_toolflags; - bm->toolflag_index = 0; - bm->totflags = 0; + /* allocate one flag pool that we don't get rid of. */ + bm->use_toolflags = params->use_toolflags; + bm->toolflag_index = 0; + bm->totflags = 0; - CustomData_reset(&bm->vdata); - CustomData_reset(&bm->edata); - CustomData_reset(&bm->ldata); - CustomData_reset(&bm->pdata); + CustomData_reset(&bm->vdata); + CustomData_reset(&bm->edata); + CustomData_reset(&bm->ldata); + CustomData_reset(&bm->pdata); - return bm; + return bm; } /** @@ -188,79 +183,93 @@ BMesh *BM_mesh_create( */ void BM_mesh_data_free(BMesh *bm) { - BMVert *v; - BMEdge *e; - BMLoop *l; - BMFace *f; - - BMIter iter; - BMIter itersub; - - const bool is_ldata_free = CustomData_bmesh_has_free(&bm->ldata); - const bool is_pdata_free = CustomData_bmesh_has_free(&bm->pdata); - - /* Check if we have to call free, if not we can avoid a lot of looping */ - if (CustomData_bmesh_has_free(&(bm->vdata))) { - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - CustomData_bmesh_free_block(&(bm->vdata), &(v->head.data)); - } - } - if (CustomData_bmesh_has_free(&(bm->edata))) { - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - CustomData_bmesh_free_block(&(bm->edata), &(e->head.data)); - } - } - - if (is_ldata_free || is_pdata_free) { - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (is_pdata_free) { - CustomData_bmesh_free_block(&(bm->pdata), &(f->head.data)); - } - if (is_ldata_free) { - BM_ITER_ELEM (l, &itersub, f, BM_LOOPS_OF_FACE) { - CustomData_bmesh_free_block(&(bm->ldata), &(l->head.data)); - } - } - } - } - - /* Free custom data pools, This should probably go in CustomData_free? */ - if (bm->vdata.totlayer) { BLI_mempool_destroy(bm->vdata.pool); } - if (bm->edata.totlayer) { BLI_mempool_destroy(bm->edata.pool); } - if (bm->ldata.totlayer) { BLI_mempool_destroy(bm->ldata.pool); } - if (bm->pdata.totlayer) { BLI_mempool_destroy(bm->pdata.pool); } - - /* free custom data */ - CustomData_free(&bm->vdata, 0); - CustomData_free(&bm->edata, 0); - CustomData_free(&bm->ldata, 0); - CustomData_free(&bm->pdata, 0); - - /* destroy element pools */ - BLI_mempool_destroy(bm->vpool); - BLI_mempool_destroy(bm->epool); - BLI_mempool_destroy(bm->lpool); - BLI_mempool_destroy(bm->fpool); - - if (bm->vtable) { MEM_freeN(bm->vtable); } - if (bm->etable) { MEM_freeN(bm->etable); } - if (bm->ftable) { MEM_freeN(bm->ftable); } - - /* destroy flag pool */ - BM_mesh_elem_toolflags_clear(bm); + BMVert *v; + BMEdge *e; + BMLoop *l; + BMFace *f; + + BMIter iter; + BMIter itersub; + + const bool is_ldata_free = CustomData_bmesh_has_free(&bm->ldata); + const bool is_pdata_free = CustomData_bmesh_has_free(&bm->pdata); + + /* Check if we have to call free, if not we can avoid a lot of looping */ + if (CustomData_bmesh_has_free(&(bm->vdata))) { + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + CustomData_bmesh_free_block(&(bm->vdata), &(v->head.data)); + } + } + if (CustomData_bmesh_has_free(&(bm->edata))) { + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + CustomData_bmesh_free_block(&(bm->edata), &(e->head.data)); + } + } + + if (is_ldata_free || is_pdata_free) { + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (is_pdata_free) { + CustomData_bmesh_free_block(&(bm->pdata), &(f->head.data)); + } + if (is_ldata_free) { + BM_ITER_ELEM (l, &itersub, f, BM_LOOPS_OF_FACE) { + CustomData_bmesh_free_block(&(bm->ldata), &(l->head.data)); + } + } + } + } + + /* Free custom data pools, This should probably go in CustomData_free? */ + if (bm->vdata.totlayer) { + BLI_mempool_destroy(bm->vdata.pool); + } + if (bm->edata.totlayer) { + BLI_mempool_destroy(bm->edata.pool); + } + if (bm->ldata.totlayer) { + BLI_mempool_destroy(bm->ldata.pool); + } + if (bm->pdata.totlayer) { + BLI_mempool_destroy(bm->pdata.pool); + } + + /* free custom data */ + CustomData_free(&bm->vdata, 0); + CustomData_free(&bm->edata, 0); + CustomData_free(&bm->ldata, 0); + CustomData_free(&bm->pdata, 0); + + /* destroy element pools */ + BLI_mempool_destroy(bm->vpool); + BLI_mempool_destroy(bm->epool); + BLI_mempool_destroy(bm->lpool); + BLI_mempool_destroy(bm->fpool); + + if (bm->vtable) { + MEM_freeN(bm->vtable); + } + if (bm->etable) { + MEM_freeN(bm->etable); + } + if (bm->ftable) { + MEM_freeN(bm->ftable); + } + + /* destroy flag pool */ + BM_mesh_elem_toolflags_clear(bm); #ifdef USE_BMESH_HOLES - BLI_mempool_destroy(bm->looplistpool); + BLI_mempool_destroy(bm->looplistpool); #endif - BLI_freelistN(&bm->selected); + BLI_freelistN(&bm->selected); - if (bm->lnor_spacearr) { - BKE_lnor_spacearr_free(bm->lnor_spacearr); - MEM_freeN(bm->lnor_spacearr); - } + if (bm->lnor_spacearr) { + BKE_lnor_spacearr_free(bm->lnor_spacearr); + MEM_freeN(bm->lnor_spacearr); + } - BMO_error_clear(bm); + BMO_error_clear(bm); } /** @@ -270,23 +279,23 @@ void BM_mesh_data_free(BMesh *bm) */ void BM_mesh_clear(BMesh *bm) { - const bool use_toolflags = bm->use_toolflags; + const bool use_toolflags = bm->use_toolflags; - /* free old mesh */ - BM_mesh_data_free(bm); - memset(bm, 0, sizeof(BMesh)); + /* free old mesh */ + BM_mesh_data_free(bm); + memset(bm, 0, sizeof(BMesh)); - /* allocate the memory pools for the mesh elements */ - bm_mempool_init(bm, &bm_mesh_allocsize_default, use_toolflags); + /* allocate the memory pools for the mesh elements */ + bm_mempool_init(bm, &bm_mesh_allocsize_default, use_toolflags); - bm->use_toolflags = use_toolflags; - bm->toolflag_index = 0; - bm->totflags = 0; + bm->use_toolflags = use_toolflags; + bm->toolflag_index = 0; + bm->totflags = 0; - CustomData_reset(&bm->vdata); - CustomData_reset(&bm->edata); - CustomData_reset(&bm->ldata); - CustomData_reset(&bm->pdata); + CustomData_reset(&bm->vdata); + CustomData_reset(&bm->edata); + CustomData_reset(&bm->ldata); + CustomData_reset(&bm->pdata); } /** @@ -296,19 +305,18 @@ void BM_mesh_clear(BMesh *bm) */ void BM_mesh_free(BMesh *bm) { - BM_mesh_data_free(bm); + BM_mesh_data_free(bm); - if (bm->py_handle) { - /* keep this out of 'BM_mesh_data_free' because we want python - * to be able to clear the mesh and maintain access. */ - bpy_bm_generic_invalidate(bm->py_handle); - bm->py_handle = NULL; - } + if (bm->py_handle) { + /* keep this out of 'BM_mesh_data_free' because we want python + * to be able to clear the mesh and maintain access. */ + bpy_bm_generic_invalidate(bm->py_handle); + bm->py_handle = NULL; + } - MEM_freeN(bm); + MEM_freeN(bm); } - /** * Helpers for #BM_mesh_normals_update and #BM_verts_calc_normal_vcos */ @@ -317,166 +325,170 @@ void BM_mesh_free(BMesh *bm) #define BM_LNORSPACE_UPDATE _FLAG_MF typedef struct BMEdgesCalcVectorsData { - /* Read-only data. */ - const float (*vcos)[3]; + /* Read-only data. */ + const float (*vcos)[3]; - /* Read-write data, but no need to protect it, no concurrency to fear here. */ - float (*edgevec)[3]; + /* Read-write data, but no need to protect it, no concurrency to fear here. */ + float (*edgevec)[3]; } BMEdgesCalcVectorsData; - static void mesh_edges_calc_vectors_cb(void *userdata, MempoolIterData *mp_e) { - BMEdgesCalcVectorsData *data = userdata; - BMEdge *e = (BMEdge *)mp_e; - - if (e->l) { - const float *v1_co = data->vcos ? data->vcos[BM_elem_index_get(e->v1)] : e->v1->co; - const float *v2_co = data->vcos ? data->vcos[BM_elem_index_get(e->v2)] : e->v2->co; - sub_v3_v3v3(data->edgevec[BM_elem_index_get(e)], v2_co, v1_co); - normalize_v3(data->edgevec[BM_elem_index_get(e)]); - } - else { - /* the edge vector will not be needed when the edge has no radial */ - } + BMEdgesCalcVectorsData *data = userdata; + BMEdge *e = (BMEdge *)mp_e; + + if (e->l) { + const float *v1_co = data->vcos ? data->vcos[BM_elem_index_get(e->v1)] : e->v1->co; + const float *v2_co = data->vcos ? data->vcos[BM_elem_index_get(e->v2)] : e->v2->co; + sub_v3_v3v3(data->edgevec[BM_elem_index_get(e)], v2_co, v1_co); + normalize_v3(data->edgevec[BM_elem_index_get(e)]); + } + else { + /* the edge vector will not be needed when the edge has no radial */ + } } static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const float (*vcos)[3]) { - BM_mesh_elem_index_ensure(bm, BM_EDGE | (vcos ? BM_VERT : 0)); + BM_mesh_elem_index_ensure(bm, BM_EDGE | (vcos ? BM_VERT : 0)); - BMEdgesCalcVectorsData data = { - .vcos = vcos, - .edgevec = edgevec, - }; + BMEdgesCalcVectorsData data = { + .vcos = vcos, + .edgevec = edgevec, + }; - BM_iter_parallel(bm, BM_EDGES_OF_MESH, mesh_edges_calc_vectors_cb, &data, bm->totedge >= BM_OMP_LIMIT); + BM_iter_parallel( + bm, BM_EDGES_OF_MESH, mesh_edges_calc_vectors_cb, &data, bm->totedge >= BM_OMP_LIMIT); } - typedef struct BMVertsCalcNormalsData { - /* Read-only data. */ - const float (*fnos)[3]; - const float (*edgevec)[3]; - const float (*vcos)[3]; + /* Read-only data. */ + const float (*fnos)[3]; + const float (*edgevec)[3]; + const float (*vcos)[3]; - /* Read-write data, protected by an atomic-based fake spinlock-like system... */ - float (*vnos)[3]; + /* Read-write data, protected by an atomic-based fake spinlock-like system... */ + float (*vnos)[3]; } BMVertsCalcNormalsData; static void mesh_verts_calc_normals_accum_cb(void *userdata, MempoolIterData *mp_f) { #define FLT_EQ_NONAN(_fa, _fb) (*((const uint32_t *)&_fa) == *((const uint32_t *)&_fb)) - BMVertsCalcNormalsData *data = userdata; - BMFace *f = (BMFace *)mp_f; - - const float *f_no = data->fnos ? data->fnos[BM_elem_index_get(f)] : f->no; - - BMLoop *l_first, *l_iter; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const float *e1diff, *e2diff; - float dotprod; - float fac; - - /* calculate the dot product of the two edges that - * meet at the loop's vertex */ - e1diff = data->edgevec[BM_elem_index_get(l_iter->prev->e)]; - e2diff = data->edgevec[BM_elem_index_get(l_iter->e)]; - dotprod = dot_v3v3(e1diff, e2diff); - - /* edge vectors are calculated from e->v1 to e->v2, so - * adjust the dot product if one but not both loops - * actually runs from from e->v2 to e->v1 */ - if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) { - dotprod = -dotprod; - } - - fac = saacos(-dotprod); - - if (fac != fac) { /* NAN detection. */ - /* Degenerated case, nothing to do here, just ignore that vertex. */ - continue; - } - - /* accumulate weighted face normal into the vertex's normal */ - float *v_no = data->vnos ? data->vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no; - - /* This block is a lockless threadsafe madd_v3_v3fl. - * It uses the first float of the vector as a sort of cheap spinlock, - * assuming FLT_MAX is a safe 'illegal' value that cannot be set here otherwise. - * It also assumes that collisions between threads are highly unlikely, - * else performances would be quite bad here. */ - float virtual_lock = v_no[0]; - while (true) { - /* This loops until following conditions are met: - * - v_no[0] has same value as virtual_lock (i.e. it did not change since last try). - * - v_no[0] was not FLT_MAX, i.e. it was not locked by another thread. - */ - const float vl = atomic_cas_float(&v_no[0], virtual_lock, FLT_MAX); - if (FLT_EQ_NONAN(vl, virtual_lock) && vl != FLT_MAX) { - break; - } - virtual_lock = vl; - } - BLI_assert(v_no[0] == FLT_MAX); - /* Now we own that normal value, and can change it. - * But first scalar of the vector must not be changed yet, it's our lock! */ - virtual_lock += f_no[0] * fac; - v_no[1] += f_no[1] * fac; - v_no[2] += f_no[2] * fac; - /* Second atomic operation to 'release' our lock on that vector and set its first scalar value. */ - /* Note that we do not need to loop here, since we 'locked' v_no[0], - * nobody should have changed it in the mean time. */ - virtual_lock = atomic_cas_float(&v_no[0], FLT_MAX, virtual_lock); - BLI_assert(virtual_lock == FLT_MAX); - - } while ((l_iter = l_iter->next) != l_first); + BMVertsCalcNormalsData *data = userdata; + BMFace *f = (BMFace *)mp_f; + + const float *f_no = data->fnos ? data->fnos[BM_elem_index_get(f)] : f->no; + + BMLoop *l_first, *l_iter; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + const float *e1diff, *e2diff; + float dotprod; + float fac; + + /* calculate the dot product of the two edges that + * meet at the loop's vertex */ + e1diff = data->edgevec[BM_elem_index_get(l_iter->prev->e)]; + e2diff = data->edgevec[BM_elem_index_get(l_iter->e)]; + dotprod = dot_v3v3(e1diff, e2diff); + + /* edge vectors are calculated from e->v1 to e->v2, so + * adjust the dot product if one but not both loops + * actually runs from from e->v2 to e->v1 */ + if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) { + dotprod = -dotprod; + } + + fac = saacos(-dotprod); + + if (fac != fac) { /* NAN detection. */ + /* Degenerated case, nothing to do here, just ignore that vertex. */ + continue; + } + + /* accumulate weighted face normal into the vertex's normal */ + float *v_no = data->vnos ? data->vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no; + + /* This block is a lockless threadsafe madd_v3_v3fl. + * It uses the first float of the vector as a sort of cheap spinlock, + * assuming FLT_MAX is a safe 'illegal' value that cannot be set here otherwise. + * It also assumes that collisions between threads are highly unlikely, + * else performances would be quite bad here. */ + float virtual_lock = v_no[0]; + while (true) { + /* This loops until following conditions are met: + * - v_no[0] has same value as virtual_lock (i.e. it did not change since last try). + * - v_no[0] was not FLT_MAX, i.e. it was not locked by another thread. + */ + const float vl = atomic_cas_float(&v_no[0], virtual_lock, FLT_MAX); + if (FLT_EQ_NONAN(vl, virtual_lock) && vl != FLT_MAX) { + break; + } + virtual_lock = vl; + } + BLI_assert(v_no[0] == FLT_MAX); + /* Now we own that normal value, and can change it. + * But first scalar of the vector must not be changed yet, it's our lock! */ + virtual_lock += f_no[0] * fac; + v_no[1] += f_no[1] * fac; + v_no[2] += f_no[2] * fac; + /* Second atomic operation to 'release' our lock on that vector and set its first scalar value. */ + /* Note that we do not need to loop here, since we 'locked' v_no[0], + * nobody should have changed it in the mean time. */ + virtual_lock = atomic_cas_float(&v_no[0], FLT_MAX, virtual_lock); + BLI_assert(virtual_lock == FLT_MAX); + + } while ((l_iter = l_iter->next) != l_first); #undef FLT_EQ_NONAN } static void mesh_verts_calc_normals_normalize_cb(void *userdata, MempoolIterData *mp_v) { - BMVertsCalcNormalsData *data = userdata; - BMVert *v = (BMVert *)mp_v; - - float *v_no = data->vnos ? data->vnos[BM_elem_index_get(v)] : v->no; - if (UNLIKELY(normalize_v3(v_no) == 0.0f)) { - const float *v_co = data->vcos ? data->vcos[BM_elem_index_get(v)] : v->co; - normalize_v3_v3(v_no, v_co); - } + BMVertsCalcNormalsData *data = userdata; + BMVert *v = (BMVert *)mp_v; + + float *v_no = data->vnos ? data->vnos[BM_elem_index_get(v)] : v->no; + if (UNLIKELY(normalize_v3(v_no) == 0.0f)) { + const float *v_co = data->vcos ? data->vcos[BM_elem_index_get(v)] : v->co; + normalize_v3_v3(v_no, v_co); + } } -static void bm_mesh_verts_calc_normals( - BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3], - const float (*vcos)[3], float (*vnos)[3]) +static void bm_mesh_verts_calc_normals(BMesh *bm, + const float (*edgevec)[3], + const float (*fnos)[3], + const float (*vcos)[3], + float (*vnos)[3]) { - BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE) | ((vnos || vcos) ? BM_VERT : 0)); - - BMVertsCalcNormalsData data = { - .fnos = fnos, - .edgevec = edgevec, - .vcos = vcos, - .vnos = vnos, - }; - - BM_iter_parallel(bm, BM_FACES_OF_MESH, mesh_verts_calc_normals_accum_cb, &data, bm->totface >= BM_OMP_LIMIT); - - /* normalize the accumulated vertex normals */ - BM_iter_parallel(bm, BM_VERTS_OF_MESH, mesh_verts_calc_normals_normalize_cb, &data, bm->totvert >= BM_OMP_LIMIT); + BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE) | ((vnos || vcos) ? BM_VERT : 0)); + + BMVertsCalcNormalsData data = { + .fnos = fnos, + .edgevec = edgevec, + .vcos = vcos, + .vnos = vnos, + }; + + BM_iter_parallel( + bm, BM_FACES_OF_MESH, mesh_verts_calc_normals_accum_cb, &data, bm->totface >= BM_OMP_LIMIT); + + /* normalize the accumulated vertex normals */ + BM_iter_parallel(bm, + BM_VERTS_OF_MESH, + mesh_verts_calc_normals_normalize_cb, + &data, + bm->totvert >= BM_OMP_LIMIT); } - static void mesh_faces_calc_normals_cb(void *UNUSED(userdata), MempoolIterData *mp_f) { - BMFace *f = (BMFace *)mp_f; + BMFace *f = (BMFace *)mp_f; - BM_face_normal_update(f); + BM_face_normal_update(f); } - /** * \brief BMesh Compute Normals * @@ -484,33 +496,34 @@ static void mesh_faces_calc_normals_cb(void *UNUSED(userdata), MempoolIterData * */ void BM_mesh_normals_update(BMesh *bm) { - float (*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__); - - /* Parallel mempool iteration does not allow to generate indices inline anymore... */ - BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE)); - - /* calculate all face normals */ - BM_iter_parallel(bm, BM_FACES_OF_MESH, mesh_faces_calc_normals_cb, NULL, bm->totface >= BM_OMP_LIMIT); - - /* Zero out vertex normals */ - BMIter viter; - BMVert *v; - int i; - - BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { - BM_elem_index_set(v, i); /* set_inline */ - zero_v3(v->no); - } - bm->elem_index_dirty &= ~BM_VERT; - - /* Compute normalized direction vectors for each edge. - * Directions will be used for calculating the weights of the face normals on the vertex normals. - */ - bm_mesh_edges_calc_vectors(bm, edgevec, NULL); - - /* Add weighted face normals to vertices, and normalize vert normals. */ - bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, NULL, NULL, NULL); - MEM_freeN(edgevec); + float(*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__); + + /* Parallel mempool iteration does not allow to generate indices inline anymore... */ + BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE)); + + /* calculate all face normals */ + BM_iter_parallel( + bm, BM_FACES_OF_MESH, mesh_faces_calc_normals_cb, NULL, bm->totface >= BM_OMP_LIMIT); + + /* Zero out vertex normals */ + BMIter viter; + BMVert *v; + int i; + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + BM_elem_index_set(v, i); /* set_inline */ + zero_v3(v->no); + } + bm->elem_index_dirty &= ~BM_VERT; + + /* Compute normalized direction vectors for each edge. + * Directions will be used for calculating the weights of the face normals on the vertex normals. + */ + bm_mesh_edges_calc_vectors(bm, edgevec, NULL); + + /* Add weighted face normals to vertices, and normalize vert normals. */ + bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, NULL, NULL, NULL); + MEM_freeN(edgevec); } /** @@ -518,95 +531,97 @@ void BM_mesh_normals_update(BMesh *bm) * * Computes the vertex normals of a mesh into vnos, using given vertex coordinates (vcos) and polygon normals (fnos). */ -void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (*vcos)[3], float (*vnos)[3]) +void BM_verts_calc_normal_vcos(BMesh *bm, + const float (*fnos)[3], + const float (*vcos)[3], + float (*vnos)[3]) { - float (*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__); + float(*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__); - /* Compute normalized direction vectors for each edge. - * Directions will be used for calculating the weights of the face normals on the vertex normals. - */ - bm_mesh_edges_calc_vectors(bm, edgevec, vcos); + /* Compute normalized direction vectors for each edge. + * Directions will be used for calculating the weights of the face normals on the vertex normals. + */ + bm_mesh_edges_calc_vectors(bm, edgevec, vcos); - /* Add weighted face normals to vertices, and normalize vert normals. */ - bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, fnos, vcos, vnos); - MEM_freeN(edgevec); + /* Add weighted face normals to vertices, and normalize vert normals. */ + bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, fnos, vcos, vnos); + MEM_freeN(edgevec); } /** * Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normal_vcos */ -static void bm_mesh_edges_sharp_tag( - BMesh *bm, - const float (*vnos)[3], const float (*fnos)[3], float (*r_lnos)[3], - const float split_angle, const bool do_sharp_edges_tag) +static void bm_mesh_edges_sharp_tag(BMesh *bm, + const float (*vnos)[3], + const float (*fnos)[3], + float (*r_lnos)[3], + const float split_angle, + const bool do_sharp_edges_tag) { - BMIter eiter; - BMEdge *e; - int i; - - const bool check_angle = (split_angle < (float)M_PI); - const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f; - - { - char htype = BM_VERT | BM_LOOP; - if (fnos) { - htype |= BM_FACE; - } - BM_mesh_elem_index_ensure(bm, htype); - } - - /* This first loop checks which edges are actually smooth, and pre-populate lnos with vnos (as if they were - * all smooth). - */ - BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) { - BMLoop *l_a, *l_b; - - BM_elem_index_set(e, i); /* set_inline */ - BM_elem_flag_disable(e, BM_ELEM_TAG); /* Clear tag (means edge is sharp). */ - - /* An edge with only two loops, might be smooth... */ - if (BM_edge_loop_pair(e, &l_a, &l_b)) { - bool is_angle_smooth = true; - if (check_angle) { - const float *no_a = fnos ? fnos[BM_elem_index_get(l_a->f)] : l_a->f->no; - const float *no_b = fnos ? fnos[BM_elem_index_get(l_b->f)] : l_b->f->no; - is_angle_smooth = (dot_v3v3(no_a, no_b) >= split_angle_cos); - } - - /* We only tag edges that are *really* smooth: - * If the angle between both its polys' normals is below split_angle value, - * and it is tagged as such, - * and both its faces are smooth, - * and both its faces have compatible (non-flipped) normals, - * i.e. both loops on the same edge do not share the same vertex. - */ - if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && - BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) && - BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH) && - l_a->v != l_b->v) - { - if (is_angle_smooth) { - const float *no; - BM_elem_flag_enable(e, BM_ELEM_TAG); - - /* linked vertices might be fully smooth, copy their normals to loop ones. */ - if (r_lnos) { - no = vnos ? vnos[BM_elem_index_get(l_a->v)] : l_a->v->no; - copy_v3_v3(r_lnos[BM_elem_index_get(l_a)], no); - no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no; - copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no); - } - } - else if (do_sharp_edges_tag) { - /* Note that we do not care about the other sharp-edge cases (sharp poly, non-manifold edge, etc.), - * only tag edge as sharp when it is due to angle threashold. */ - BM_elem_flag_disable(e, BM_ELEM_SMOOTH); - } - } - } - } - - bm->elem_index_dirty &= ~BM_EDGE; + BMIter eiter; + BMEdge *e; + int i; + + const bool check_angle = (split_angle < (float)M_PI); + const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f; + + { + char htype = BM_VERT | BM_LOOP; + if (fnos) { + htype |= BM_FACE; + } + BM_mesh_elem_index_ensure(bm, htype); + } + + /* This first loop checks which edges are actually smooth, and pre-populate lnos with vnos (as if they were + * all smooth). + */ + BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) { + BMLoop *l_a, *l_b; + + BM_elem_index_set(e, i); /* set_inline */ + BM_elem_flag_disable(e, BM_ELEM_TAG); /* Clear tag (means edge is sharp). */ + + /* An edge with only two loops, might be smooth... */ + if (BM_edge_loop_pair(e, &l_a, &l_b)) { + bool is_angle_smooth = true; + if (check_angle) { + const float *no_a = fnos ? fnos[BM_elem_index_get(l_a->f)] : l_a->f->no; + const float *no_b = fnos ? fnos[BM_elem_index_get(l_b->f)] : l_b->f->no; + is_angle_smooth = (dot_v3v3(no_a, no_b) >= split_angle_cos); + } + + /* We only tag edges that are *really* smooth: + * If the angle between both its polys' normals is below split_angle value, + * and it is tagged as such, + * and both its faces are smooth, + * and both its faces have compatible (non-flipped) normals, + * i.e. both loops on the same edge do not share the same vertex. + */ + if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) && + BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH) && l_a->v != l_b->v) { + if (is_angle_smooth) { + const float *no; + BM_elem_flag_enable(e, BM_ELEM_TAG); + + /* linked vertices might be fully smooth, copy their normals to loop ones. */ + if (r_lnos) { + no = vnos ? vnos[BM_elem_index_get(l_a->v)] : l_a->v->no; + copy_v3_v3(r_lnos[BM_elem_index_get(l_a)], no); + no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no; + copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no); + } + } + else if (do_sharp_edges_tag) { + /* Note that we do not care about the other sharp-edge cases (sharp poly, non-manifold edge, etc.), + * only tag edge as sharp when it is due to angle threashold. */ + BM_elem_flag_disable(e, BM_ELEM_SMOOTH); + } + } + } + } + + bm->elem_index_dirty &= ~BM_EDGE; } /** @@ -615,389 +630,396 @@ static void bm_mesh_edges_sharp_tag( */ bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr) { - BMLoop *lfan_pivot_next = l_curr; - BMEdge *e_next = l_curr->e; - - BLI_assert(!BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)); - BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG); - - while (true) { - /* Much simpler than in sibling code with basic Mesh data! */ - lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot_next, &e_next); - - if (!lfan_pivot_next || !BM_elem_flag_test(e_next, BM_ELEM_TAG)) { - /* Sharp loop/edge, so not a cyclic smooth fan... */ - return false; - } - /* Smooth loop/edge... */ - else if (BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)) { - if (lfan_pivot_next == l_curr) { - /* We walked around a whole cyclic smooth fan without finding any already-processed loop, means we can - * use initial l_curr/l_prev edge as start for this smooth fan. */ - return true; - } - /* ... already checked in some previous looping, we can abort. */ - return false; - } - else { - /* ... we can skip it in future, and keep checking the smooth fan. */ - BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG); - } - } + BMLoop *lfan_pivot_next = l_curr; + BMEdge *e_next = l_curr->e; + + BLI_assert(!BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)); + BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG); + + while (true) { + /* Much simpler than in sibling code with basic Mesh data! */ + lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot_next, &e_next); + + if (!lfan_pivot_next || !BM_elem_flag_test(e_next, BM_ELEM_TAG)) { + /* Sharp loop/edge, so not a cyclic smooth fan... */ + return false; + } + /* Smooth loop/edge... */ + else if (BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)) { + if (lfan_pivot_next == l_curr) { + /* We walked around a whole cyclic smooth fan without finding any already-processed loop, means we can + * use initial l_curr/l_prev edge as start for this smooth fan. */ + return true; + } + /* ... already checked in some previous looping, we can abort. */ + return false; + } + else { + /* ... we can skip it in future, and keep checking the smooth fan. */ + BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG); + } + } } /* BMesh version of BKE_mesh_normals_loop_split() in mesh_evaluate.c * Will use first clnors_data array, and fallback to cd_loop_clnors_offset (use NULL and -1 to not use clnors). */ -static void bm_mesh_loops_calc_normals( - BMesh *bm, const float (*vcos)[3], const float (*fnos)[3], float (*r_lnos)[3], - MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], - const int cd_loop_clnors_offset, const bool do_rebuild) +static void bm_mesh_loops_calc_normals(BMesh *bm, + const float (*vcos)[3], + const float (*fnos)[3], + float (*r_lnos)[3], + MLoopNorSpaceArray *r_lnors_spacearr, + short (*clnors_data)[2], + const int cd_loop_clnors_offset, + const bool do_rebuild) { - BMIter fiter; - BMFace *f_curr; - const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); - - MLoopNorSpaceArray _lnors_spacearr = {NULL}; - - /* Temp normal stack. */ - BLI_SMALLSTACK_DECLARE(normal, float *); - /* Temp clnors stack. */ - BLI_SMALLSTACK_DECLARE(clnors, short *); - /* Temp edge vectors stack, only used when computing lnor spacearr. */ - BLI_Stack *edge_vectors = NULL; - - { - char htype = 0; - if (vcos) { - htype |= BM_VERT; - } - /* Face/Loop indices are set inline below. */ - BM_mesh_elem_index_ensure(bm, htype); - } - - if (!r_lnors_spacearr && has_clnors) { - /* We need to compute lnor spacearr if some custom lnor data are given to us! */ - r_lnors_spacearr = &_lnors_spacearr; - } - if (r_lnors_spacearr) { - BKE_lnor_spacearr_init(r_lnors_spacearr, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR); - edge_vectors = BLI_stack_new(sizeof(float[3]), __func__); - } - - /* Clear all loops' tags (means none are to be skipped for now). */ - int index_face, index_loop = 0; - BM_ITER_MESH_INDEX (f_curr, &fiter, bm, BM_FACES_OF_MESH, index_face) { - BMLoop *l_curr, *l_first; - - BM_elem_index_set(f_curr, index_face); /* set_inline */ - - l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr); - do { - BM_elem_index_set(l_curr, index_loop++); /* set_inline */ - BM_elem_flag_disable(l_curr, BM_ELEM_TAG); - } while ((l_curr = l_curr->next) != l_first); - } - bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); - - /* We now know edges that can be smoothed (they are tagged), and edges that will be hard (they aren't). - * Now, time to generate the normals. - */ - BM_ITER_MESH (f_curr, &fiter, bm, BM_FACES_OF_MESH) { - BMLoop *l_curr, *l_first; - - l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr); - do { - if (do_rebuild && !BM_ELEM_API_FLAG_TEST(l_curr, BM_LNORSPACE_UPDATE) && - !(bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL)) - { - continue; - } - /* A smooth edge, we have to check for cyclic smooth fan case. - * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as - * 'entry point', otherwise we can skip it. */ - /* Note: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store mlfan_pivot's in a stack, - * to avoid having to fan again around the vert during actual computation of clnor & clnorspace. - * However, this would complicate the code, add more memory usage, and BM_vert_step_fan_loop() - * is quite cheap in term of CPU cycles, so really think it's not worth it. */ - if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && - (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !BM_loop_check_cyclic_smooth_fan(l_curr))) - { - } - else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && - !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) - { - /* Simple case (both edges around that vertex are sharp in related polygon), - * this vertex just takes its poly normal. - */ - const int l_curr_index = BM_elem_index_get(l_curr); - const float *no = fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no; - copy_v3_v3(r_lnos[l_curr_index], no); - - /* If needed, generate this (simple!) lnor space. */ - if (r_lnors_spacearr) { - float vec_curr[3], vec_prev[3]; - MLoopNorSpace *lnor_space = BKE_lnor_space_create(r_lnors_spacearr); - - { - const BMVert *v_pivot = l_curr->v; - const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co; - const BMVert *v_1 = BM_edge_other_vert(l_curr->e, v_pivot); - const float *co_1 = vcos ? vcos[BM_elem_index_get(v_1)] : v_1->co; - const BMVert *v_2 = BM_edge_other_vert(l_curr->prev->e, v_pivot); - const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co; - - sub_v3_v3v3(vec_curr, co_1, co_pivot); - normalize_v3(vec_curr); - sub_v3_v3v3(vec_prev, co_2, co_pivot); - normalize_v3(vec_prev); - } - - BKE_lnor_space_define(lnor_space, r_lnos[l_curr_index], vec_curr, vec_prev, NULL); - /* We know there is only one loop in this space, no need to create a linklist in this case... */ - BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, l_curr_index, l_curr, true); - - if (has_clnors) { - short (*clnor)[2] = clnors_data ? &clnors_data[l_curr_index] : - BM_ELEM_CD_GET_VOID_P(l_curr, cd_loop_clnors_offset); - BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor, r_lnos[l_curr_index]); - } - } - } - /* We *do not need* to check/tag loops as already computed! - * Due to the fact a loop only links to one of its two edges, a same fan *will never be walked more than - * once!* - * Since we consider edges having neighbor faces with inverted (flipped) normals as sharp, we are sure that - * no fan will be skipped, even only considering the case (sharp curr_edge, smooth prev_edge), and not the - * alternative (smooth curr_edge, sharp prev_edge). - * All this due/thanks to link between normals and loop ordering. - */ - else { - /* We have to fan around current vertex, until we find the other non-smooth edge, - * and accumulate face normals into the vertex! - * Note in case this vertex has only one sharp edge, this is a waste because the normal is the same as - * the vertex normal, but I do not see any easy way to detect that (would need to count number - * of sharp edges per vertex, I doubt the additional memory usage would be worth it, especially as - * it should not be a common case in real-life meshes anyway). - */ - BMVert *v_pivot = l_curr->v; - BMEdge *e_next; - const BMEdge *e_org = l_curr->e; - BMLoop *lfan_pivot, *lfan_pivot_next; - int lfan_pivot_index; - float lnor[3] = {0.0f, 0.0f, 0.0f}; - float vec_curr[3], vec_next[3], vec_org[3]; - - /* We validate clnors data on the fly - cheapest way to do! */ - int clnors_avg[2] = {0, 0}; - short (*clnor_ref)[2] = NULL; - int clnors_nbr = 0; - bool clnors_invalid = false; - - const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co; - - MLoopNorSpace *lnor_space = r_lnors_spacearr ? BKE_lnor_space_create(r_lnors_spacearr) : NULL; - - BLI_assert((edge_vectors == NULL) || BLI_stack_is_empty(edge_vectors)); - - lfan_pivot = l_curr; - lfan_pivot_index = BM_elem_index_get(lfan_pivot); - e_next = lfan_pivot->e; /* Current edge here, actually! */ - - /* Only need to compute previous edge's vector once, then we can just reuse old current one! */ - { - const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot); - const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co; - - sub_v3_v3v3(vec_org, co_2, co_pivot); - normalize_v3(vec_org); - copy_v3_v3(vec_curr, vec_org); - - if (r_lnors_spacearr) { - BLI_stack_push(edge_vectors, vec_org); - } - } - - while (true) { - /* Much simpler than in sibling code with basic Mesh data! */ - lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next); - if (lfan_pivot_next) { - BLI_assert(lfan_pivot_next->v == v_pivot); - } - else { - /* next edge is non-manifold, we have to find it ourselves! */ - e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e; - } - - /* Compute edge vector. - * NOTE: We could pre-compute those into an array, in the first iteration, instead of computing them - * twice (or more) here. However, time gained is not worth memory and time lost, - * given the fact that this code should not be called that much in real-life meshes... - */ - { - const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot); - const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co; - - sub_v3_v3v3(vec_next, co_2, co_pivot); - normalize_v3(vec_next); - } - - { - /* Code similar to accumulate_vertex_normals_poly_v3. */ - /* Calculate angle between the two poly edges incident on this vertex. */ - const BMFace *f = lfan_pivot->f; - const float fac = saacos(dot_v3v3(vec_next, vec_curr)); - const float *no = fnos ? fnos[BM_elem_index_get(f)] : f->no; - /* Accumulate */ - madd_v3_v3fl(lnor, no, fac); - - if (has_clnors) { - /* Accumulate all clnors, if they are not all equal we have to fix that! */ - short (*clnor)[2] = clnors_data ? &clnors_data[lfan_pivot_index] : - BM_ELEM_CD_GET_VOID_P(lfan_pivot, cd_loop_clnors_offset); - if (clnors_nbr) { - clnors_invalid |= ((*clnor_ref)[0] != (*clnor)[0] || (*clnor_ref)[1] != (*clnor)[1]); - } - else { - clnor_ref = clnor; - } - clnors_avg[0] += (*clnor)[0]; - clnors_avg[1] += (*clnor)[1]; - clnors_nbr++; - /* We store here a pointer to all custom lnors processed. */ - BLI_SMALLSTACK_PUSH(clnors, (short *)*clnor); - } - } - - /* We store here a pointer to all loop-normals processed. */ - BLI_SMALLSTACK_PUSH(normal, (float *)r_lnos[lfan_pivot_index]); - - if (r_lnors_spacearr) { - /* Assign current lnor space to current 'vertex' loop. */ - BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, lfan_pivot_index, lfan_pivot, false); - if (e_next != e_org) { - /* We store here all edges-normalized vectors processed. */ - BLI_stack_push(edge_vectors, vec_next); - } - } - - if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) { - /* Next edge is sharp, we have finished with this fan of faces around this vert! */ - break; - } - - /* Copy next edge vector to current one. */ - copy_v3_v3(vec_curr, vec_next); - /* Next pivot loop to current one. */ - lfan_pivot = lfan_pivot_next; - lfan_pivot_index = BM_elem_index_get(lfan_pivot); - } - - { - float lnor_len = normalize_v3(lnor); - - /* If we are generating lnor spacearr, we can now define the one for this fan. */ - if (r_lnors_spacearr) { - if (UNLIKELY(lnor_len == 0.0f)) { - /* Use vertex normal as fallback! */ - copy_v3_v3(lnor, r_lnos[lfan_pivot_index]); - lnor_len = 1.0f; - } - - BKE_lnor_space_define(lnor_space, lnor, vec_org, vec_next, edge_vectors); - - if (has_clnors) { - if (clnors_invalid) { - short *clnor; - - clnors_avg[0] /= clnors_nbr; - clnors_avg[1] /= clnors_nbr; - /* Fix/update all clnors of this fan with computed average value. */ - - /* Prints continuously when merge custom normals, so commenting. */ - /* printf("Invalid clnors in this fan!\n"); */ - - while ((clnor = BLI_SMALLSTACK_POP(clnors))) { - //print_v2("org clnor", clnor); - clnor[0] = (short)clnors_avg[0]; - clnor[1] = (short)clnors_avg[1]; - } - //print_v2("new clnors", clnors_avg); - } - else { - /* We still have to consume the stack! */ - while (BLI_SMALLSTACK_POP(clnors)) { - /* pass */ - } - } - BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor); - } - } - - /* In case we get a zero normal here, just use vertex normal already set! */ - if (LIKELY(lnor_len != 0.0f)) { - /* Copy back the final computed normal into all related loop-normals. */ - float *nor; - - while ((nor = BLI_SMALLSTACK_POP(normal))) { - copy_v3_v3(nor, lnor); - } - } - else { - /* We still have to consume the stack! */ - while (BLI_SMALLSTACK_POP(normal)) { - /* pass */ - } - } - } - - /* Tag related vertex as sharp, to avoid fanning around it again (in case it was a smooth one). */ - if (r_lnors_spacearr) { - BM_elem_flag_enable(l_curr->v, BM_ELEM_TAG); - } - } - } while ((l_curr = l_curr->next) != l_first); - } - - if (r_lnors_spacearr) { - BLI_stack_free(edge_vectors); - if (r_lnors_spacearr == &_lnors_spacearr) { - BKE_lnor_spacearr_free(r_lnors_spacearr); - } - } + BMIter fiter; + BMFace *f_curr; + const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); + + MLoopNorSpaceArray _lnors_spacearr = {NULL}; + + /* Temp normal stack. */ + BLI_SMALLSTACK_DECLARE(normal, float *); + /* Temp clnors stack. */ + BLI_SMALLSTACK_DECLARE(clnors, short *); + /* Temp edge vectors stack, only used when computing lnor spacearr. */ + BLI_Stack *edge_vectors = NULL; + + { + char htype = 0; + if (vcos) { + htype |= BM_VERT; + } + /* Face/Loop indices are set inline below. */ + BM_mesh_elem_index_ensure(bm, htype); + } + + if (!r_lnors_spacearr && has_clnors) { + /* We need to compute lnor spacearr if some custom lnor data are given to us! */ + r_lnors_spacearr = &_lnors_spacearr; + } + if (r_lnors_spacearr) { + BKE_lnor_spacearr_init(r_lnors_spacearr, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR); + edge_vectors = BLI_stack_new(sizeof(float[3]), __func__); + } + + /* Clear all loops' tags (means none are to be skipped for now). */ + int index_face, index_loop = 0; + BM_ITER_MESH_INDEX (f_curr, &fiter, bm, BM_FACES_OF_MESH, index_face) { + BMLoop *l_curr, *l_first; + + BM_elem_index_set(f_curr, index_face); /* set_inline */ + + l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr); + do { + BM_elem_index_set(l_curr, index_loop++); /* set_inline */ + BM_elem_flag_disable(l_curr, BM_ELEM_TAG); + } while ((l_curr = l_curr->next) != l_first); + } + bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); + + /* We now know edges that can be smoothed (they are tagged), and edges that will be hard (they aren't). + * Now, time to generate the normals. + */ + BM_ITER_MESH (f_curr, &fiter, bm, BM_FACES_OF_MESH) { + BMLoop *l_curr, *l_first; + + l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr); + do { + if (do_rebuild && !BM_ELEM_API_FLAG_TEST(l_curr, BM_LNORSPACE_UPDATE) && + !(bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL)) { + continue; + } + /* A smooth edge, we have to check for cyclic smooth fan case. + * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as + * 'entry point', otherwise we can skip it. */ + /* Note: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store mlfan_pivot's in a stack, + * to avoid having to fan again around the vert during actual computation of clnor & clnorspace. + * However, this would complicate the code, add more memory usage, and BM_vert_step_fan_loop() + * is quite cheap in term of CPU cycles, so really think it's not worth it. */ + if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && + (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !BM_loop_check_cyclic_smooth_fan(l_curr))) { + } + else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && + !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) { + /* Simple case (both edges around that vertex are sharp in related polygon), + * this vertex just takes its poly normal. + */ + const int l_curr_index = BM_elem_index_get(l_curr); + const float *no = fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no; + copy_v3_v3(r_lnos[l_curr_index], no); + + /* If needed, generate this (simple!) lnor space. */ + if (r_lnors_spacearr) { + float vec_curr[3], vec_prev[3]; + MLoopNorSpace *lnor_space = BKE_lnor_space_create(r_lnors_spacearr); + + { + const BMVert *v_pivot = l_curr->v; + const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co; + const BMVert *v_1 = BM_edge_other_vert(l_curr->e, v_pivot); + const float *co_1 = vcos ? vcos[BM_elem_index_get(v_1)] : v_1->co; + const BMVert *v_2 = BM_edge_other_vert(l_curr->prev->e, v_pivot); + const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co; + + sub_v3_v3v3(vec_curr, co_1, co_pivot); + normalize_v3(vec_curr); + sub_v3_v3v3(vec_prev, co_2, co_pivot); + normalize_v3(vec_prev); + } + + BKE_lnor_space_define(lnor_space, r_lnos[l_curr_index], vec_curr, vec_prev, NULL); + /* We know there is only one loop in this space, no need to create a linklist in this case... */ + BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, l_curr_index, l_curr, true); + + if (has_clnors) { + short(*clnor)[2] = clnors_data ? &clnors_data[l_curr_index] : + BM_ELEM_CD_GET_VOID_P(l_curr, cd_loop_clnors_offset); + BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor, r_lnos[l_curr_index]); + } + } + } + /* We *do not need* to check/tag loops as already computed! + * Due to the fact a loop only links to one of its two edges, a same fan *will never be walked more than + * once!* + * Since we consider edges having neighbor faces with inverted (flipped) normals as sharp, we are sure that + * no fan will be skipped, even only considering the case (sharp curr_edge, smooth prev_edge), and not the + * alternative (smooth curr_edge, sharp prev_edge). + * All this due/thanks to link between normals and loop ordering. + */ + else { + /* We have to fan around current vertex, until we find the other non-smooth edge, + * and accumulate face normals into the vertex! + * Note in case this vertex has only one sharp edge, this is a waste because the normal is the same as + * the vertex normal, but I do not see any easy way to detect that (would need to count number + * of sharp edges per vertex, I doubt the additional memory usage would be worth it, especially as + * it should not be a common case in real-life meshes anyway). + */ + BMVert *v_pivot = l_curr->v; + BMEdge *e_next; + const BMEdge *e_org = l_curr->e; + BMLoop *lfan_pivot, *lfan_pivot_next; + int lfan_pivot_index; + float lnor[3] = {0.0f, 0.0f, 0.0f}; + float vec_curr[3], vec_next[3], vec_org[3]; + + /* We validate clnors data on the fly - cheapest way to do! */ + int clnors_avg[2] = {0, 0}; + short(*clnor_ref)[2] = NULL; + int clnors_nbr = 0; + bool clnors_invalid = false; + + const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co; + + MLoopNorSpace *lnor_space = r_lnors_spacearr ? BKE_lnor_space_create(r_lnors_spacearr) : + NULL; + + BLI_assert((edge_vectors == NULL) || BLI_stack_is_empty(edge_vectors)); + + lfan_pivot = l_curr; + lfan_pivot_index = BM_elem_index_get(lfan_pivot); + e_next = lfan_pivot->e; /* Current edge here, actually! */ + + /* Only need to compute previous edge's vector once, then we can just reuse old current one! */ + { + const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot); + const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co; + + sub_v3_v3v3(vec_org, co_2, co_pivot); + normalize_v3(vec_org); + copy_v3_v3(vec_curr, vec_org); + + if (r_lnors_spacearr) { + BLI_stack_push(edge_vectors, vec_org); + } + } + + while (true) { + /* Much simpler than in sibling code with basic Mesh data! */ + lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next); + if (lfan_pivot_next) { + BLI_assert(lfan_pivot_next->v == v_pivot); + } + else { + /* next edge is non-manifold, we have to find it ourselves! */ + e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e; + } + + /* Compute edge vector. + * NOTE: We could pre-compute those into an array, in the first iteration, instead of computing them + * twice (or more) here. However, time gained is not worth memory and time lost, + * given the fact that this code should not be called that much in real-life meshes... + */ + { + const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot); + const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co; + + sub_v3_v3v3(vec_next, co_2, co_pivot); + normalize_v3(vec_next); + } + + { + /* Code similar to accumulate_vertex_normals_poly_v3. */ + /* Calculate angle between the two poly edges incident on this vertex. */ + const BMFace *f = lfan_pivot->f; + const float fac = saacos(dot_v3v3(vec_next, vec_curr)); + const float *no = fnos ? fnos[BM_elem_index_get(f)] : f->no; + /* Accumulate */ + madd_v3_v3fl(lnor, no, fac); + + if (has_clnors) { + /* Accumulate all clnors, if they are not all equal we have to fix that! */ + short(*clnor)[2] = clnors_data ? + &clnors_data[lfan_pivot_index] : + BM_ELEM_CD_GET_VOID_P(lfan_pivot, cd_loop_clnors_offset); + if (clnors_nbr) { + clnors_invalid |= ((*clnor_ref)[0] != (*clnor)[0] || + (*clnor_ref)[1] != (*clnor)[1]); + } + else { + clnor_ref = clnor; + } + clnors_avg[0] += (*clnor)[0]; + clnors_avg[1] += (*clnor)[1]; + clnors_nbr++; + /* We store here a pointer to all custom lnors processed. */ + BLI_SMALLSTACK_PUSH(clnors, (short *)*clnor); + } + } + + /* We store here a pointer to all loop-normals processed. */ + BLI_SMALLSTACK_PUSH(normal, (float *)r_lnos[lfan_pivot_index]); + + if (r_lnors_spacearr) { + /* Assign current lnor space to current 'vertex' loop. */ + BKE_lnor_space_add_loop( + r_lnors_spacearr, lnor_space, lfan_pivot_index, lfan_pivot, false); + if (e_next != e_org) { + /* We store here all edges-normalized vectors processed. */ + BLI_stack_push(edge_vectors, vec_next); + } + } + + if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) { + /* Next edge is sharp, we have finished with this fan of faces around this vert! */ + break; + } + + /* Copy next edge vector to current one. */ + copy_v3_v3(vec_curr, vec_next); + /* Next pivot loop to current one. */ + lfan_pivot = lfan_pivot_next; + lfan_pivot_index = BM_elem_index_get(lfan_pivot); + } + + { + float lnor_len = normalize_v3(lnor); + + /* If we are generating lnor spacearr, we can now define the one for this fan. */ + if (r_lnors_spacearr) { + if (UNLIKELY(lnor_len == 0.0f)) { + /* Use vertex normal as fallback! */ + copy_v3_v3(lnor, r_lnos[lfan_pivot_index]); + lnor_len = 1.0f; + } + + BKE_lnor_space_define(lnor_space, lnor, vec_org, vec_next, edge_vectors); + + if (has_clnors) { + if (clnors_invalid) { + short *clnor; + + clnors_avg[0] /= clnors_nbr; + clnors_avg[1] /= clnors_nbr; + /* Fix/update all clnors of this fan with computed average value. */ + + /* Prints continuously when merge custom normals, so commenting. */ + /* printf("Invalid clnors in this fan!\n"); */ + + while ((clnor = BLI_SMALLSTACK_POP(clnors))) { + //print_v2("org clnor", clnor); + clnor[0] = (short)clnors_avg[0]; + clnor[1] = (short)clnors_avg[1]; + } + //print_v2("new clnors", clnors_avg); + } + else { + /* We still have to consume the stack! */ + while (BLI_SMALLSTACK_POP(clnors)) { + /* pass */ + } + } + BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor); + } + } + + /* In case we get a zero normal here, just use vertex normal already set! */ + if (LIKELY(lnor_len != 0.0f)) { + /* Copy back the final computed normal into all related loop-normals. */ + float *nor; + + while ((nor = BLI_SMALLSTACK_POP(normal))) { + copy_v3_v3(nor, lnor); + } + } + else { + /* We still have to consume the stack! */ + while (BLI_SMALLSTACK_POP(normal)) { + /* pass */ + } + } + } + + /* Tag related vertex as sharp, to avoid fanning around it again (in case it was a smooth one). */ + if (r_lnors_spacearr) { + BM_elem_flag_enable(l_curr->v, BM_ELEM_TAG); + } + } + } while ((l_curr = l_curr->next) != l_first); + } + + if (r_lnors_spacearr) { + BLI_stack_free(edge_vectors); + if (r_lnors_spacearr == &_lnors_spacearr) { + BKE_lnor_spacearr_free(r_lnors_spacearr); + } + } } -static void bm_mesh_loops_calc_normals_no_autosmooth( - BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float (*r_lnos)[3]) +static void bm_mesh_loops_calc_normals_no_autosmooth(BMesh *bm, + const float (*vnos)[3], + const float (*fnos)[3], + float (*r_lnos)[3]) { - BMIter fiter; - BMFace *f_curr; - - { - char htype = BM_LOOP; - if (vnos) { - htype |= BM_VERT; - } - if (fnos) { - htype |= BM_FACE; - } - BM_mesh_elem_index_ensure(bm, htype); - } - - BM_ITER_MESH (f_curr, &fiter, bm, BM_FACES_OF_MESH) { - BMLoop *l_curr, *l_first; - const bool is_face_flat = !BM_elem_flag_test(f_curr, BM_ELEM_SMOOTH); - - l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr); - do { - const float *no = is_face_flat ? (fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no) : - (vnos ? vnos[BM_elem_index_get(l_curr->v)] : l_curr->v->no); - copy_v3_v3(r_lnos[BM_elem_index_get(l_curr)], no); - - } while ((l_curr = l_curr->next) != l_first); - } + BMIter fiter; + BMFace *f_curr; + + { + char htype = BM_LOOP; + if (vnos) { + htype |= BM_VERT; + } + if (fnos) { + htype |= BM_FACE; + } + BM_mesh_elem_index_ensure(bm, htype); + } + + BM_ITER_MESH (f_curr, &fiter, bm, BM_FACES_OF_MESH) { + BMLoop *l_curr, *l_first; + const bool is_face_flat = !BM_elem_flag_test(f_curr, BM_ELEM_SMOOTH); + + l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr); + do { + const float *no = is_face_flat ? (fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no) : + (vnos ? vnos[BM_elem_index_get(l_curr->v)] : l_curr->v->no); + copy_v3_v3(r_lnos[BM_elem_index_get(l_curr)], no); + + } while ((l_curr = l_curr->next) != l_first); + } } -#if 0 /* Unused currently */ +#if 0 /* Unused currently */ /** * \brief BMesh Compute Loop Normals * @@ -1008,20 +1030,20 @@ void BM_mesh_loop_normals_update( BMesh *bm, const bool use_split_normals, const float split_angle, float (*r_lnos)[3], MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset) { - const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); - - if (use_split_normals) { - /* Tag smooth edges and set lnos from vnos when they might be completely smooth... - * When using custom loop normals, disable the angle feature! */ - bm_mesh_edges_sharp_tag(bm, NULL, NULL, has_clnors ? (float)M_PI : split_angle, r_lnos); - - /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */ - bm_mesh_loops_calc_normals(bm, NULL, NULL, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset); - } - else { - BLI_assert(!r_lnors_spacearr); - bm_mesh_loops_calc_normals_no_autosmooth(bm, NULL, NULL, r_lnos); - } + const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); + + if (use_split_normals) { + /* Tag smooth edges and set lnos from vnos when they might be completely smooth... + * When using custom loop normals, disable the angle feature! */ + bm_mesh_edges_sharp_tag(bm, NULL, NULL, has_clnors ? (float)M_PI : split_angle, r_lnos); + + /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */ + bm_mesh_loops_calc_normals(bm, NULL, NULL, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset); + } + else { + BLI_assert(!r_lnors_spacearr); + bm_mesh_loops_calc_normals_no_autosmooth(bm, NULL, NULL, r_lnos); + } } #endif @@ -1031,27 +1053,33 @@ void BM_mesh_loop_normals_update( * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals'). * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges). */ -void BM_loops_calc_normal_vcos( - BMesh *bm, const float (*vcos)[3], const float (*vnos)[3], const float (*fnos)[3], - const bool use_split_normals, const float split_angle, float (*r_lnos)[3], - MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], - const int cd_loop_clnors_offset, const bool do_rebuild) +void BM_loops_calc_normal_vcos(BMesh *bm, + const float (*vcos)[3], + const float (*vnos)[3], + const float (*fnos)[3], + const bool use_split_normals, + const float split_angle, + float (*r_lnos)[3], + MLoopNorSpaceArray *r_lnors_spacearr, + short (*clnors_data)[2], + const int cd_loop_clnors_offset, + const bool do_rebuild) { - const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); - - if (use_split_normals) { - /* Tag smooth edges and set lnos from vnos when they might be completely smooth... - * When using custom loop normals, disable the angle feature! */ - bm_mesh_edges_sharp_tag(bm, vnos, fnos, r_lnos, has_clnors ? (float)M_PI : split_angle, false); - - /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */ - bm_mesh_loops_calc_normals( - bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, do_rebuild); - } - else { - BLI_assert(!r_lnors_spacearr); - bm_mesh_loops_calc_normals_no_autosmooth(bm, vnos, fnos, r_lnos); - } + const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1); + + if (use_split_normals) { + /* Tag smooth edges and set lnos from vnos when they might be completely smooth... + * When using custom loop normals, disable the angle feature! */ + bm_mesh_edges_sharp_tag(bm, vnos, fnos, r_lnos, has_clnors ? (float)M_PI : split_angle, false); + + /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */ + bm_mesh_loops_calc_normals( + bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, do_rebuild); + } + else { + BLI_assert(!r_lnors_spacearr); + bm_mesh_loops_calc_normals_no_autosmooth(bm, vnos, fnos, r_lnos); + } } /** Define sharp edges as needed to mimic 'autosmooth' from angle threshold. @@ -1060,215 +1088,232 @@ void BM_loops_calc_normal_vcos( */ void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle) { - if (split_angle >= (float)M_PI) { - /* Nothing to do! */ - return; - } + if (split_angle >= (float)M_PI) { + /* Nothing to do! */ + return; + } - bm_mesh_edges_sharp_tag(bm, NULL, NULL, NULL, split_angle, true); + bm_mesh_edges_sharp_tag(bm, NULL, NULL, NULL, split_angle, true); } -void BM_lnorspacearr_store(BMesh *bm, float(*r_lnors)[3]) +void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3]) { - BLI_assert(bm->lnor_spacearr != NULL); - - if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) { - BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL); - } - - int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); - - BM_loops_calc_normal_vcos( - bm, NULL, NULL, NULL, true, M_PI, r_lnors, bm->lnor_spacearr, NULL, cd_loop_clnors_offset, false); - bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL); + BLI_assert(bm->lnor_spacearr != NULL); + + if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) { + BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL); + } + + int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); + + BM_loops_calc_normal_vcos(bm, + NULL, + NULL, + NULL, + true, + M_PI, + r_lnors, + bm->lnor_spacearr, + NULL, + cd_loop_clnors_offset, + false); + bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL); } #define CLEAR_SPACEARRAY_THRESHOLD(x) ((x) / 2) void BM_lnorspace_invalidate(BMesh *bm, const bool do_invalidate_all) { - if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) { - return; - } - if (do_invalidate_all || bm->totvertsel > CLEAR_SPACEARRAY_THRESHOLD(bm->totvert)) { - bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; - return; - } - if (bm->lnor_spacearr == NULL) { - bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; - return; - } - - BMVert *v; - BMLoop *l; - BMIter viter, liter; - /* Note: we could use temp tag of BMItem for that, but probably better not use it in such a low-level func? - * --mont29 */ - BLI_bitmap *done_verts = BLI_BITMAP_NEW(bm->totvert, __func__); - - BM_mesh_elem_index_ensure(bm, BM_VERT); - - /* When we affect a given vertex, we may affect following smooth fans: - * - all smooth fans of said vertex; - * - all smooth fans of all immediate loop-neighbors vertices; - * This can be simplified as 'all loops of selected vertices and their immediate neighbors' - * need to be tagged for update. - */ - BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) { - BM_ELEM_API_FLAG_ENABLE(l, BM_LNORSPACE_UPDATE); - - /* Note that we only handle unselected neighbor vertices here, main loop will take care of - * selected ones. */ - if ((!BM_elem_flag_test(l->prev->v, BM_ELEM_SELECT)) && - !BLI_BITMAP_TEST(done_verts, BM_elem_index_get(l->prev->v))) - { - - BMLoop *l_prev; - BMIter liter_prev; - BM_ITER_ELEM(l_prev, &liter_prev, l->prev->v, BM_LOOPS_OF_VERT) { - BM_ELEM_API_FLAG_ENABLE(l_prev, BM_LNORSPACE_UPDATE); - } - BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(l_prev->v)); - } - - if ((!BM_elem_flag_test(l->next->v, BM_ELEM_SELECT)) && - !BLI_BITMAP_TEST(done_verts, BM_elem_index_get(l->next->v))) - { - - BMLoop *l_next; - BMIter liter_next; - BM_ITER_ELEM(l_next, &liter_next, l->next->v, BM_LOOPS_OF_VERT) { - BM_ELEM_API_FLAG_ENABLE(l_next, BM_LNORSPACE_UPDATE); - } - BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(l_next->v)); - } - } - - BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(v)); - } - } - - MEM_freeN(done_verts); - bm->spacearr_dirty |= BM_SPACEARR_DIRTY; + if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) { + return; + } + if (do_invalidate_all || bm->totvertsel > CLEAR_SPACEARRAY_THRESHOLD(bm->totvert)) { + bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; + return; + } + if (bm->lnor_spacearr == NULL) { + bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; + return; + } + + BMVert *v; + BMLoop *l; + BMIter viter, liter; + /* Note: we could use temp tag of BMItem for that, but probably better not use it in such a low-level func? + * --mont29 */ + BLI_bitmap *done_verts = BLI_BITMAP_NEW(bm->totvert, __func__); + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + /* When we affect a given vertex, we may affect following smooth fans: + * - all smooth fans of said vertex; + * - all smooth fans of all immediate loop-neighbors vertices; + * This can be simplified as 'all loops of selected vertices and their immediate neighbors' + * need to be tagged for update. + */ + BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + BM_ELEM_API_FLAG_ENABLE(l, BM_LNORSPACE_UPDATE); + + /* Note that we only handle unselected neighbor vertices here, main loop will take care of + * selected ones. */ + if ((!BM_elem_flag_test(l->prev->v, BM_ELEM_SELECT)) && + !BLI_BITMAP_TEST(done_verts, BM_elem_index_get(l->prev->v))) { + + BMLoop *l_prev; + BMIter liter_prev; + BM_ITER_ELEM (l_prev, &liter_prev, l->prev->v, BM_LOOPS_OF_VERT) { + BM_ELEM_API_FLAG_ENABLE(l_prev, BM_LNORSPACE_UPDATE); + } + BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(l_prev->v)); + } + + if ((!BM_elem_flag_test(l->next->v, BM_ELEM_SELECT)) && + !BLI_BITMAP_TEST(done_verts, BM_elem_index_get(l->next->v))) { + + BMLoop *l_next; + BMIter liter_next; + BM_ITER_ELEM (l_next, &liter_next, l->next->v, BM_LOOPS_OF_VERT) { + BM_ELEM_API_FLAG_ENABLE(l_next, BM_LNORSPACE_UPDATE); + } + BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(l_next->v)); + } + } + + BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(v)); + } + } + + MEM_freeN(done_verts); + bm->spacearr_dirty |= BM_SPACEARR_DIRTY; } void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor) { - BLI_assert(bm->lnor_spacearr != NULL); - - if (!(bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL))) { - return; - } - BMFace *f; - BMLoop *l; - BMIter fiter, liter; - - float(*r_lnors)[3] = MEM_callocN(sizeof(*r_lnors) * bm->totloop, __func__); - float(*oldnors)[3] = preserve_clnor ? MEM_mallocN(sizeof(*oldnors) * bm->totloop, __func__) : NULL; - - int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); - - BM_mesh_elem_index_ensure(bm, BM_LOOP); - - if (preserve_clnor) { - BLI_assert(bm->lnor_spacearr->lspacearr != NULL); - - BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) { - if (BM_ELEM_API_FLAG_TEST(l, BM_LNORSPACE_UPDATE) || bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) { - short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset); - int l_index = BM_elem_index_get(l); - - BKE_lnor_space_custom_data_to_normal( - bm->lnor_spacearr->lspacearr[l_index], *clnor, - oldnors[l_index]); - } - } - } - } - - if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) { - BKE_lnor_spacearr_clear(bm->lnor_spacearr); - } - BM_loops_calc_normal_vcos( - bm, NULL, NULL, NULL, true, M_PI, r_lnors, bm->lnor_spacearr, NULL, cd_loop_clnors_offset, true); - MEM_freeN(r_lnors); - - BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) { - if (BM_ELEM_API_FLAG_TEST(l, BM_LNORSPACE_UPDATE) || bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) { - if (preserve_clnor) { - short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset); - int l_index = BM_elem_index_get(l); - BKE_lnor_space_custom_normal_to_data( - bm->lnor_spacearr->lspacearr[l_index], oldnors[l_index], - *clnor); - } - BM_ELEM_API_FLAG_DISABLE(l, BM_LNORSPACE_UPDATE); - } - } - } - - MEM_SAFE_FREE(oldnors); - bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL); + BLI_assert(bm->lnor_spacearr != NULL); + + if (!(bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL))) { + return; + } + BMFace *f; + BMLoop *l; + BMIter fiter, liter; + + float(*r_lnors)[3] = MEM_callocN(sizeof(*r_lnors) * bm->totloop, __func__); + float(*oldnors)[3] = preserve_clnor ? MEM_mallocN(sizeof(*oldnors) * bm->totloop, __func__) : + NULL; + + int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); + + BM_mesh_elem_index_ensure(bm, BM_LOOP); + + if (preserve_clnor) { + BLI_assert(bm->lnor_spacearr->lspacearr != NULL); + + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + if (BM_ELEM_API_FLAG_TEST(l, BM_LNORSPACE_UPDATE) || + bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) { + short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset); + int l_index = BM_elem_index_get(l); + + BKE_lnor_space_custom_data_to_normal( + bm->lnor_spacearr->lspacearr[l_index], *clnor, oldnors[l_index]); + } + } + } + } + + if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) { + BKE_lnor_spacearr_clear(bm->lnor_spacearr); + } + BM_loops_calc_normal_vcos(bm, + NULL, + NULL, + NULL, + true, + M_PI, + r_lnors, + bm->lnor_spacearr, + NULL, + cd_loop_clnors_offset, + true); + MEM_freeN(r_lnors); + + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + if (BM_ELEM_API_FLAG_TEST(l, BM_LNORSPACE_UPDATE) || + bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) { + if (preserve_clnor) { + short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset); + int l_index = BM_elem_index_get(l); + BKE_lnor_space_custom_normal_to_data( + bm->lnor_spacearr->lspacearr[l_index], oldnors[l_index], *clnor); + } + BM_ELEM_API_FLAG_DISABLE(l, BM_LNORSPACE_UPDATE); + } + } + } + + MEM_SAFE_FREE(oldnors); + bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL); #ifndef NDEBUG - BM_lnorspace_err(bm); + BM_lnorspace_err(bm); #endif } void BM_lnorspace_update(BMesh *bm) { - if (bm->lnor_spacearr == NULL) { - bm->lnor_spacearr = MEM_callocN(sizeof(*bm->lnor_spacearr), __func__); - } - if (bm->lnor_spacearr->lspacearr == NULL) { - float(*lnors)[3] = MEM_callocN(sizeof(*lnors) * bm->totloop, __func__); - - BM_lnorspacearr_store(bm, lnors); - - MEM_freeN(lnors); - } - else if (bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL)) { - BM_lnorspace_rebuild(bm, false); - } + if (bm->lnor_spacearr == NULL) { + bm->lnor_spacearr = MEM_callocN(sizeof(*bm->lnor_spacearr), __func__); + } + if (bm->lnor_spacearr->lspacearr == NULL) { + float(*lnors)[3] = MEM_callocN(sizeof(*lnors) * bm->totloop, __func__); + + BM_lnorspacearr_store(bm, lnors); + + MEM_freeN(lnors); + } + else if (bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL)) { + BM_lnorspace_rebuild(bm, false); + } } void BM_normals_loops_edges_tag(BMesh *bm, const bool do_edges) { - BMFace *f; - BMEdge *e; - BMIter fiter, eiter; - BMLoop *l_curr, *l_first; - - if (do_edges) { - int index_edge; - BM_ITER_MESH_INDEX(e, &eiter, bm, BM_EDGES_OF_MESH, index_edge) { - BMLoop *l_a, *l_b; - - BM_elem_index_set(e, index_edge); /* set_inline */ - BM_elem_flag_disable(e, BM_ELEM_TAG); - if (BM_edge_loop_pair(e, &l_a, &l_b)) { - if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && l_a->v != l_b->v) { - BM_elem_flag_enable(e, BM_ELEM_TAG); - } - } - } - bm->elem_index_dirty &= ~BM_EDGE; - } - - int index_face, index_loop = 0; - BM_ITER_MESH_INDEX(f, &fiter, bm, BM_FACES_OF_MESH, index_face) { - BM_elem_index_set(f, index_face); /* set_inline */ - l_curr = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_elem_index_set(l_curr, index_loop++); /* set_inline */ - BM_elem_flag_disable(l_curr, BM_ELEM_TAG); - } while ((l_curr = l_curr->next) != l_first); - } - bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); + BMFace *f; + BMEdge *e; + BMIter fiter, eiter; + BMLoop *l_curr, *l_first; + + if (do_edges) { + int index_edge; + BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, index_edge) { + BMLoop *l_a, *l_b; + + BM_elem_index_set(e, index_edge); /* set_inline */ + BM_elem_flag_disable(e, BM_ELEM_TAG); + if (BM_edge_loop_pair(e, &l_a, &l_b)) { + if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && l_a->v != l_b->v) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + } + } + } + bm->elem_index_dirty &= ~BM_EDGE; + } + + int index_face, index_loop = 0; + BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, index_face) { + BM_elem_index_set(f, index_face); /* set_inline */ + l_curr = l_first = BM_FACE_FIRST_LOOP(f); + do { + BM_elem_index_set(l_curr, index_loop++); /* set_inline */ + BM_elem_flag_disable(l_curr, BM_ELEM_TAG); + } while ((l_curr = l_curr->next) != l_first); + } + bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); } /** @@ -1279,253 +1324,268 @@ void BM_normals_loops_edges_tag(BMesh *bm, const bool do_edges) #ifndef NDEBUG void BM_lnorspace_err(BMesh *bm) { - bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; - bool clear = true; - - MLoopNorSpaceArray *temp = MEM_callocN(sizeof(*temp), __func__); - temp->lspacearr = NULL; - - BKE_lnor_spacearr_init(temp, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR); - - int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); - float(*lnors)[3] = MEM_callocN(sizeof(*lnors) * bm->totloop, __func__); - BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, M_PI, lnors, temp, NULL, cd_loop_clnors_offset, true); - - for (int i = 0; i < bm->totloop; i++) { - int j = 0; - j += compare_ff(temp->lspacearr[i]->ref_alpha, bm->lnor_spacearr->lspacearr[i]->ref_alpha, 1e-4f); - j += compare_ff(temp->lspacearr[i]->ref_beta, bm->lnor_spacearr->lspacearr[i]->ref_beta, 1e-4f); - j += compare_v3v3(temp->lspacearr[i]->vec_lnor, bm->lnor_spacearr->lspacearr[i]->vec_lnor, 1e-4f); - j += compare_v3v3(temp->lspacearr[i]->vec_ortho, bm->lnor_spacearr->lspacearr[i]->vec_ortho, 1e-4f); - j += compare_v3v3(temp->lspacearr[i]->vec_ref, bm->lnor_spacearr->lspacearr[i]->vec_ref, 1e-4f); - - if (j != 5) { - clear = false; - break; - } - } - BKE_lnor_spacearr_free(temp); - MEM_freeN(temp); - MEM_freeN(lnors); - BLI_assert(clear); - - bm->spacearr_dirty &= ~BM_SPACEARR_DIRTY_ALL; + bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; + bool clear = true; + + MLoopNorSpaceArray *temp = MEM_callocN(sizeof(*temp), __func__); + temp->lspacearr = NULL; + + BKE_lnor_spacearr_init(temp, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR); + + int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); + float(*lnors)[3] = MEM_callocN(sizeof(*lnors) * bm->totloop, __func__); + BM_loops_calc_normal_vcos( + bm, NULL, NULL, NULL, true, M_PI, lnors, temp, NULL, cd_loop_clnors_offset, true); + + for (int i = 0; i < bm->totloop; i++) { + int j = 0; + j += compare_ff( + temp->lspacearr[i]->ref_alpha, bm->lnor_spacearr->lspacearr[i]->ref_alpha, 1e-4f); + j += compare_ff( + temp->lspacearr[i]->ref_beta, bm->lnor_spacearr->lspacearr[i]->ref_beta, 1e-4f); + j += compare_v3v3( + temp->lspacearr[i]->vec_lnor, bm->lnor_spacearr->lspacearr[i]->vec_lnor, 1e-4f); + j += compare_v3v3( + temp->lspacearr[i]->vec_ortho, bm->lnor_spacearr->lspacearr[i]->vec_ortho, 1e-4f); + j += compare_v3v3( + temp->lspacearr[i]->vec_ref, bm->lnor_spacearr->lspacearr[i]->vec_ref, 1e-4f); + + if (j != 5) { + clear = false; + break; + } + } + BKE_lnor_spacearr_free(temp); + MEM_freeN(temp); + MEM_freeN(lnors); + BLI_assert(clear); + + bm->spacearr_dirty &= ~BM_SPACEARR_DIRTY_ALL; } #endif -static void bm_loop_normal_mark_indiv_do_loop( - BMLoop *l, BLI_bitmap *loops, MLoopNorSpaceArray *lnor_spacearr, int *totloopsel) +static void bm_loop_normal_mark_indiv_do_loop(BMLoop *l, + BLI_bitmap *loops, + MLoopNorSpaceArray *lnor_spacearr, + int *totloopsel) { - if (l != NULL) { - const int l_idx = BM_elem_index_get(l); - - if (!BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) { - /* If vert and face selected share a loop, mark it for editing. */ - BLI_BITMAP_ENABLE(loops, l_idx); - (*totloopsel)++; - - /* Mark all loops in same loop normal space (aka smooth fan). */ - if ((lnor_spacearr->lspacearr[l_idx]->flags & MLNOR_SPACE_IS_SINGLE) == 0) { - for (LinkNode *node = lnor_spacearr->lspacearr[l_idx]->loops; node; node = node->next) { - const int lfan_idx = BM_elem_index_get((BMLoop *)node->link); - if (!BLI_BITMAP_TEST(loops, lfan_idx)) { - BLI_BITMAP_ENABLE(loops, lfan_idx); - (*totloopsel)++; - } - } - } - } - } + if (l != NULL) { + const int l_idx = BM_elem_index_get(l); + + if (!BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) { + /* If vert and face selected share a loop, mark it for editing. */ + BLI_BITMAP_ENABLE(loops, l_idx); + (*totloopsel)++; + + /* Mark all loops in same loop normal space (aka smooth fan). */ + if ((lnor_spacearr->lspacearr[l_idx]->flags & MLNOR_SPACE_IS_SINGLE) == 0) { + for (LinkNode *node = lnor_spacearr->lspacearr[l_idx]->loops; node; node = node->next) { + const int lfan_idx = BM_elem_index_get((BMLoop *)node->link); + if (!BLI_BITMAP_TEST(loops, lfan_idx)) { + BLI_BITMAP_ENABLE(loops, lfan_idx); + (*totloopsel)++; + } + } + } + } + } } /* Mark the individual clnors to be edited, if multiple selection methods are used. */ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops) { - BMEditSelection *ese, *ese_prev; - int totloopsel = 0; - - const bool sel_verts = (bm->selectmode & SCE_SELECT_VERTEX) != 0; - const bool sel_edges = (bm->selectmode & SCE_SELECT_EDGE) != 0; - const bool sel_faces = (bm->selectmode & SCE_SELECT_FACE) != 0; - const bool use_sel_face_history = sel_faces && (sel_edges || sel_verts); - - BM_mesh_elem_index_ensure(bm, BM_LOOP); - - BLI_assert(bm->lnor_spacearr != NULL); - BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR); - - if (use_sel_face_history) { - /* Using face history allows to select a single loop from a single face... - * Note that this is On² piece of code, but it is not designed to be used with huge selection sets, - * rather with only a few items selected at most.*/ - printf("using face history selection\n"); - /* Goes from last selected to the first selected element. */ - for (ese = bm->selected.last; ese; ese = ese->prev) { - if (ese->htype == BM_FACE) { - /* If current face is selected, then any verts to be edited must have been selected before it. */ - for (ese_prev = ese->prev; ese_prev; ese_prev = ese_prev->prev) { - if (ese_prev->htype == BM_VERT) { - bm_loop_normal_mark_indiv_do_loop( - BM_face_vert_share_loop((BMFace *)ese->ele, (BMVert *)ese_prev->ele), - loops, bm->lnor_spacearr, &totloopsel); - } - else if (ese_prev->htype == BM_EDGE) { - BMEdge *e = (BMEdge *)ese_prev->ele; - bm_loop_normal_mark_indiv_do_loop( - BM_face_vert_share_loop((BMFace *)ese->ele, e->v1), - loops, bm->lnor_spacearr, &totloopsel); - - bm_loop_normal_mark_indiv_do_loop( - BM_face_vert_share_loop((BMFace *)ese->ele, e->v2), - loops, bm->lnor_spacearr, &totloopsel); - } - } - } - } - } - else { - if (sel_faces) { - /* Only select all loops of selected faces. */ - printf("using face selection\n"); - BMLoop *l; - BMFace *f; - BMIter liter, fiter; - BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) { - bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel); - } - } - } - } - if (sel_edges) { - /* Only select all loops of selected edges. */ - printf("using edge selection\n"); - BMLoop *l; - BMEdge *e; - BMIter liter, eiter; - BM_ITER_MESH(e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - BM_ITER_ELEM(l, &liter, e, BM_LOOPS_OF_EDGE) { - bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel); - /* Loops actually 'have' two edges, or said otherwise, a selected edge actually selects - * *two* loops in each of its faces. We have to find the other one too. */ - if (BM_vert_in_edge(e, l->next->v)) { - bm_loop_normal_mark_indiv_do_loop(l->next, loops, bm->lnor_spacearr, &totloopsel); - } - else { - BLI_assert(BM_vert_in_edge(e, l->prev->v)); - bm_loop_normal_mark_indiv_do_loop(l->prev, loops, bm->lnor_spacearr, &totloopsel); - } - } - } - } - } - if (sel_verts) { - /* Select all loops of selected verts. */ - printf("using vert selection\n"); - BMLoop *l; - BMVert *v; - BMIter liter, viter; - BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) { - bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel); - } - } - } - } - } - - return totloopsel; + BMEditSelection *ese, *ese_prev; + int totloopsel = 0; + + const bool sel_verts = (bm->selectmode & SCE_SELECT_VERTEX) != 0; + const bool sel_edges = (bm->selectmode & SCE_SELECT_EDGE) != 0; + const bool sel_faces = (bm->selectmode & SCE_SELECT_FACE) != 0; + const bool use_sel_face_history = sel_faces && (sel_edges || sel_verts); + + BM_mesh_elem_index_ensure(bm, BM_LOOP); + + BLI_assert(bm->lnor_spacearr != NULL); + BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR); + + if (use_sel_face_history) { + /* Using face history allows to select a single loop from a single face... + * Note that this is On² piece of code, but it is not designed to be used with huge selection sets, + * rather with only a few items selected at most.*/ + printf("using face history selection\n"); + /* Goes from last selected to the first selected element. */ + for (ese = bm->selected.last; ese; ese = ese->prev) { + if (ese->htype == BM_FACE) { + /* If current face is selected, then any verts to be edited must have been selected before it. */ + for (ese_prev = ese->prev; ese_prev; ese_prev = ese_prev->prev) { + if (ese_prev->htype == BM_VERT) { + bm_loop_normal_mark_indiv_do_loop( + BM_face_vert_share_loop((BMFace *)ese->ele, (BMVert *)ese_prev->ele), + loops, + bm->lnor_spacearr, + &totloopsel); + } + else if (ese_prev->htype == BM_EDGE) { + BMEdge *e = (BMEdge *)ese_prev->ele; + bm_loop_normal_mark_indiv_do_loop(BM_face_vert_share_loop((BMFace *)ese->ele, e->v1), + loops, + bm->lnor_spacearr, + &totloopsel); + + bm_loop_normal_mark_indiv_do_loop(BM_face_vert_share_loop((BMFace *)ese->ele, e->v2), + loops, + bm->lnor_spacearr, + &totloopsel); + } + } + } + } + } + else { + if (sel_faces) { + /* Only select all loops of selected faces. */ + printf("using face selection\n"); + BMLoop *l; + BMFace *f; + BMIter liter, fiter; + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel); + } + } + } + } + if (sel_edges) { + /* Only select all loops of selected edges. */ + printf("using edge selection\n"); + BMLoop *l; + BMEdge *e; + BMIter liter, eiter; + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { + bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel); + /* Loops actually 'have' two edges, or said otherwise, a selected edge actually selects + * *two* loops in each of its faces. We have to find the other one too. */ + if (BM_vert_in_edge(e, l->next->v)) { + bm_loop_normal_mark_indiv_do_loop(l->next, loops, bm->lnor_spacearr, &totloopsel); + } + else { + BLI_assert(BM_vert_in_edge(e, l->prev->v)); + bm_loop_normal_mark_indiv_do_loop(l->prev, loops, bm->lnor_spacearr, &totloopsel); + } + } + } + } + } + if (sel_verts) { + /* Select all loops of selected verts. */ + printf("using vert selection\n"); + BMLoop *l; + BMVert *v; + BMIter liter, viter; + BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel); + } + } + } + } + } + + return totloopsel; } -static void loop_normal_editdata_init(BMesh *bm, BMLoopNorEditData *lnor_ed, BMVert *v, BMLoop *l, const int offset) +static void loop_normal_editdata_init( + BMesh *bm, BMLoopNorEditData *lnor_ed, BMVert *v, BMLoop *l, const int offset) { - BLI_assert(bm->lnor_spacearr != NULL); - BLI_assert(bm->lnor_spacearr->lspacearr != NULL); + BLI_assert(bm->lnor_spacearr != NULL); + BLI_assert(bm->lnor_spacearr->lspacearr != NULL); - const int l_index = BM_elem_index_get(l); - short *clnors_data = BM_ELEM_CD_GET_VOID_P(l, offset); + const int l_index = BM_elem_index_get(l); + short *clnors_data = BM_ELEM_CD_GET_VOID_P(l, offset); - lnor_ed->loop_index = l_index; - lnor_ed->loop = l; + lnor_ed->loop_index = l_index; + lnor_ed->loop = l; - float custom_normal[3]; - BKE_lnor_space_custom_data_to_normal(bm->lnor_spacearr->lspacearr[l_index], clnors_data, custom_normal); + float custom_normal[3]; + BKE_lnor_space_custom_data_to_normal( + bm->lnor_spacearr->lspacearr[l_index], clnors_data, custom_normal); - lnor_ed->clnors_data = clnors_data; - copy_v3_v3(lnor_ed->nloc, custom_normal); - copy_v3_v3(lnor_ed->niloc, custom_normal); + lnor_ed->clnors_data = clnors_data; + copy_v3_v3(lnor_ed->nloc, custom_normal); + copy_v3_v3(lnor_ed->niloc, custom_normal); - lnor_ed->loc = v->co; + lnor_ed->loc = v->co; } BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm) { - BMLoop *l; - BMVert *v; - BMIter liter, viter; + BMLoop *l; + BMVert *v; + BMIter liter, viter; - int totloopsel = 0; + int totloopsel = 0; - BLI_assert(bm->spacearr_dirty == 0); + BLI_assert(bm->spacearr_dirty == 0); - BMLoopNorEditDataArray *lnors_ed_arr = MEM_mallocN(sizeof(*lnors_ed_arr), __func__); - lnors_ed_arr->lidx_to_lnor_editdata = MEM_callocN( - sizeof(*lnors_ed_arr->lidx_to_lnor_editdata) * bm->totloop, __func__); + BMLoopNorEditDataArray *lnors_ed_arr = MEM_mallocN(sizeof(*lnors_ed_arr), __func__); + lnors_ed_arr->lidx_to_lnor_editdata = MEM_callocN( + sizeof(*lnors_ed_arr->lidx_to_lnor_editdata) * bm->totloop, __func__); - if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) { - BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL); - } - const int cd_custom_normal_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); + if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) { + BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL); + } + const int cd_custom_normal_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); - BM_mesh_elem_index_ensure(bm, BM_LOOP); + BM_mesh_elem_index_ensure(bm, BM_LOOP); - BLI_bitmap *loops = BLI_BITMAP_NEW(bm->totloop, __func__); + BLI_bitmap *loops = BLI_BITMAP_NEW(bm->totloop, __func__); - /* This function define loop normals to edit, based on selection modes and history. */ - totloopsel = bm_loop_normal_mark_indiv(bm, loops); + /* This function define loop normals to edit, based on selection modes and history. */ + totloopsel = bm_loop_normal_mark_indiv(bm, loops); - if (totloopsel) { - BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata = MEM_mallocN(sizeof(*lnor_ed) * totloopsel, __func__); + if (totloopsel) { + BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata = MEM_mallocN( + sizeof(*lnor_ed) * totloopsel, __func__); - BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) { - BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) { - if (BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) { - loop_normal_editdata_init(bm, lnor_ed, v, l, cd_custom_normal_offset); - lnors_ed_arr->lidx_to_lnor_editdata[BM_elem_index_get(l)] = lnor_ed; - lnor_ed++; - } - } - } - lnors_ed_arr->totloop = totloopsel; - } + BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + if (BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) { + loop_normal_editdata_init(bm, lnor_ed, v, l, cd_custom_normal_offset); + lnors_ed_arr->lidx_to_lnor_editdata[BM_elem_index_get(l)] = lnor_ed; + lnor_ed++; + } + } + } + lnors_ed_arr->totloop = totloopsel; + } - MEM_freeN(loops); - lnors_ed_arr->cd_custom_normal_offset = cd_custom_normal_offset; - return lnors_ed_arr; + MEM_freeN(loops); + lnors_ed_arr->cd_custom_normal_offset = cd_custom_normal_offset; + return lnors_ed_arr; } void BM_loop_normal_editdata_array_free(BMLoopNorEditDataArray *lnors_ed_arr) { - MEM_SAFE_FREE(lnors_ed_arr->lnor_editdata); - MEM_SAFE_FREE(lnors_ed_arr->lidx_to_lnor_editdata); - MEM_freeN(lnors_ed_arr); + MEM_SAFE_FREE(lnors_ed_arr->lnor_editdata); + MEM_SAFE_FREE(lnors_ed_arr->lidx_to_lnor_editdata); + MEM_freeN(lnors_ed_arr); } int BM_total_loop_select(BMesh *bm) { - int r_sel = 0; - BMVert *v; - BMIter viter; - - BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - r_sel += BM_vert_face_count(v); - } - } - return r_sel; + int r_sel = 0; + BMVert *v; + BMIter viter; + + BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + r_sel += BM_vert_face_count(v); + } + } + return r_sel; } /** @@ -1537,20 +1597,21 @@ int BM_total_loop_select(BMesh *bm) */ void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag)) { - /* Most operators seem to be using BMO_OPTYPE_FLAG_UNTAN_MULTIRES to change the MDisps to - * absolute space during mesh edits. With this enabled, changes to the topology - * (loop cuts, edge subdivides, etc) are not reflected in the higher levels of - * the mesh at all, which doesn't seem right. Turning off completely for now, - * until this is shown to be better for certain types of mesh edits. */ + /* Most operators seem to be using BMO_OPTYPE_FLAG_UNTAN_MULTIRES to change the MDisps to + * absolute space during mesh edits. With this enabled, changes to the topology + * (loop cuts, edge subdivides, etc) are not reflected in the higher levels of + * the mesh at all, which doesn't seem right. Turning off completely for now, + * until this is shown to be better for certain types of mesh edits. */ #ifdef BMOP_UNTAN_MULTIRES_ENABLED - /* switch multires data out of tangent space */ - if ((type_flag & BMO_OPTYPE_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) { - bmesh_mdisps_space_set(bm, MULTIRES_SPACE_TANGENT, MULTIRES_SPACE_ABSOLUTE); - - /* ensure correct normals, if possible */ - bmesh_rationalize_normals(bm, 0); - BM_mesh_normals_update(bm); - } + /* switch multires data out of tangent space */ + if ((type_flag & BMO_OPTYPE_FLAG_UNTAN_MULTIRES) && + CustomData_has_layer(&bm->ldata, CD_MDISPS)) { + bmesh_mdisps_space_set(bm, MULTIRES_SPACE_TANGENT, MULTIRES_SPACE_ABSOLUTE); + + /* ensure correct normals, if possible */ + bmesh_rationalize_normals(bm, 0); + BM_mesh_normals_update(bm); + } #endif } @@ -1559,164 +1620,163 @@ void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag)) */ void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag) { - ListBase select_history; + ListBase select_history; - /* BMO_OPTYPE_FLAG_UNTAN_MULTIRES disabled for now, see comment above in bmesh_edit_begin. */ + /* BMO_OPTYPE_FLAG_UNTAN_MULTIRES disabled for now, see comment above in bmesh_edit_begin. */ #ifdef BMOP_UNTAN_MULTIRES_ENABLED - /* switch multires data into tangent space */ - if ((flag & BMO_OPTYPE_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) { - /* set normals to their previous winding */ - bmesh_rationalize_normals(bm, 1); - bmesh_mdisps_space_set(bm, MULTIRES_SPACE_ABSOLUTE, MULTIRES_SPACE_TANGENT); - } - else if (flag & BMO_OP_FLAG_RATIONALIZE_NORMALS) { - bmesh_rationalize_normals(bm, 1); - } + /* switch multires data into tangent space */ + if ((flag & BMO_OPTYPE_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) { + /* set normals to their previous winding */ + bmesh_rationalize_normals(bm, 1); + bmesh_mdisps_space_set(bm, MULTIRES_SPACE_ABSOLUTE, MULTIRES_SPACE_TANGENT); + } + else if (flag & BMO_OP_FLAG_RATIONALIZE_NORMALS) { + bmesh_rationalize_normals(bm, 1); + } #endif - /* compute normals, clear temp flags and flush selections */ - if (type_flag & BMO_OPTYPE_FLAG_NORMALS_CALC) { - bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; - BM_mesh_normals_update(bm); - } - - - if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) { - select_history = bm->selected; - BLI_listbase_clear(&bm->selected); - } - - if (type_flag & BMO_OPTYPE_FLAG_SELECT_FLUSH) { - BM_mesh_select_mode_flush(bm); - } - - if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) { - bm->selected = select_history; - } - if (type_flag & BMO_OPTYPE_FLAG_INVALIDATE_CLNOR_ALL) { - bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; - } + /* compute normals, clear temp flags and flush selections */ + if (type_flag & BMO_OPTYPE_FLAG_NORMALS_CALC) { + bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; + BM_mesh_normals_update(bm); + } + + if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) { + select_history = bm->selected; + BLI_listbase_clear(&bm->selected); + } + + if (type_flag & BMO_OPTYPE_FLAG_SELECT_FLUSH) { + BM_mesh_select_mode_flush(bm); + } + + if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) { + bm->selected = select_history; + } + if (type_flag & BMO_OPTYPE_FLAG_INVALIDATE_CLNOR_ALL) { + bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; + } } void BM_mesh_elem_index_ensure_ex(BMesh *bm, const char htype, int elem_offset[4]) { #ifdef DEBUG - BM_ELEM_INDEX_VALIDATE(bm, "Should Never Fail!", __func__); + BM_ELEM_INDEX_VALIDATE(bm, "Should Never Fail!", __func__); #endif - if (elem_offset == NULL) { - /* Simple case. */ - const char htype_needed = bm->elem_index_dirty & htype; - if (htype_needed == 0) { - goto finally; - } - } - - if (htype & BM_VERT) { - if ((bm->elem_index_dirty & BM_VERT) || (elem_offset && elem_offset[0])) { - BMIter iter; - BMElem *ele; - - int index = elem_offset ? elem_offset[0] : 0; - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - BM_elem_index_set(ele, index++); /* set_ok */ - } - BLI_assert(elem_offset || index == bm->totvert); - } - else { - // printf("%s: skipping vert index calc!\n", __func__); - } - } - - if (htype & BM_EDGE) { - if ((bm->elem_index_dirty & BM_EDGE) || (elem_offset && elem_offset[1])) { - BMIter iter; - BMElem *ele; - - int index = elem_offset ? elem_offset[1] : 0; - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - BM_elem_index_set(ele, index++); /* set_ok */ - } - BLI_assert(elem_offset || index == bm->totedge); - } - else { - // printf("%s: skipping edge index calc!\n", __func__); - } - } - - if (htype & (BM_FACE | BM_LOOP)) { - if ((bm->elem_index_dirty & (BM_FACE | BM_LOOP)) || (elem_offset && (elem_offset[2] || elem_offset[3]))) { - BMIter iter; - BMElem *ele; - - const bool update_face = (htype & BM_FACE) && (bm->elem_index_dirty & BM_FACE); - const bool update_loop = (htype & BM_LOOP) && (bm->elem_index_dirty & BM_LOOP); - - int index_loop = elem_offset ? elem_offset[2] : 0; - int index = elem_offset ? elem_offset[3] : 0; - - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - if (update_face) { - BM_elem_index_set(ele, index++); /* set_ok */ - } - - if (update_loop) { - BMLoop *l_iter, *l_first; - - l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)ele); - do { - BM_elem_index_set(l_iter, index_loop++); /* set_ok */ - } while ((l_iter = l_iter->next) != l_first); - } - } - - BLI_assert(elem_offset || !update_face || index == bm->totface); - if (update_loop) { - BLI_assert(elem_offset || !update_loop || index_loop == bm->totloop); - } - } - else { - // printf("%s: skipping face/loop index calc!\n", __func__); - } - } + if (elem_offset == NULL) { + /* Simple case. */ + const char htype_needed = bm->elem_index_dirty & htype; + if (htype_needed == 0) { + goto finally; + } + } + + if (htype & BM_VERT) { + if ((bm->elem_index_dirty & BM_VERT) || (elem_offset && elem_offset[0])) { + BMIter iter; + BMElem *ele; + + int index = elem_offset ? elem_offset[0] : 0; + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + BM_elem_index_set(ele, index++); /* set_ok */ + } + BLI_assert(elem_offset || index == bm->totvert); + } + else { + // printf("%s: skipping vert index calc!\n", __func__); + } + } + + if (htype & BM_EDGE) { + if ((bm->elem_index_dirty & BM_EDGE) || (elem_offset && elem_offset[1])) { + BMIter iter; + BMElem *ele; + + int index = elem_offset ? elem_offset[1] : 0; + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + BM_elem_index_set(ele, index++); /* set_ok */ + } + BLI_assert(elem_offset || index == bm->totedge); + } + else { + // printf("%s: skipping edge index calc!\n", __func__); + } + } + + if (htype & (BM_FACE | BM_LOOP)) { + if ((bm->elem_index_dirty & (BM_FACE | BM_LOOP)) || + (elem_offset && (elem_offset[2] || elem_offset[3]))) { + BMIter iter; + BMElem *ele; + + const bool update_face = (htype & BM_FACE) && (bm->elem_index_dirty & BM_FACE); + const bool update_loop = (htype & BM_LOOP) && (bm->elem_index_dirty & BM_LOOP); + + int index_loop = elem_offset ? elem_offset[2] : 0; + int index = elem_offset ? elem_offset[3] : 0; + + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + if (update_face) { + BM_elem_index_set(ele, index++); /* set_ok */ + } + + if (update_loop) { + BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)ele); + do { + BM_elem_index_set(l_iter, index_loop++); /* set_ok */ + } while ((l_iter = l_iter->next) != l_first); + } + } + + BLI_assert(elem_offset || !update_face || index == bm->totface); + if (update_loop) { + BLI_assert(elem_offset || !update_loop || index_loop == bm->totloop); + } + } + else { + // printf("%s: skipping face/loop index calc!\n", __func__); + } + } finally: - bm->elem_index_dirty &= ~htype; - if (elem_offset) { - if (htype & BM_VERT) { - elem_offset[0] += bm->totvert; - if (elem_offset[0] != bm->totvert) { - bm->elem_index_dirty |= BM_VERT; - } - } - if (htype & BM_EDGE) { - elem_offset[1] += bm->totedge; - if (elem_offset[1] != bm->totedge) { - bm->elem_index_dirty |= BM_EDGE; - } - } - if (htype & BM_LOOP) { - elem_offset[2] += bm->totloop; - if (elem_offset[2] != bm->totloop) { - bm->elem_index_dirty |= BM_LOOP; - } - } - if (htype & BM_FACE) { - elem_offset[3] += bm->totface; - if (elem_offset[3] != bm->totface) { - bm->elem_index_dirty |= BM_FACE; - } - } - } + bm->elem_index_dirty &= ~htype; + if (elem_offset) { + if (htype & BM_VERT) { + elem_offset[0] += bm->totvert; + if (elem_offset[0] != bm->totvert) { + bm->elem_index_dirty |= BM_VERT; + } + } + if (htype & BM_EDGE) { + elem_offset[1] += bm->totedge; + if (elem_offset[1] != bm->totedge) { + bm->elem_index_dirty |= BM_EDGE; + } + } + if (htype & BM_LOOP) { + elem_offset[2] += bm->totloop; + if (elem_offset[2] != bm->totloop) { + bm->elem_index_dirty |= BM_LOOP; + } + } + if (htype & BM_FACE) { + elem_offset[3] += bm->totface; + if (elem_offset[3] != bm->totface) { + bm->elem_index_dirty |= BM_FACE; + } + } + } } void BM_mesh_elem_index_ensure(BMesh *bm, const char htype) { - BM_mesh_elem_index_ensure_ex(bm, htype, NULL); + BM_mesh_elem_index_ensure_ex(bm, htype, NULL); } - /** * Array checking/setting macros * @@ -1729,221 +1789,223 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype) */ void BM_mesh_elem_index_validate( - BMesh *bm, const char *location, const char *func, - const char *msg_a, const char *msg_b) + BMesh *bm, const char *location, const char *func, const char *msg_a, const char *msg_b) { - const char iter_types[3] = {BM_VERTS_OF_MESH, - BM_EDGES_OF_MESH, - BM_FACES_OF_MESH}; - - const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE}; - const char *type_names[3] = {"vert", "edge", "face"}; - - BMIter iter; - BMElem *ele; - int i; - bool is_any_error = 0; - - for (i = 0; i < 3; i++) { - const bool is_dirty = (flag_types[i] & bm->elem_index_dirty) != 0; - int index = 0; - bool is_error = false; - int err_val = 0; - int err_idx = 0; - - BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { - if (!is_dirty) { - if (BM_elem_index_get(ele) != index) { - err_val = BM_elem_index_get(ele); - err_idx = index; - is_error = true; - } - } - - BM_elem_index_set(ele, index); /* set_ok */ - index++; - } - - if ((is_error == true) && (is_dirty == false)) { - is_any_error = true; - fprintf(stderr, - "Invalid Index: at %s, %s, %s[%d] invalid index %d, '%s', '%s'\n", - location, func, type_names[i], err_idx, err_val, msg_a, msg_b); - } - else if ((is_error == false) && (is_dirty == true)) { - -#if 0 /* mostly annoying */ - - /* dirty may have been incorrectly set */ - fprintf(stderr, - "Invalid Dirty: at %s, %s (%s), dirty flag was set but all index values are correct, '%s', '%s'\n", - location, func, type_names[i], msg_a, msg_b); + const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH}; + + const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE}; + const char *type_names[3] = {"vert", "edge", "face"}; + + BMIter iter; + BMElem *ele; + int i; + bool is_any_error = 0; + + for (i = 0; i < 3; i++) { + const bool is_dirty = (flag_types[i] & bm->elem_index_dirty) != 0; + int index = 0; + bool is_error = false; + int err_val = 0; + int err_idx = 0; + + BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { + if (!is_dirty) { + if (BM_elem_index_get(ele) != index) { + err_val = BM_elem_index_get(ele); + err_idx = index; + is_error = true; + } + } + + BM_elem_index_set(ele, index); /* set_ok */ + index++; + } + + if ((is_error == true) && (is_dirty == false)) { + is_any_error = true; + fprintf(stderr, + "Invalid Index: at %s, %s, %s[%d] invalid index %d, '%s', '%s'\n", + location, + func, + type_names[i], + err_idx, + err_val, + msg_a, + msg_b); + } + else if ((is_error == false) && (is_dirty == true)) { + +#if 0 /* mostly annoying */ + + /* dirty may have been incorrectly set */ + fprintf(stderr, + "Invalid Dirty: at %s, %s (%s), dirty flag was set but all index values are correct, '%s', '%s'\n", + location, func, type_names[i], msg_a, msg_b); #endif - } - } + } + } #if 0 /* mostly annoying, even in debug mode */ -#ifdef DEBUG - if (is_any_error == 0) { - fprintf(stderr, - "Valid Index Success: at %s, %s, '%s', '%s'\n", - location, func, msg_a, msg_b); - } +# ifdef DEBUG + if (is_any_error == 0) { + fprintf(stderr, + "Valid Index Success: at %s, %s, '%s', '%s'\n", + location, func, msg_a, msg_b); + } +# endif #endif -#endif - (void) is_any_error; /* shut up the compiler */ - + (void)is_any_error; /* shut up the compiler */ } /* debug check only - no need to optimize */ #ifndef NDEBUG bool BM_mesh_elem_table_check(BMesh *bm) { - BMIter iter; - BMElem *ele; - int i; - - if (bm->vtable && ((bm->elem_table_dirty & BM_VERT) == 0)) { - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { - if (ele != (BMElem *)bm->vtable[i]) { - return false; - } - } - } - - if (bm->etable && ((bm->elem_table_dirty & BM_EDGE) == 0)) { - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { - if (ele != (BMElem *)bm->etable[i]) { - return false; - } - } - } - - if (bm->ftable && ((bm->elem_table_dirty & BM_FACE) == 0)) { - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { - if (ele != (BMElem *)bm->ftable[i]) { - return false; - } - } - } - - return true; + BMIter iter; + BMElem *ele; + int i; + + if (bm->vtable && ((bm->elem_table_dirty & BM_VERT) == 0)) { + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { + if (ele != (BMElem *)bm->vtable[i]) { + return false; + } + } + } + + if (bm->etable && ((bm->elem_table_dirty & BM_EDGE) == 0)) { + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { + if (ele != (BMElem *)bm->etable[i]) { + return false; + } + } + } + + if (bm->ftable && ((bm->elem_table_dirty & BM_FACE) == 0)) { + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { + if (ele != (BMElem *)bm->ftable[i]) { + return false; + } + } + } + + return true; } #endif - - void BM_mesh_elem_table_ensure(BMesh *bm, const char htype) { - /* assume if the array is non-null then its valid and no need to recalc */ - const char htype_needed = (((bm->vtable && ((bm->elem_table_dirty & BM_VERT) == 0)) ? 0 : BM_VERT) | - ((bm->etable && ((bm->elem_table_dirty & BM_EDGE) == 0)) ? 0 : BM_EDGE) | - ((bm->ftable && ((bm->elem_table_dirty & BM_FACE) == 0)) ? 0 : BM_FACE)) & htype; - - BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); - - /* in debug mode double check we didn't need to recalculate */ - BLI_assert(BM_mesh_elem_table_check(bm) == true); - - if (htype_needed == 0) { - goto finally; - } - - if (htype_needed & BM_VERT) { - if (bm->vtable && bm->totvert <= bm->vtable_tot && bm->totvert * 2 >= bm->vtable_tot) { - /* pass (re-use the array) */ - } - else { - if (bm->vtable) { - MEM_freeN(bm->vtable); - } - bm->vtable = MEM_mallocN(sizeof(void **) * bm->totvert, "bm->vtable"); - bm->vtable_tot = bm->totvert; - } - } - if (htype_needed & BM_EDGE) { - if (bm->etable && bm->totedge <= bm->etable_tot && bm->totedge * 2 >= bm->etable_tot) { - /* pass (re-use the array) */ - } - else { - if (bm->etable) { - MEM_freeN(bm->etable); - } - bm->etable = MEM_mallocN(sizeof(void **) * bm->totedge, "bm->etable"); - bm->etable_tot = bm->totedge; - } - } - if (htype_needed & BM_FACE) { - if (bm->ftable && bm->totface <= bm->ftable_tot && bm->totface * 2 >= bm->ftable_tot) { - /* pass (re-use the array) */ - } - else { - if (bm->ftable) { - MEM_freeN(bm->ftable); - } - bm->ftable = MEM_mallocN(sizeof(void **) * bm->totface, "bm->ftable"); - bm->ftable_tot = bm->totface; - } - } - - if (htype_needed & BM_VERT) { - BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)bm->vtable, bm->totvert); - } - - if (htype_needed & BM_EDGE) { - BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)bm->etable, bm->totedge); - } - - if (htype_needed & BM_FACE) { - BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)bm->ftable, bm->totface); - } + /* assume if the array is non-null then its valid and no need to recalc */ + const char htype_needed = + (((bm->vtable && ((bm->elem_table_dirty & BM_VERT) == 0)) ? 0 : BM_VERT) | + ((bm->etable && ((bm->elem_table_dirty & BM_EDGE) == 0)) ? 0 : BM_EDGE) | + ((bm->ftable && ((bm->elem_table_dirty & BM_FACE) == 0)) ? 0 : BM_FACE)) & + htype; + + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + + /* in debug mode double check we didn't need to recalculate */ + BLI_assert(BM_mesh_elem_table_check(bm) == true); + + if (htype_needed == 0) { + goto finally; + } + + if (htype_needed & BM_VERT) { + if (bm->vtable && bm->totvert <= bm->vtable_tot && bm->totvert * 2 >= bm->vtable_tot) { + /* pass (re-use the array) */ + } + else { + if (bm->vtable) { + MEM_freeN(bm->vtable); + } + bm->vtable = MEM_mallocN(sizeof(void **) * bm->totvert, "bm->vtable"); + bm->vtable_tot = bm->totvert; + } + } + if (htype_needed & BM_EDGE) { + if (bm->etable && bm->totedge <= bm->etable_tot && bm->totedge * 2 >= bm->etable_tot) { + /* pass (re-use the array) */ + } + else { + if (bm->etable) { + MEM_freeN(bm->etable); + } + bm->etable = MEM_mallocN(sizeof(void **) * bm->totedge, "bm->etable"); + bm->etable_tot = bm->totedge; + } + } + if (htype_needed & BM_FACE) { + if (bm->ftable && bm->totface <= bm->ftable_tot && bm->totface * 2 >= bm->ftable_tot) { + /* pass (re-use the array) */ + } + else { + if (bm->ftable) { + MEM_freeN(bm->ftable); + } + bm->ftable = MEM_mallocN(sizeof(void **) * bm->totface, "bm->ftable"); + bm->ftable_tot = bm->totface; + } + } + + if (htype_needed & BM_VERT) { + BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)bm->vtable, bm->totvert); + } + + if (htype_needed & BM_EDGE) { + BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)bm->etable, bm->totedge); + } + + if (htype_needed & BM_FACE) { + BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)bm->ftable, bm->totface); + } finally: - /* Only clear dirty flags when all the pointers and data are actually valid. - * This prevents possible threading issues when dirty flag check failed but - * data wasn't ready still. - */ - bm->elem_table_dirty &= ~htype_needed; + /* Only clear dirty flags when all the pointers and data are actually valid. + * This prevents possible threading issues when dirty flag check failed but + * data wasn't ready still. + */ + bm->elem_table_dirty &= ~htype_needed; } /* use BM_mesh_elem_table_ensure where possible to avoid full rebuild */ void BM_mesh_elem_table_init(BMesh *bm, const char htype) { - BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); - /* force recalc */ - BM_mesh_elem_table_free(bm, BM_ALL_NOLOOP); - BM_mesh_elem_table_ensure(bm, htype); + /* force recalc */ + BM_mesh_elem_table_free(bm, BM_ALL_NOLOOP); + BM_mesh_elem_table_ensure(bm, htype); } void BM_mesh_elem_table_free(BMesh *bm, const char htype) { - if (htype & BM_VERT) { - MEM_SAFE_FREE(bm->vtable); - } + if (htype & BM_VERT) { + MEM_SAFE_FREE(bm->vtable); + } - if (htype & BM_EDGE) { - MEM_SAFE_FREE(bm->etable); - } + if (htype & BM_EDGE) { + MEM_SAFE_FREE(bm->etable); + } - if (htype & BM_FACE) { - MEM_SAFE_FREE(bm->ftable); - } + if (htype & BM_FACE) { + MEM_SAFE_FREE(bm->ftable); + } } BMVert *BM_vert_at_index_find(BMesh *bm, const int index) { - return BLI_mempool_findelem(bm->vpool, index); + return BLI_mempool_findelem(bm->vpool, index); } BMEdge *BM_edge_at_index_find(BMesh *bm, const int index) { - return BLI_mempool_findelem(bm->epool, index); + return BLI_mempool_findelem(bm->epool, index); } BMFace *BM_face_at_index_find(BMesh *bm, const int index) { - return BLI_mempool_findelem(bm->fpool, index); + return BLI_mempool_findelem(bm->fpool, index); } /** @@ -1953,55 +2015,55 @@ BMFace *BM_face_at_index_find(BMesh *bm, const int index) */ BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index) { - if ((bm->elem_table_dirty & BM_VERT) == 0) { - return (index < bm->totvert) ? bm->vtable[index] : NULL; - } - else { - return BM_vert_at_index_find(bm, index); - } + if ((bm->elem_table_dirty & BM_VERT) == 0) { + return (index < bm->totvert) ? bm->vtable[index] : NULL; + } + else { + return BM_vert_at_index_find(bm, index); + } } BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index) { - if ((bm->elem_table_dirty & BM_EDGE) == 0) { - return (index < bm->totedge) ? bm->etable[index] : NULL; - } - else { - return BM_edge_at_index_find(bm, index); - } + if ((bm->elem_table_dirty & BM_EDGE) == 0) { + return (index < bm->totedge) ? bm->etable[index] : NULL; + } + else { + return BM_edge_at_index_find(bm, index); + } } BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index) { - if ((bm->elem_table_dirty & BM_FACE) == 0) { - return (index < bm->totface) ? bm->ftable[index] : NULL; - } - else { - return BM_face_at_index_find(bm, index); - } + if ((bm->elem_table_dirty & BM_FACE) == 0) { + return (index < bm->totface) ? bm->ftable[index] : NULL; + } + else { + return BM_face_at_index_find(bm, index); + } } - /** * Return the amount of element of type 'type' in a given bmesh. */ int BM_mesh_elem_count(BMesh *bm, const char htype) { - BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); - - switch (htype) { - case BM_VERT: return bm->totvert; - case BM_EDGE: return bm->totedge; - case BM_FACE: return bm->totface; - default: - { - BLI_assert(0); - return 0; - } - } + BLI_assert((htype & ~BM_ALL_NOLOOP) == 0); + + switch (htype) { + case BM_VERT: + return bm->totvert; + case BM_EDGE: + return bm->totedge; + case BM_FACE: + return bm->totface; + default: { + BLI_assert(0); + return 0; + } + } } - /** * Remaps the vertices, edges and/or faces of the bmesh as indicated by vert/edge/face_idx arrays * (xxx_idx[org_index] = new_index). @@ -2014,281 +2076,277 @@ int BM_mesh_elem_count(BMesh *bm, const char htype) * * WARNING: Be careful if you keep pointers to affected BM elements, or arrays, when using this func! */ -void BM_mesh_remap( - BMesh *bm, - const uint *vert_idx, - const uint *edge_idx, - const uint *face_idx) +void BM_mesh_remap(BMesh *bm, const uint *vert_idx, const uint *edge_idx, const uint *face_idx) { - /* Mapping old to new pointers. */ - GHash *vptr_map = NULL, *eptr_map = NULL, *fptr_map = NULL; - BMIter iter, iterl; - BMVert *ve; - BMEdge *ed; - BMFace *fa; - BMLoop *lo; - - if (!(vert_idx || edge_idx || face_idx)) { - return; - } - - BM_mesh_elem_table_ensure( - bm, - (vert_idx ? BM_VERT : 0) | - (edge_idx ? BM_EDGE : 0) | - (face_idx ? BM_FACE : 0)); - - /* Remap Verts */ - if (vert_idx) { - BMVert **verts_pool, *verts_copy, **vep; - int i, totvert = bm->totvert; - const uint *new_idx; - /* Special case: Python uses custom - data layers to hold PyObject references. - * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */ - const int cd_vert_pyptr = CustomData_get_offset(&bm->vdata, CD_BM_ELEM_PYPTR); - - /* Init the old-to-new vert pointers mapping */ - vptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap vert pointers mapping", bm->totvert); - - /* Make a copy of all vertices. */ - verts_pool = bm->vtable; - verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy"); - void **pyptrs = (cd_vert_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totvert, __func__) : NULL; - for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--; ve--, vep--) { - *ve = **vep; -/* printf("*vep: %p, verts_pool[%d]: %p\n", *vep, i, verts_pool[i]);*/ - if (cd_vert_pyptr != -1) { - void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ve), cd_vert_pyptr); - pyptrs[i] = *pyptr; - } - } - - /* Copy back verts to their new place, and update old2new pointers mapping. */ - new_idx = vert_idx + totvert - 1; - ve = verts_copy + totvert - 1; - vep = verts_pool + totvert - 1; /* old, org pointer */ - for (i = totvert; i--; new_idx--, ve--, vep--) { - BMVert *new_vep = verts_pool[*new_idx]; - *new_vep = *ve; -/* printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/ - BLI_ghash_insert(vptr_map, *vep, new_vep); - if (cd_vert_pyptr != -1) { - void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_vep), cd_vert_pyptr); - *pyptr = pyptrs[*new_idx]; - } - } - bm->elem_index_dirty |= BM_VERT; - bm->elem_table_dirty |= BM_VERT; - - MEM_freeN(verts_copy); - if (pyptrs) { - MEM_freeN(pyptrs); - } - } - - /* Remap Edges */ - if (edge_idx) { - BMEdge **edges_pool, *edges_copy, **edp; - int i, totedge = bm->totedge; - const uint *new_idx; - /* Special case: Python uses custom - data layers to hold PyObject references. - * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */ - const int cd_edge_pyptr = CustomData_get_offset(&bm->edata, CD_BM_ELEM_PYPTR); - - /* Init the old-to-new vert pointers mapping */ - eptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap edge pointers mapping", bm->totedge); - - /* Make a copy of all vertices. */ - edges_pool = bm->etable; - edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy"); - void **pyptrs = (cd_edge_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totedge, __func__) : NULL; - for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--; ed--, edp--) { - *ed = **edp; - if (cd_edge_pyptr != -1) { - void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ed), cd_edge_pyptr); - pyptrs[i] = *pyptr; - } - } - - /* Copy back verts to their new place, and update old2new pointers mapping. */ - new_idx = edge_idx + totedge - 1; - ed = edges_copy + totedge - 1; - edp = edges_pool + totedge - 1; /* old, org pointer */ - for (i = totedge; i--; new_idx--, ed--, edp--) { - BMEdge *new_edp = edges_pool[*new_idx]; - *new_edp = *ed; - BLI_ghash_insert(eptr_map, *edp, new_edp); -/* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/ - if (cd_edge_pyptr != -1) { - void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_edp), cd_edge_pyptr); - *pyptr = pyptrs[*new_idx]; - } - } - bm->elem_index_dirty |= BM_EDGE; - bm->elem_table_dirty |= BM_EDGE; - - MEM_freeN(edges_copy); - if (pyptrs) { - MEM_freeN(pyptrs); - } - } - - /* Remap Faces */ - if (face_idx) { - BMFace **faces_pool, *faces_copy, **fap; - int i, totface = bm->totface; - const uint *new_idx; - /* Special case: Python uses custom - data layers to hold PyObject references. - * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */ - const int cd_poly_pyptr = CustomData_get_offset(&bm->pdata, CD_BM_ELEM_PYPTR); - - /* Init the old-to-new vert pointers mapping */ - fptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap face pointers mapping", bm->totface); - - /* Make a copy of all vertices. */ - faces_pool = bm->ftable; - faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy"); - void **pyptrs = (cd_poly_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totface, __func__) : NULL; - for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--; fa--, fap--) { - *fa = **fap; - if (cd_poly_pyptr != -1) { - void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)fa), cd_poly_pyptr); - pyptrs[i] = *pyptr; - } - } - - /* Copy back verts to their new place, and update old2new pointers mapping. */ - new_idx = face_idx + totface - 1; - fa = faces_copy + totface - 1; - fap = faces_pool + totface - 1; /* old, org pointer */ - for (i = totface; i--; new_idx--, fa--, fap--) { - BMFace *new_fap = faces_pool[*new_idx]; - *new_fap = *fa; - BLI_ghash_insert(fptr_map, *fap, new_fap); - if (cd_poly_pyptr != -1) { - void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_fap), cd_poly_pyptr); - *pyptr = pyptrs[*new_idx]; - } - } - - bm->elem_index_dirty |= BM_FACE | BM_LOOP; - bm->elem_table_dirty |= BM_FACE; - - MEM_freeN(faces_copy); - if (pyptrs) { - MEM_freeN(pyptrs); - } - } - - /* And now, fix all vertices/edges/faces/loops pointers! */ - /* Verts' pointers, only edge pointers... */ - if (eptr_map) { - BM_ITER_MESH (ve, &iter, bm, BM_VERTS_OF_MESH) { -/* printf("Vert e: %p -> %p\n", ve->e, BLI_ghash_lookup(eptr_map, ve->e));*/ - if (ve->e) { - ve->e = BLI_ghash_lookup(eptr_map, ve->e); - BLI_assert(ve->e); - } - } - } - - /* Edges' pointers, only vert pointers (as we don't mess with loops!), and - ack! - edge pointers, - * as we have to handle disklinks... */ - if (vptr_map || eptr_map) { - BM_ITER_MESH (ed, &iter, bm, BM_EDGES_OF_MESH) { - if (vptr_map) { -/* printf("Edge v1: %p -> %p\n", ed->v1, BLI_ghash_lookup(vptr_map, ed->v1));*/ -/* printf("Edge v2: %p -> %p\n", ed->v2, BLI_ghash_lookup(vptr_map, ed->v2));*/ - ed->v1 = BLI_ghash_lookup(vptr_map, ed->v1); - ed->v2 = BLI_ghash_lookup(vptr_map, ed->v2); - BLI_assert(ed->v1); - BLI_assert(ed->v2); - } - if (eptr_map) { -/* printf("Edge v1_disk_link prev: %p -> %p\n", ed->v1_disk_link.prev,*/ -/* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev));*/ -/* printf("Edge v1_disk_link next: %p -> %p\n", ed->v1_disk_link.next,*/ -/* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next));*/ -/* printf("Edge v2_disk_link prev: %p -> %p\n", ed->v2_disk_link.prev,*/ -/* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev));*/ -/* printf("Edge v2_disk_link next: %p -> %p\n", ed->v2_disk_link.next,*/ -/* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next));*/ - ed->v1_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev); - ed->v1_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next); - ed->v2_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev); - ed->v2_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next); - BLI_assert(ed->v1_disk_link.prev); - BLI_assert(ed->v1_disk_link.next); - BLI_assert(ed->v2_disk_link.prev); - BLI_assert(ed->v2_disk_link.next); - } - } - } - - /* Faces' pointers (loops, in fact), always needed... */ - BM_ITER_MESH (fa, &iter, bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (lo, &iterl, fa, BM_LOOPS_OF_FACE) { - if (vptr_map) { -/* printf("Loop v: %p -> %p\n", lo->v, BLI_ghash_lookup(vptr_map, lo->v));*/ - lo->v = BLI_ghash_lookup(vptr_map, lo->v); - BLI_assert(lo->v); - } - if (eptr_map) { -/* printf("Loop e: %p -> %p\n", lo->e, BLI_ghash_lookup(eptr_map, lo->e));*/ - lo->e = BLI_ghash_lookup(eptr_map, lo->e); - BLI_assert(lo->e); - } - if (fptr_map) { -/* printf("Loop f: %p -> %p\n", lo->f, BLI_ghash_lookup(fptr_map, lo->f));*/ - lo->f = BLI_ghash_lookup(fptr_map, lo->f); - BLI_assert(lo->f); - } - } - } - - /* Selection history */ - { - BMEditSelection *ese; - for (ese = bm->selected.first; ese; ese = ese->next) { - switch (ese->htype) { - case BM_VERT: - if (vptr_map) { - ese->ele = BLI_ghash_lookup(vptr_map, ese->ele); - BLI_assert(ese->ele); - } - break; - case BM_EDGE: - if (eptr_map) { - ese->ele = BLI_ghash_lookup(eptr_map, ese->ele); - BLI_assert(ese->ele); - } - break; - case BM_FACE: - if (fptr_map) { - ese->ele = BLI_ghash_lookup(fptr_map, ese->ele); - BLI_assert(ese->ele); - } - break; - } - } - } - - if (fptr_map) { - if (bm->act_face) { - bm->act_face = BLI_ghash_lookup(fptr_map, bm->act_face); - BLI_assert(bm->act_face); - } - } - - if (vptr_map) { - BLI_ghash_free(vptr_map, NULL, NULL); - } - if (eptr_map) { - BLI_ghash_free(eptr_map, NULL, NULL); - } - if (fptr_map) { - BLI_ghash_free(fptr_map, NULL, NULL); - } + /* Mapping old to new pointers. */ + GHash *vptr_map = NULL, *eptr_map = NULL, *fptr_map = NULL; + BMIter iter, iterl; + BMVert *ve; + BMEdge *ed; + BMFace *fa; + BMLoop *lo; + + if (!(vert_idx || edge_idx || face_idx)) { + return; + } + + BM_mesh_elem_table_ensure( + bm, (vert_idx ? BM_VERT : 0) | (edge_idx ? BM_EDGE : 0) | (face_idx ? BM_FACE : 0)); + + /* Remap Verts */ + if (vert_idx) { + BMVert **verts_pool, *verts_copy, **vep; + int i, totvert = bm->totvert; + const uint *new_idx; + /* Special case: Python uses custom - data layers to hold PyObject references. + * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */ + const int cd_vert_pyptr = CustomData_get_offset(&bm->vdata, CD_BM_ELEM_PYPTR); + + /* Init the old-to-new vert pointers mapping */ + vptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap vert pointers mapping", bm->totvert); + + /* Make a copy of all vertices. */ + verts_pool = bm->vtable; + verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy"); + void **pyptrs = (cd_vert_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totvert, __func__) : NULL; + for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--; + ve--, vep--) { + *ve = **vep; + /* printf("*vep: %p, verts_pool[%d]: %p\n", *vep, i, verts_pool[i]);*/ + if (cd_vert_pyptr != -1) { + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ve), cd_vert_pyptr); + pyptrs[i] = *pyptr; + } + } + + /* Copy back verts to their new place, and update old2new pointers mapping. */ + new_idx = vert_idx + totvert - 1; + ve = verts_copy + totvert - 1; + vep = verts_pool + totvert - 1; /* old, org pointer */ + for (i = totvert; i--; new_idx--, ve--, vep--) { + BMVert *new_vep = verts_pool[*new_idx]; + *new_vep = *ve; + /* printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/ + BLI_ghash_insert(vptr_map, *vep, new_vep); + if (cd_vert_pyptr != -1) { + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_vep), cd_vert_pyptr); + *pyptr = pyptrs[*new_idx]; + } + } + bm->elem_index_dirty |= BM_VERT; + bm->elem_table_dirty |= BM_VERT; + + MEM_freeN(verts_copy); + if (pyptrs) { + MEM_freeN(pyptrs); + } + } + + /* Remap Edges */ + if (edge_idx) { + BMEdge **edges_pool, *edges_copy, **edp; + int i, totedge = bm->totedge; + const uint *new_idx; + /* Special case: Python uses custom - data layers to hold PyObject references. + * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */ + const int cd_edge_pyptr = CustomData_get_offset(&bm->edata, CD_BM_ELEM_PYPTR); + + /* Init the old-to-new vert pointers mapping */ + eptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap edge pointers mapping", bm->totedge); + + /* Make a copy of all vertices. */ + edges_pool = bm->etable; + edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy"); + void **pyptrs = (cd_edge_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totedge, __func__) : NULL; + for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--; + ed--, edp--) { + *ed = **edp; + if (cd_edge_pyptr != -1) { + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ed), cd_edge_pyptr); + pyptrs[i] = *pyptr; + } + } + + /* Copy back verts to their new place, and update old2new pointers mapping. */ + new_idx = edge_idx + totedge - 1; + ed = edges_copy + totedge - 1; + edp = edges_pool + totedge - 1; /* old, org pointer */ + for (i = totedge; i--; new_idx--, ed--, edp--) { + BMEdge *new_edp = edges_pool[*new_idx]; + *new_edp = *ed; + BLI_ghash_insert(eptr_map, *edp, new_edp); + /* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/ + if (cd_edge_pyptr != -1) { + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_edp), cd_edge_pyptr); + *pyptr = pyptrs[*new_idx]; + } + } + bm->elem_index_dirty |= BM_EDGE; + bm->elem_table_dirty |= BM_EDGE; + + MEM_freeN(edges_copy); + if (pyptrs) { + MEM_freeN(pyptrs); + } + } + + /* Remap Faces */ + if (face_idx) { + BMFace **faces_pool, *faces_copy, **fap; + int i, totface = bm->totface; + const uint *new_idx; + /* Special case: Python uses custom - data layers to hold PyObject references. + * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */ + const int cd_poly_pyptr = CustomData_get_offset(&bm->pdata, CD_BM_ELEM_PYPTR); + + /* Init the old-to-new vert pointers mapping */ + fptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap face pointers mapping", bm->totface); + + /* Make a copy of all vertices. */ + faces_pool = bm->ftable; + faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy"); + void **pyptrs = (cd_poly_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totface, __func__) : NULL; + for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--; + fa--, fap--) { + *fa = **fap; + if (cd_poly_pyptr != -1) { + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)fa), cd_poly_pyptr); + pyptrs[i] = *pyptr; + } + } + + /* Copy back verts to their new place, and update old2new pointers mapping. */ + new_idx = face_idx + totface - 1; + fa = faces_copy + totface - 1; + fap = faces_pool + totface - 1; /* old, org pointer */ + for (i = totface; i--; new_idx--, fa--, fap--) { + BMFace *new_fap = faces_pool[*new_idx]; + *new_fap = *fa; + BLI_ghash_insert(fptr_map, *fap, new_fap); + if (cd_poly_pyptr != -1) { + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_fap), cd_poly_pyptr); + *pyptr = pyptrs[*new_idx]; + } + } + + bm->elem_index_dirty |= BM_FACE | BM_LOOP; + bm->elem_table_dirty |= BM_FACE; + + MEM_freeN(faces_copy); + if (pyptrs) { + MEM_freeN(pyptrs); + } + } + + /* And now, fix all vertices/edges/faces/loops pointers! */ + /* Verts' pointers, only edge pointers... */ + if (eptr_map) { + BM_ITER_MESH (ve, &iter, bm, BM_VERTS_OF_MESH) { + /* printf("Vert e: %p -> %p\n", ve->e, BLI_ghash_lookup(eptr_map, ve->e));*/ + if (ve->e) { + ve->e = BLI_ghash_lookup(eptr_map, ve->e); + BLI_assert(ve->e); + } + } + } + + /* Edges' pointers, only vert pointers (as we don't mess with loops!), and - ack! - edge pointers, + * as we have to handle disklinks... */ + if (vptr_map || eptr_map) { + BM_ITER_MESH (ed, &iter, bm, BM_EDGES_OF_MESH) { + if (vptr_map) { + /* printf("Edge v1: %p -> %p\n", ed->v1, BLI_ghash_lookup(vptr_map, ed->v1));*/ + /* printf("Edge v2: %p -> %p\n", ed->v2, BLI_ghash_lookup(vptr_map, ed->v2));*/ + ed->v1 = BLI_ghash_lookup(vptr_map, ed->v1); + ed->v2 = BLI_ghash_lookup(vptr_map, ed->v2); + BLI_assert(ed->v1); + BLI_assert(ed->v2); + } + if (eptr_map) { + /* printf("Edge v1_disk_link prev: %p -> %p\n", ed->v1_disk_link.prev,*/ + /* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev));*/ + /* printf("Edge v1_disk_link next: %p -> %p\n", ed->v1_disk_link.next,*/ + /* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next));*/ + /* printf("Edge v2_disk_link prev: %p -> %p\n", ed->v2_disk_link.prev,*/ + /* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev));*/ + /* printf("Edge v2_disk_link next: %p -> %p\n", ed->v2_disk_link.next,*/ + /* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next));*/ + ed->v1_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev); + ed->v1_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next); + ed->v2_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev); + ed->v2_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next); + BLI_assert(ed->v1_disk_link.prev); + BLI_assert(ed->v1_disk_link.next); + BLI_assert(ed->v2_disk_link.prev); + BLI_assert(ed->v2_disk_link.next); + } + } + } + + /* Faces' pointers (loops, in fact), always needed... */ + BM_ITER_MESH (fa, &iter, bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (lo, &iterl, fa, BM_LOOPS_OF_FACE) { + if (vptr_map) { + /* printf("Loop v: %p -> %p\n", lo->v, BLI_ghash_lookup(vptr_map, lo->v));*/ + lo->v = BLI_ghash_lookup(vptr_map, lo->v); + BLI_assert(lo->v); + } + if (eptr_map) { + /* printf("Loop e: %p -> %p\n", lo->e, BLI_ghash_lookup(eptr_map, lo->e));*/ + lo->e = BLI_ghash_lookup(eptr_map, lo->e); + BLI_assert(lo->e); + } + if (fptr_map) { + /* printf("Loop f: %p -> %p\n", lo->f, BLI_ghash_lookup(fptr_map, lo->f));*/ + lo->f = BLI_ghash_lookup(fptr_map, lo->f); + BLI_assert(lo->f); + } + } + } + + /* Selection history */ + { + BMEditSelection *ese; + for (ese = bm->selected.first; ese; ese = ese->next) { + switch (ese->htype) { + case BM_VERT: + if (vptr_map) { + ese->ele = BLI_ghash_lookup(vptr_map, ese->ele); + BLI_assert(ese->ele); + } + break; + case BM_EDGE: + if (eptr_map) { + ese->ele = BLI_ghash_lookup(eptr_map, ese->ele); + BLI_assert(ese->ele); + } + break; + case BM_FACE: + if (fptr_map) { + ese->ele = BLI_ghash_lookup(fptr_map, ese->ele); + BLI_assert(ese->ele); + } + break; + } + } + } + + if (fptr_map) { + if (bm->act_face) { + bm->act_face = BLI_ghash_lookup(fptr_map, bm->act_face); + BLI_assert(bm->act_face); + } + } + + if (vptr_map) { + BLI_ghash_free(vptr_map, NULL, NULL); + } + if (eptr_map) { + BLI_ghash_free(eptr_map, NULL, NULL); + } + if (fptr_map) { + BLI_ghash_free(fptr_map, NULL, NULL); + } } /** @@ -2297,168 +2355,202 @@ void BM_mesh_remap( * \note needed for re-sizing elements (adding/removing tool flags) * but could also be used for packing fragmented bmeshes. */ -void BM_mesh_rebuild( - BMesh *bm, const struct BMeshCreateParams *params, - BLI_mempool *vpool_dst, BLI_mempool *epool_dst, BLI_mempool *lpool_dst, BLI_mempool *fpool_dst) +void BM_mesh_rebuild(BMesh *bm, + const struct BMeshCreateParams *params, + BLI_mempool *vpool_dst, + BLI_mempool *epool_dst, + BLI_mempool *lpool_dst, + BLI_mempool *fpool_dst) { - const char remap = - (vpool_dst ? BM_VERT : 0) | - (epool_dst ? BM_EDGE : 0) | - (lpool_dst ? BM_LOOP : 0) | - (fpool_dst ? BM_FACE : 0); - - BMVert **vtable_dst = (remap & BM_VERT) ? MEM_mallocN(bm->totvert * sizeof(BMVert *), __func__) : NULL; - BMEdge **etable_dst = (remap & BM_EDGE) ? MEM_mallocN(bm->totedge * sizeof(BMEdge *), __func__) : NULL; - BMLoop **ltable_dst = (remap & BM_LOOP) ? MEM_mallocN(bm->totloop * sizeof(BMLoop *), __func__) : NULL; - BMFace **ftable_dst = (remap & BM_FACE) ? MEM_mallocN(bm->totface * sizeof(BMFace *), __func__) : NULL; - - const bool use_toolflags = params->use_toolflags; - - if (remap & BM_VERT) { - BMIter iter; - int index; - BMVert *v_src; - BM_ITER_MESH_INDEX (v_src, &iter, bm, BM_VERTS_OF_MESH, index) { - BMVert *v_dst = BLI_mempool_alloc(vpool_dst); - memcpy(v_dst, v_src, sizeof(BMVert)); - if (use_toolflags) { - ((BMVert_OFlag *)v_dst)->oflags = bm->vtoolflagpool ? BLI_mempool_calloc(bm->vtoolflagpool) : NULL; - } - - vtable_dst[index] = v_dst; - BM_elem_index_set(v_src, index); /* set_ok */ - } - } - - if (remap & BM_EDGE) { - BMIter iter; - int index; - BMEdge *e_src; - BM_ITER_MESH_INDEX (e_src, &iter, bm, BM_EDGES_OF_MESH, index) { - BMEdge *e_dst = BLI_mempool_alloc(epool_dst); - memcpy(e_dst, e_src, sizeof(BMEdge)); - if (use_toolflags) { - ((BMEdge_OFlag *)e_dst)->oflags = bm->etoolflagpool ? BLI_mempool_calloc(bm->etoolflagpool) : NULL; - } - - etable_dst[index] = e_dst; - BM_elem_index_set(e_src, index); /* set_ok */ - } - } - - if (remap & (BM_LOOP | BM_FACE)) { - BMIter iter; - int index, index_loop = 0; - BMFace *f_src; - BM_ITER_MESH_INDEX (f_src, &iter, bm, BM_FACES_OF_MESH, index) { - - if (remap & BM_FACE) { - BMFace *f_dst = BLI_mempool_alloc(fpool_dst); - memcpy(f_dst, f_src, sizeof(BMFace)); - if (use_toolflags) { - ((BMFace_OFlag *)f_dst)->oflags = bm->ftoolflagpool ? BLI_mempool_calloc(bm->ftoolflagpool) : NULL; - } - - ftable_dst[index] = f_dst; - BM_elem_index_set(f_src, index); /* set_ok */ - } - - /* handle loops */ - if (remap & BM_LOOP) { - BMLoop *l_iter_src, *l_first_src; - l_iter_src = l_first_src = BM_FACE_FIRST_LOOP((BMFace *)f_src); - do { - BMLoop *l_dst = BLI_mempool_alloc(lpool_dst); - memcpy(l_dst, l_iter_src, sizeof(BMLoop)); - ltable_dst[index_loop] = l_dst; - BM_elem_index_set(l_iter_src, index_loop++); /* set_ok */ - } while ((l_iter_src = l_iter_src->next) != l_first_src); - } - } - } + const char remap = (vpool_dst ? BM_VERT : 0) | (epool_dst ? BM_EDGE : 0) | + (lpool_dst ? BM_LOOP : 0) | (fpool_dst ? BM_FACE : 0); + + BMVert **vtable_dst = (remap & BM_VERT) ? MEM_mallocN(bm->totvert * sizeof(BMVert *), __func__) : + NULL; + BMEdge **etable_dst = (remap & BM_EDGE) ? MEM_mallocN(bm->totedge * sizeof(BMEdge *), __func__) : + NULL; + BMLoop **ltable_dst = (remap & BM_LOOP) ? MEM_mallocN(bm->totloop * sizeof(BMLoop *), __func__) : + NULL; + BMFace **ftable_dst = (remap & BM_FACE) ? MEM_mallocN(bm->totface * sizeof(BMFace *), __func__) : + NULL; + + const bool use_toolflags = params->use_toolflags; + + if (remap & BM_VERT) { + BMIter iter; + int index; + BMVert *v_src; + BM_ITER_MESH_INDEX (v_src, &iter, bm, BM_VERTS_OF_MESH, index) { + BMVert *v_dst = BLI_mempool_alloc(vpool_dst); + memcpy(v_dst, v_src, sizeof(BMVert)); + if (use_toolflags) { + ((BMVert_OFlag *)v_dst)->oflags = bm->vtoolflagpool ? + BLI_mempool_calloc(bm->vtoolflagpool) : + NULL; + } + + vtable_dst[index] = v_dst; + BM_elem_index_set(v_src, index); /* set_ok */ + } + } + + if (remap & BM_EDGE) { + BMIter iter; + int index; + BMEdge *e_src; + BM_ITER_MESH_INDEX (e_src, &iter, bm, BM_EDGES_OF_MESH, index) { + BMEdge *e_dst = BLI_mempool_alloc(epool_dst); + memcpy(e_dst, e_src, sizeof(BMEdge)); + if (use_toolflags) { + ((BMEdge_OFlag *)e_dst)->oflags = bm->etoolflagpool ? + BLI_mempool_calloc(bm->etoolflagpool) : + NULL; + } + + etable_dst[index] = e_dst; + BM_elem_index_set(e_src, index); /* set_ok */ + } + } + + if (remap & (BM_LOOP | BM_FACE)) { + BMIter iter; + int index, index_loop = 0; + BMFace *f_src; + BM_ITER_MESH_INDEX (f_src, &iter, bm, BM_FACES_OF_MESH, index) { + + if (remap & BM_FACE) { + BMFace *f_dst = BLI_mempool_alloc(fpool_dst); + memcpy(f_dst, f_src, sizeof(BMFace)); + if (use_toolflags) { + ((BMFace_OFlag *)f_dst)->oflags = bm->ftoolflagpool ? + BLI_mempool_calloc(bm->ftoolflagpool) : + NULL; + } + + ftable_dst[index] = f_dst; + BM_elem_index_set(f_src, index); /* set_ok */ + } + + /* handle loops */ + if (remap & BM_LOOP) { + BMLoop *l_iter_src, *l_first_src; + l_iter_src = l_first_src = BM_FACE_FIRST_LOOP((BMFace *)f_src); + do { + BMLoop *l_dst = BLI_mempool_alloc(lpool_dst); + memcpy(l_dst, l_iter_src, sizeof(BMLoop)); + ltable_dst[index_loop] = l_dst; + BM_elem_index_set(l_iter_src, index_loop++); /* set_ok */ + } while ((l_iter_src = l_iter_src->next) != l_first_src); + } + } + } #define MAP_VERT(ele) vtable_dst[BM_elem_index_get(ele)] #define MAP_EDGE(ele) etable_dst[BM_elem_index_get(ele)] #define MAP_LOOP(ele) ltable_dst[BM_elem_index_get(ele)] #define MAP_FACE(ele) ftable_dst[BM_elem_index_get(ele)] -#define REMAP_VERT(ele) { if (remap & BM_VERT) { ele = MAP_VERT(ele); }} ((void)0) -#define REMAP_EDGE(ele) { if (remap & BM_EDGE) { ele = MAP_EDGE(ele); }} ((void)0) -#define REMAP_LOOP(ele) { if (remap & BM_LOOP) { ele = MAP_LOOP(ele); }} ((void)0) -#define REMAP_FACE(ele) { if (remap & BM_FACE) { ele = MAP_FACE(ele); }} ((void)0) - - /* verts */ - { - for (int i = 0; i < bm->totvert; i++) { - BMVert *v = vtable_dst[i]; - if (v->e) { - REMAP_EDGE(v->e); - } - } - } - - /* edges */ - { - for (int i = 0; i < bm->totedge; i++) { - BMEdge *e = etable_dst[i]; - REMAP_VERT(e->v1); - REMAP_VERT(e->v2); - REMAP_EDGE(e->v1_disk_link.next); - REMAP_EDGE(e->v1_disk_link.prev); - REMAP_EDGE(e->v2_disk_link.next); - REMAP_EDGE(e->v2_disk_link.prev); - if (e->l) { - REMAP_LOOP(e->l); - } - } - } - - /* faces */ - { - for (int i = 0; i < bm->totface; i++) { - BMFace *f = ftable_dst[i]; - REMAP_LOOP(f->l_first); - - { - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)f); - do { - REMAP_VERT(l_iter->v); - REMAP_EDGE(l_iter->e); - REMAP_FACE(l_iter->f); - - REMAP_LOOP(l_iter->radial_next); - REMAP_LOOP(l_iter->radial_prev); - REMAP_LOOP(l_iter->next); - REMAP_LOOP(l_iter->prev); - } while ((l_iter = l_iter->next) != l_first); - } - } - } - - for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) { - switch (ese->htype) { - case BM_VERT: - if (remap & BM_VERT) { - ese->ele = (BMElem *)MAP_VERT(ese->ele); - } - break; - case BM_EDGE: - if (remap & BM_EDGE) { - ese->ele = (BMElem *)MAP_EDGE(ese->ele); - } - break; - case BM_FACE: - if (remap & BM_FACE) { - ese->ele = (BMElem *)MAP_FACE(ese->ele); - } - break; - } - } - - if (bm->act_face) { - REMAP_FACE(bm->act_face); - } +#define REMAP_VERT(ele) \ + { \ + if (remap & BM_VERT) { \ + ele = MAP_VERT(ele); \ + } \ + } \ + ((void)0) +#define REMAP_EDGE(ele) \ + { \ + if (remap & BM_EDGE) { \ + ele = MAP_EDGE(ele); \ + } \ + } \ + ((void)0) +#define REMAP_LOOP(ele) \ + { \ + if (remap & BM_LOOP) { \ + ele = MAP_LOOP(ele); \ + } \ + } \ + ((void)0) +#define REMAP_FACE(ele) \ + { \ + if (remap & BM_FACE) { \ + ele = MAP_FACE(ele); \ + } \ + } \ + ((void)0) + + /* verts */ + { + for (int i = 0; i < bm->totvert; i++) { + BMVert *v = vtable_dst[i]; + if (v->e) { + REMAP_EDGE(v->e); + } + } + } + + /* edges */ + { + for (int i = 0; i < bm->totedge; i++) { + BMEdge *e = etable_dst[i]; + REMAP_VERT(e->v1); + REMAP_VERT(e->v2); + REMAP_EDGE(e->v1_disk_link.next); + REMAP_EDGE(e->v1_disk_link.prev); + REMAP_EDGE(e->v2_disk_link.next); + REMAP_EDGE(e->v2_disk_link.prev); + if (e->l) { + REMAP_LOOP(e->l); + } + } + } + + /* faces */ + { + for (int i = 0; i < bm->totface; i++) { + BMFace *f = ftable_dst[i]; + REMAP_LOOP(f->l_first); + + { + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)f); + do { + REMAP_VERT(l_iter->v); + REMAP_EDGE(l_iter->e); + REMAP_FACE(l_iter->f); + + REMAP_LOOP(l_iter->radial_next); + REMAP_LOOP(l_iter->radial_prev); + REMAP_LOOP(l_iter->next); + REMAP_LOOP(l_iter->prev); + } while ((l_iter = l_iter->next) != l_first); + } + } + } + + for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) { + switch (ese->htype) { + case BM_VERT: + if (remap & BM_VERT) { + ese->ele = (BMElem *)MAP_VERT(ese->ele); + } + break; + case BM_EDGE: + if (remap & BM_EDGE) { + ese->ele = (BMElem *)MAP_EDGE(ese->ele); + } + break; + case BM_FACE: + if (remap & BM_FACE) { + ese->ele = (BMElem *)MAP_FACE(ese->ele); + } + break; + } + } + + if (bm->act_face) { + REMAP_FACE(bm->act_face); + } #undef MAP_VERT #undef MAP_EDGE @@ -2470,47 +2562,47 @@ void BM_mesh_rebuild( #undef REMAP_LOOP #undef REMAP_EDGE - /* Cleanup, re-use local tables if the current mesh had tables allocated. - * could use irrespective but it may use more memory then the caller wants (and not be needed). */ - if (remap & BM_VERT) { - if (bm->vtable) { - SWAP(BMVert **, vtable_dst, bm->vtable); - bm->vtable_tot = bm->totvert; - bm->elem_table_dirty &= ~BM_VERT; - } - MEM_freeN(vtable_dst); - BLI_mempool_destroy(bm->vpool); - bm->vpool = vpool_dst; - } - - if (remap & BM_EDGE) { - if (bm->etable) { - SWAP(BMEdge **, etable_dst, bm->etable); - bm->etable_tot = bm->totedge; - bm->elem_table_dirty &= ~BM_EDGE; - } - MEM_freeN(etable_dst); - BLI_mempool_destroy(bm->epool); - bm->epool = epool_dst; - } - - if (remap & BM_LOOP) { - /* no loop table */ - MEM_freeN(ltable_dst); - BLI_mempool_destroy(bm->lpool); - bm->lpool = lpool_dst; - } - - if (remap & BM_FACE) { - if (bm->ftable) { - SWAP(BMFace **, ftable_dst, bm->ftable); - bm->ftable_tot = bm->totface; - bm->elem_table_dirty &= ~BM_FACE; - } - MEM_freeN(ftable_dst); - BLI_mempool_destroy(bm->fpool); - bm->fpool = fpool_dst; - } + /* Cleanup, re-use local tables if the current mesh had tables allocated. + * could use irrespective but it may use more memory then the caller wants (and not be needed). */ + if (remap & BM_VERT) { + if (bm->vtable) { + SWAP(BMVert **, vtable_dst, bm->vtable); + bm->vtable_tot = bm->totvert; + bm->elem_table_dirty &= ~BM_VERT; + } + MEM_freeN(vtable_dst); + BLI_mempool_destroy(bm->vpool); + bm->vpool = vpool_dst; + } + + if (remap & BM_EDGE) { + if (bm->etable) { + SWAP(BMEdge **, etable_dst, bm->etable); + bm->etable_tot = bm->totedge; + bm->elem_table_dirty &= ~BM_EDGE; + } + MEM_freeN(etable_dst); + BLI_mempool_destroy(bm->epool); + bm->epool = epool_dst; + } + + if (remap & BM_LOOP) { + /* no loop table */ + MEM_freeN(ltable_dst); + BLI_mempool_destroy(bm->lpool); + bm->lpool = lpool_dst; + } + + if (remap & BM_FACE) { + if (bm->ftable) { + SWAP(BMFace **, ftable_dst, bm->ftable); + bm->ftable_tot = bm->totface; + bm->elem_table_dirty &= ~BM_FACE; + } + MEM_freeN(ftable_dst); + BLI_mempool_destroy(bm->fpool); + bm->fpool = fpool_dst; + } } /** @@ -2518,34 +2610,36 @@ void BM_mesh_rebuild( */ void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags) { - if (bm->use_toolflags == use_toolflags) { - return; - } - - const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm); - - BLI_mempool *vpool_dst = NULL; - BLI_mempool *epool_dst = NULL; - BLI_mempool *fpool_dst = NULL; - - bm_mempool_init_ex( - &allocsize, use_toolflags, - &vpool_dst, &epool_dst, NULL, &fpool_dst); - - if (use_toolflags == false) { - BLI_mempool_destroy(bm->vtoolflagpool); - BLI_mempool_destroy(bm->etoolflagpool); - BLI_mempool_destroy(bm->ftoolflagpool); - - bm->vtoolflagpool = NULL; - bm->etoolflagpool = NULL; - bm->ftoolflagpool = NULL; - } - - BM_mesh_rebuild( - bm, - &((struct BMeshCreateParams){.use_toolflags = use_toolflags,}), - vpool_dst, epool_dst, NULL, fpool_dst); - - bm->use_toolflags = use_toolflags; + if (bm->use_toolflags == use_toolflags) { + return; + } + + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm); + + BLI_mempool *vpool_dst = NULL; + BLI_mempool *epool_dst = NULL; + BLI_mempool *fpool_dst = NULL; + + bm_mempool_init_ex(&allocsize, use_toolflags, &vpool_dst, &epool_dst, NULL, &fpool_dst); + + if (use_toolflags == false) { + BLI_mempool_destroy(bm->vtoolflagpool); + BLI_mempool_destroy(bm->etoolflagpool); + BLI_mempool_destroy(bm->ftoolflagpool); + + bm->vtoolflagpool = NULL; + bm->etoolflagpool = NULL; + bm->ftoolflagpool = NULL; + } + + BM_mesh_rebuild(bm, + &((struct BMeshCreateParams){ + .use_toolflags = use_toolflags, + }), + vpool_dst, + epool_dst, + NULL, + fpool_dst); + + bm->use_toolflags = use_toolflags; } diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 6f340411b00..d0cf50a7894 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -25,31 +25,39 @@ struct BMAllocTemplate; struct BMLoopNorEditDataArray; struct MLoopNorSpaceArray; -void BM_mesh_elem_toolflags_ensure(BMesh *bm); -void BM_mesh_elem_toolflags_clear(BMesh *bm); +void BM_mesh_elem_toolflags_ensure(BMesh *bm); +void BM_mesh_elem_toolflags_clear(BMesh *bm); struct BMeshCreateParams { - uint use_toolflags : 1; + uint use_toolflags : 1; }; -BMesh *BM_mesh_create( - const struct BMAllocTemplate *allocsize, - const struct BMeshCreateParams *params); +BMesh *BM_mesh_create(const struct BMAllocTemplate *allocsize, + const struct BMeshCreateParams *params); -void BM_mesh_free(BMesh *bm); -void BM_mesh_data_free(BMesh *bm); -void BM_mesh_clear(BMesh *bm); +void BM_mesh_free(BMesh *bm); +void BM_mesh_data_free(BMesh *bm); +void BM_mesh_clear(BMesh *bm); void BM_mesh_normals_update(BMesh *bm); -void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (*vcos)[3], float (*vnos)[3]); -void BM_loops_calc_normal_vcos( - BMesh *bm, const float(*vcos)[3], const float(*vnos)[3], const float(*pnos)[3], - const bool use_split_normals, const float split_angle, float(*r_lnos)[3], - struct MLoopNorSpaceArray *r_lnors_spacearr, short(*clnors_data)[2], - const int cd_loop_clnors_offset, const bool do_rebuild); +void BM_verts_calc_normal_vcos(BMesh *bm, + const float (*fnos)[3], + const float (*vcos)[3], + float (*vnos)[3]); +void BM_loops_calc_normal_vcos(BMesh *bm, + const float (*vcos)[3], + const float (*vnos)[3], + const float (*pnos)[3], + const bool use_split_normals, + const float split_angle, + float (*r_lnos)[3], + struct MLoopNorSpaceArray *r_lnors_spacearr, + short (*clnors_data)[2], + const int cd_loop_clnors_offset, + const bool do_rebuild); bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr); -void BM_lnorspacearr_store(BMesh *bm, float(*r_lnors)[3]); +void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3]); void BM_lnorspace_invalidate(BMesh *bm, const bool do_invalidate_all); void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor); void BM_lnorspace_update(BMesh *bm); @@ -63,7 +71,6 @@ struct BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm); void BM_loop_normal_editdata_array_free(struct BMLoopNorEditDataArray *lnors_ed_arr); int BM_total_loop_select(BMesh *bm); - void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle); void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag); @@ -72,8 +79,7 @@ void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag); void BM_mesh_elem_index_ensure_ex(BMesh *bm, const char htype, int elem_offset[4]); void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag); void BM_mesh_elem_index_validate( - BMesh *bm, const char *location, const char *func, - const char *msg_a, const char *msg_b); + BMesh *bm, const char *location, const char *func, const char *msg_a, const char *msg_b); void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags); @@ -81,27 +87,27 @@ void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags); bool BM_mesh_elem_table_check(BMesh *bm); #endif -void BM_mesh_elem_table_ensure(BMesh *bm, const char htype); -void BM_mesh_elem_table_init(BMesh *bm, const char htype); -void BM_mesh_elem_table_free(BMesh *bm, const char htype); +void BM_mesh_elem_table_ensure(BMesh *bm, const char htype); +void BM_mesh_elem_table_init(BMesh *bm, const char htype); +void BM_mesh_elem_table_free(BMesh *bm, const char htype); BLI_INLINE BMVert *BM_vert_at_index(BMesh *bm, const int index) { - BLI_assert((index >= 0) && (index < bm->totvert)); - BLI_assert((bm->elem_table_dirty & BM_VERT) == 0); - return bm->vtable[index]; + BLI_assert((index >= 0) && (index < bm->totvert)); + BLI_assert((bm->elem_table_dirty & BM_VERT) == 0); + return bm->vtable[index]; } BLI_INLINE BMEdge *BM_edge_at_index(BMesh *bm, const int index) { - BLI_assert((index >= 0) && (index < bm->totedge)); - BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0); - return bm->etable[index]; + BLI_assert((index >= 0) && (index < bm->totedge)); + BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0); + return bm->etable[index]; } BLI_INLINE BMFace *BM_face_at_index(BMesh *bm, const int index) { - BLI_assert((index >= 0) && (index < bm->totface)); - BLI_assert((bm->elem_table_dirty & BM_FACE) == 0); - return bm->ftable[index]; + BLI_assert((index >= 0) && (index < bm->totface)); + BLI_assert((bm->elem_table_dirty & BM_FACE) == 0); + return bm->ftable[index]; } BMVert *BM_vert_at_index_find(BMesh *bm, const int index); @@ -114,43 +120,42 @@ BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index); // XXX -int BM_mesh_elem_count(BMesh *bm, const char htype); +int BM_mesh_elem_count(BMesh *bm, const char htype); -void BM_mesh_remap( - BMesh *bm, - const uint *vert_idx, - const uint *edge_idx, - const uint *face_idx); +void BM_mesh_remap(BMesh *bm, const uint *vert_idx, const uint *edge_idx, const uint *face_idx); -void BM_mesh_rebuild( - BMesh *bm, const struct BMeshCreateParams *params, - struct BLI_mempool *vpool, struct BLI_mempool *epool, struct BLI_mempool *lpool, struct BLI_mempool *fpool); +void BM_mesh_rebuild(BMesh *bm, + const struct BMeshCreateParams *params, + struct BLI_mempool *vpool, + struct BLI_mempool *epool, + struct BLI_mempool *lpool, + struct BLI_mempool *fpool); typedef struct BMAllocTemplate { - int totvert, totedge, totloop, totface; + int totvert, totedge, totloop, totface; } BMAllocTemplate; extern const BMAllocTemplate bm_mesh_allocsize_default; extern const BMAllocTemplate bm_mesh_chunksize_default; -#define BMALLOC_TEMPLATE_FROM_BM(bm) { (CHECK_TYPE_INLINE(bm, BMesh *), \ - (bm)->totvert), (bm)->totedge, (bm)->totloop, (bm)->totface} - -#define _VA_BMALLOC_TEMPLATE_FROM_ME_1(me) { \ - (CHECK_TYPE_INLINE(me, Mesh *), \ - (me)->totvert), \ - (me)->totedge, \ - (me)->totloop, \ - (me)->totpoly, \ -} -#define _VA_BMALLOC_TEMPLATE_FROM_ME_2(me_a, me_b) { \ - (CHECK_TYPE_INLINE(me_a, Mesh *), \ - CHECK_TYPE_INLINE(me_b, Mesh *), \ - (me_a)->totvert + (me_b)->totvert), \ - (me_a)->totedge + (me_b)->totedge, \ - (me_a)->totloop + (me_b)->totloop, \ - (me_a)->totpoly + (me_b)->totpoly, \ -} -#define BMALLOC_TEMPLATE_FROM_ME(...) VA_NARGS_CALL_OVERLOAD(_VA_BMALLOC_TEMPLATE_FROM_ME_, __VA_ARGS__) +#define BMALLOC_TEMPLATE_FROM_BM(bm) \ + { \ + (CHECK_TYPE_INLINE(bm, BMesh *), (bm)->totvert), (bm)->totedge, (bm)->totloop, (bm)->totface \ + } + +#define _VA_BMALLOC_TEMPLATE_FROM_ME_1(me) \ + { \ + (CHECK_TYPE_INLINE(me, Mesh *), (me)->totvert), (me)->totedge, (me)->totloop, (me)->totpoly, \ + } +#define _VA_BMALLOC_TEMPLATE_FROM_ME_2(me_a, me_b) \ + { \ + (CHECK_TYPE_INLINE(me_a, Mesh *), \ + CHECK_TYPE_INLINE(me_b, Mesh *), \ + (me_a)->totvert + (me_b)->totvert), \ + (me_a)->totedge + (me_b)->totedge, (me_a)->totloop + (me_b)->totloop, \ + (me_a)->totpoly + (me_b)->totpoly, \ + } +#define BMALLOC_TEMPLATE_FROM_ME(...) \ + VA_NARGS_CALL_OVERLOAD(_VA_BMALLOC_TEMPLATE_FROM_ME_, __VA_ARGS__) #endif /* __BMESH_MESH_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 66cd3a0b30c..f2db451888a 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -87,87 +87,85 @@ void BM_mesh_cd_flag_ensure(BMesh *bm, Mesh *mesh, const char cd_flag) { - const char cd_flag_all = BM_mesh_cd_flag_from_bmesh(bm) | cd_flag; - BM_mesh_cd_flag_apply(bm, cd_flag_all); - if (mesh) { - mesh->cd_flag = cd_flag_all; - } + const char cd_flag_all = BM_mesh_cd_flag_from_bmesh(bm) | cd_flag; + BM_mesh_cd_flag_apply(bm, cd_flag_all); + if (mesh) { + mesh->cd_flag = cd_flag_all; + } } void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag) { - /* CustomData_bmesh_init_pool() must run first */ - BLI_assert(bm->vdata.totlayer == 0 || bm->vdata.pool != NULL); - BLI_assert(bm->edata.totlayer == 0 || bm->edata.pool != NULL); - BLI_assert(bm->pdata.totlayer == 0 || bm->pdata.pool != NULL); - - if (cd_flag & ME_CDFLAG_VERT_BWEIGHT) { - if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { - BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT); - } - } - else { - if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { - BM_data_layer_free(bm, &bm->vdata, CD_BWEIGHT); - } - } - - if (cd_flag & ME_CDFLAG_EDGE_BWEIGHT) { - if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { - BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT); - } - } - else { - if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { - BM_data_layer_free(bm, &bm->edata, CD_BWEIGHT); - } - } - - if (cd_flag & ME_CDFLAG_EDGE_CREASE) { - if (!CustomData_has_layer(&bm->edata, CD_CREASE)) { - BM_data_layer_add(bm, &bm->edata, CD_CREASE); - } - } - else { - if (CustomData_has_layer(&bm->edata, CD_CREASE)) { - BM_data_layer_free(bm, &bm->edata, CD_CREASE); - } - } + /* CustomData_bmesh_init_pool() must run first */ + BLI_assert(bm->vdata.totlayer == 0 || bm->vdata.pool != NULL); + BLI_assert(bm->edata.totlayer == 0 || bm->edata.pool != NULL); + BLI_assert(bm->pdata.totlayer == 0 || bm->pdata.pool != NULL); + + if (cd_flag & ME_CDFLAG_VERT_BWEIGHT) { + if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT); + } + } + else { + if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + BM_data_layer_free(bm, &bm->vdata, CD_BWEIGHT); + } + } + + if (cd_flag & ME_CDFLAG_EDGE_BWEIGHT) { + if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT); + } + } + else { + if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + BM_data_layer_free(bm, &bm->edata, CD_BWEIGHT); + } + } + + if (cd_flag & ME_CDFLAG_EDGE_CREASE) { + if (!CustomData_has_layer(&bm->edata, CD_CREASE)) { + BM_data_layer_add(bm, &bm->edata, CD_CREASE); + } + } + else { + if (CustomData_has_layer(&bm->edata, CD_CREASE)) { + BM_data_layer_free(bm, &bm->edata, CD_CREASE); + } + } } char BM_mesh_cd_flag_from_bmesh(BMesh *bm) { - char cd_flag = 0; - if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { - cd_flag |= ME_CDFLAG_VERT_BWEIGHT; - } - if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { - cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; - } - if (CustomData_has_layer(&bm->edata, CD_CREASE)) { - cd_flag |= ME_CDFLAG_EDGE_CREASE; - } - return cd_flag; + char cd_flag = 0; + if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + cd_flag |= ME_CDFLAG_VERT_BWEIGHT; + } + if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; + } + if (CustomData_has_layer(&bm->edata, CD_CREASE)) { + cd_flag |= ME_CDFLAG_EDGE_CREASE; + } + return cd_flag; } /* Static function for alloc (duplicate in modifiers_bmesh.c) */ static BMFace *bm_face_create_from_mpoly( - MPoly *mp, MLoop *ml, - BMesh *bm, BMVert **vtable, BMEdge **etable) + MPoly *mp, MLoop *ml, BMesh *bm, BMVert **vtable, BMEdge **etable) { - BMVert **verts = BLI_array_alloca(verts, mp->totloop); - BMEdge **edges = BLI_array_alloca(edges, mp->totloop); - int j; + BMVert **verts = BLI_array_alloca(verts, mp->totloop); + BMEdge **edges = BLI_array_alloca(edges, mp->totloop); + int j; - for (j = 0; j < mp->totloop; j++, ml++) { - verts[j] = vtable[ml->v]; - edges[j] = etable[ml->e]; - } + for (j = 0; j < mp->totloop; j++, ml++) { + verts[j] = vtable[ml->v]; + edges[j] = etable[ml->e]; + } - return BM_face_create(bm, verts, edges, mp->totloop, NULL, BM_CREATE_SKIP_CD); + return BM_face_create(bm, verts, edges, mp->totloop, NULL, BM_CREATE_SKIP_CD); } - /** * \brief Mesh -> BMesh * \param bm: The mesh to write into, while this is typically a newly created BMesh, @@ -178,340 +176,338 @@ static BMFace *bm_face_create_from_mpoly( * * \warning This function doesn't calculate face normals. */ -void BM_mesh_bm_from_me( - BMesh *bm, const Mesh *me, - const struct BMeshFromMeshParams *params) +void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params) { - const bool is_new = - !(bm->totvert || - (bm->vdata.totlayer || bm->edata.totlayer || bm->pdata.totlayer || bm->ldata.totlayer)); - MVert *mvert; - MEdge *medge; - MLoop *mloop; - MPoly *mp; - KeyBlock *actkey, *block; - BMVert *v, **vtable = NULL; - BMEdge *e, **etable = NULL; - BMFace *f, **ftable = NULL; - float (*keyco)[3] = NULL; - int totloops, i; - CustomData_MeshMasks mask = CD_MASK_BMESH; - CustomData_MeshMasks_update(&mask, ¶ms->cd_mask_extra); - - if (!me || !me->totvert) { - if (me && is_new) { /*no verts? still copy customdata layout*/ - CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_ASSIGN, 0); - CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_ASSIGN, 0); - CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_ASSIGN, 0); - CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_ASSIGN, 0); - - CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT); - CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE); - CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP); - CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); - } - return; /* sanity check */ - } - - if (is_new) { - CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, 0); - CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_CALLOC, 0); - CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, 0); - CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, 0); - } - else { - CustomData_bmesh_merge(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, bm, BM_VERT); - CustomData_bmesh_merge(&me->edata, &bm->edata, mask.emask, CD_CALLOC, bm, BM_EDGE); - CustomData_bmesh_merge(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, bm, BM_LOOP); - CustomData_bmesh_merge(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, bm, BM_FACE); - } - - /* -------------------------------------------------------------------- */ - /* Shape Key */ - int tot_shape_keys = me->key ? BLI_listbase_count(&me->key->block) : 0; - if (is_new == false) { - tot_shape_keys = min_ii(tot_shape_keys, CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY)); - } - const float (**shape_key_table)[3] = tot_shape_keys ? BLI_array_alloca(shape_key_table, tot_shape_keys) : NULL; - - if ((params->active_shapekey != 0) && (me->key != NULL)) { - actkey = BLI_findlink(&me->key->block, params->active_shapekey - 1); - } - else { - actkey = NULL; - } - - if (is_new) { - if (tot_shape_keys || params->add_key_index) { - CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0); - } - } - - if (tot_shape_keys) { - if (is_new) { - /* check if we need to generate unique ids for the shapekeys. - * this also exists in the file reading code, but is here for - * a sanity check */ - if (!me->key->uidgen) { - fprintf(stderr, - "%s had to generate shape key uid's in a situation we shouldn't need to! " - "(bmesh internal error)\n", - __func__); - - me->key->uidgen = 1; - for (block = me->key->block.first; block; block = block->next) { - block->uid = me->key->uidgen++; - } - } - } - - if (actkey && actkey->totelem == me->totvert) { - keyco = params->use_shapekey ? actkey->data : NULL; - if (is_new) { - bm->shapenr = params->active_shapekey; - } - } - - for (i = 0, block = me->key->block.first; i < tot_shape_keys; block = block->next, i++) { - if (is_new) { - CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY, - CD_ASSIGN, NULL, 0, block->name); - int j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i); - bm->vdata.layers[j].uid = block->uid; - } - shape_key_table[i] = (const float (*)[3])block->data; - } - } - - if (is_new) { - CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT); - CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE); - CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP); - CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); - - BM_mesh_cd_flag_apply(bm, me->cd_flag); - } - - const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); - const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); - const int cd_shape_key_offset = me->key ? CustomData_get_offset(&bm->vdata, CD_SHAPEKEY) : -1; - const int cd_shape_keyindex_offset = is_new && (tot_shape_keys || params->add_key_index) ? - CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) : -1; - - vtable = MEM_mallocN(sizeof(BMVert **) * me->totvert, __func__); - - for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { - v = vtable[i] = BM_vert_create(bm, keyco ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD); - BM_elem_index_set(v, i); /* set_ok */ - - /* transfer flag */ - v->head.hflag = BM_vert_flag_from_mflag(mvert->flag & ~SELECT); - - /* this is necessary for selection counts to work properly */ - if (mvert->flag & SELECT) { - BM_vert_select_set(bm, v, true); - } - - normal_short_to_float_v3(v->no, mvert->no); - - /* Copy Custom Data */ - CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true); - - if (cd_vert_bweight_offset != -1) { - BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f); - } - - /* set shape key original index */ - if (cd_shape_keyindex_offset != -1) { - BM_ELEM_CD_SET_INT(v, cd_shape_keyindex_offset, i); - } - - /* set shapekey data */ - if (tot_shape_keys) { - float (*co_dst)[3] = BM_ELEM_CD_GET_VOID_P(v, cd_shape_key_offset); - for (int j = 0; j < tot_shape_keys; j++, co_dst++) { - copy_v3_v3(*co_dst, shape_key_table[j][i]); - } - } - } - if (is_new) { - bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */ - } - - etable = MEM_mallocN(sizeof(BMEdge **) * me->totedge, __func__); - - medge = me->medge; - for (i = 0; i < me->totedge; i++, medge++) { - e = etable[i] = BM_edge_create(bm, vtable[medge->v1], vtable[medge->v2], NULL, BM_CREATE_SKIP_CD); - BM_elem_index_set(e, i); /* set_ok */ - - /* transfer flags */ - e->head.hflag = BM_edge_flag_from_mflag(medge->flag & ~SELECT); - - /* this is necessary for selection counts to work properly */ - if (medge->flag & SELECT) { - BM_edge_select_set(bm, e, true); - } - - /* Copy Custom Data */ - CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true); - - if (cd_edge_bweight_offset != -1) { - BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)medge->bweight / 255.0f); - } - if (cd_edge_crease_offset != -1) { - BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)medge->crease / 255.0f); - } - - } - if (is_new) { - bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */ - } - - /* only needed for selection. */ - if (me->mselect && me->totselect != 0) { - ftable = MEM_mallocN(sizeof(BMFace **) * me->totpoly, __func__); - } - - mloop = me->mloop; - mp = me->mpoly; - for (i = 0, totloops = 0; i < me->totpoly; i++, mp++) { - BMLoop *l_iter; - BMLoop *l_first; - - f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart, - bm, vtable, etable); - if (ftable != NULL) { - ftable[i] = f; - } - - if (UNLIKELY(f == NULL)) { - printf("%s: Warning! Bad face in mesh" - " \"%s\" at index %d!, skipping\n", - __func__, me->id.name + 2, i); - continue; - } - - /* don't use 'i' since we may have skipped the face */ - BM_elem_index_set(f, bm->totface - 1); /* set_ok */ - - /* transfer flag */ - f->head.hflag = BM_face_flag_from_mflag(mp->flag & ~ME_FACE_SEL); - - /* this is necessary for selection counts to work properly */ - if (mp->flag & ME_FACE_SEL) { - BM_face_select_set(bm, f, true); - } - - f->mat_nr = mp->mat_nr; - if (i == me->act_face) { - bm->act_face = f; - } - - int j = mp->loopstart; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - /* don't use 'j' since we may have skipped some faces, hence some loops. */ - BM_elem_index_set(l_iter, totloops++); /* set_ok */ - - /* Save index of correspsonding MLoop */ - CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true); - } while ((l_iter = l_iter->next) != l_first); - - /* Copy Custom Data */ - CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true); - - if (params->calc_face_normal) { - BM_face_normal_update(f); - } - } - if (is_new) { - bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* added in order, clear dirty flag */ - } - - /* -------------------------------------------------------------------- */ - /* MSelect clears the array elements (avoid adding multiple times). - * - * Take care to keep this last and not use (v/e/ftable) after this. - */ - - if (me->mselect && me->totselect != 0) { - MSelect *msel; - for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) { - BMElem **ele_p; - switch (msel->type) { - case ME_VSEL: - ele_p = (BMElem **)&vtable[msel->index]; - break; - case ME_ESEL: - ele_p = (BMElem **)&etable[msel->index]; - break; - case ME_FSEL: - ele_p = (BMElem **)&ftable[msel->index]; - break; - default: - continue; - } - - if (*ele_p != NULL) { - BM_select_history_store_notest(bm, *ele_p); - *ele_p = NULL; - } - } - } - else { - BM_select_history_clear(bm); - } - - MEM_freeN(vtable); - MEM_freeN(etable); - if (ftable) { - MEM_freeN(ftable); - } + const bool is_new = !(bm->totvert || (bm->vdata.totlayer || bm->edata.totlayer || + bm->pdata.totlayer || bm->ldata.totlayer)); + MVert *mvert; + MEdge *medge; + MLoop *mloop; + MPoly *mp; + KeyBlock *actkey, *block; + BMVert *v, **vtable = NULL; + BMEdge *e, **etable = NULL; + BMFace *f, **ftable = NULL; + float(*keyco)[3] = NULL; + int totloops, i; + CustomData_MeshMasks mask = CD_MASK_BMESH; + CustomData_MeshMasks_update(&mask, ¶ms->cd_mask_extra); + + if (!me || !me->totvert) { + if (me && is_new) { /*no verts? still copy customdata layout*/ + CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_ASSIGN, 0); + CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_ASSIGN, 0); + CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_ASSIGN, 0); + CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_ASSIGN, 0); + + CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT); + CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE); + CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP); + CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); + } + return; /* sanity check */ + } + + if (is_new) { + CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, 0); + CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_CALLOC, 0); + CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, 0); + CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, 0); + } + else { + CustomData_bmesh_merge(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, bm, BM_VERT); + CustomData_bmesh_merge(&me->edata, &bm->edata, mask.emask, CD_CALLOC, bm, BM_EDGE); + CustomData_bmesh_merge(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, bm, BM_LOOP); + CustomData_bmesh_merge(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, bm, BM_FACE); + } + + /* -------------------------------------------------------------------- */ + /* Shape Key */ + int tot_shape_keys = me->key ? BLI_listbase_count(&me->key->block) : 0; + if (is_new == false) { + tot_shape_keys = min_ii(tot_shape_keys, CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY)); + } + const float(**shape_key_table)[3] = tot_shape_keys ? + BLI_array_alloca(shape_key_table, tot_shape_keys) : + NULL; + + if ((params->active_shapekey != 0) && (me->key != NULL)) { + actkey = BLI_findlink(&me->key->block, params->active_shapekey - 1); + } + else { + actkey = NULL; + } + + if (is_new) { + if (tot_shape_keys || params->add_key_index) { + CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0); + } + } + + if (tot_shape_keys) { + if (is_new) { + /* check if we need to generate unique ids for the shapekeys. + * this also exists in the file reading code, but is here for + * a sanity check */ + if (!me->key->uidgen) { + fprintf(stderr, + "%s had to generate shape key uid's in a situation we shouldn't need to! " + "(bmesh internal error)\n", + __func__); + + me->key->uidgen = 1; + for (block = me->key->block.first; block; block = block->next) { + block->uid = me->key->uidgen++; + } + } + } + + if (actkey && actkey->totelem == me->totvert) { + keyco = params->use_shapekey ? actkey->data : NULL; + if (is_new) { + bm->shapenr = params->active_shapekey; + } + } + + for (i = 0, block = me->key->block.first; i < tot_shape_keys; block = block->next, i++) { + if (is_new) { + CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY, CD_ASSIGN, NULL, 0, block->name); + int j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i); + bm->vdata.layers[j].uid = block->uid; + } + shape_key_table[i] = (const float(*)[3])block->data; + } + } + + if (is_new) { + CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT); + CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE); + CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP); + CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); + + BM_mesh_cd_flag_apply(bm, me->cd_flag); + } + + const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); + const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); + const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); + const int cd_shape_key_offset = me->key ? CustomData_get_offset(&bm->vdata, CD_SHAPEKEY) : -1; + const int cd_shape_keyindex_offset = is_new && (tot_shape_keys || params->add_key_index) ? + CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) : + -1; + + vtable = MEM_mallocN(sizeof(BMVert **) * me->totvert, __func__); + + for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { + v = vtable[i] = BM_vert_create(bm, keyco ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD); + BM_elem_index_set(v, i); /* set_ok */ + + /* transfer flag */ + v->head.hflag = BM_vert_flag_from_mflag(mvert->flag & ~SELECT); + + /* this is necessary for selection counts to work properly */ + if (mvert->flag & SELECT) { + BM_vert_select_set(bm, v, true); + } + + normal_short_to_float_v3(v->no, mvert->no); + + /* Copy Custom Data */ + CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true); + + if (cd_vert_bweight_offset != -1) { + BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f); + } + + /* set shape key original index */ + if (cd_shape_keyindex_offset != -1) { + BM_ELEM_CD_SET_INT(v, cd_shape_keyindex_offset, i); + } + + /* set shapekey data */ + if (tot_shape_keys) { + float(*co_dst)[3] = BM_ELEM_CD_GET_VOID_P(v, cd_shape_key_offset); + for (int j = 0; j < tot_shape_keys; j++, co_dst++) { + copy_v3_v3(*co_dst, shape_key_table[j][i]); + } + } + } + if (is_new) { + bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */ + } + + etable = MEM_mallocN(sizeof(BMEdge **) * me->totedge, __func__); + + medge = me->medge; + for (i = 0; i < me->totedge; i++, medge++) { + e = etable[i] = BM_edge_create( + bm, vtable[medge->v1], vtable[medge->v2], NULL, BM_CREATE_SKIP_CD); + BM_elem_index_set(e, i); /* set_ok */ + + /* transfer flags */ + e->head.hflag = BM_edge_flag_from_mflag(medge->flag & ~SELECT); + + /* this is necessary for selection counts to work properly */ + if (medge->flag & SELECT) { + BM_edge_select_set(bm, e, true); + } + + /* Copy Custom Data */ + CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true); + + if (cd_edge_bweight_offset != -1) { + BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)medge->bweight / 255.0f); + } + if (cd_edge_crease_offset != -1) { + BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)medge->crease / 255.0f); + } + } + if (is_new) { + bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */ + } + + /* only needed for selection. */ + if (me->mselect && me->totselect != 0) { + ftable = MEM_mallocN(sizeof(BMFace **) * me->totpoly, __func__); + } + + mloop = me->mloop; + mp = me->mpoly; + for (i = 0, totloops = 0; i < me->totpoly; i++, mp++) { + BMLoop *l_iter; + BMLoop *l_first; + + f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart, bm, vtable, etable); + if (ftable != NULL) { + ftable[i] = f; + } + + if (UNLIKELY(f == NULL)) { + printf( + "%s: Warning! Bad face in mesh" + " \"%s\" at index %d!, skipping\n", + __func__, + me->id.name + 2, + i); + continue; + } + + /* don't use 'i' since we may have skipped the face */ + BM_elem_index_set(f, bm->totface - 1); /* set_ok */ + + /* transfer flag */ + f->head.hflag = BM_face_flag_from_mflag(mp->flag & ~ME_FACE_SEL); + + /* this is necessary for selection counts to work properly */ + if (mp->flag & ME_FACE_SEL) { + BM_face_select_set(bm, f, true); + } + + f->mat_nr = mp->mat_nr; + if (i == me->act_face) { + bm->act_face = f; + } + + int j = mp->loopstart; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + /* don't use 'j' since we may have skipped some faces, hence some loops. */ + BM_elem_index_set(l_iter, totloops++); /* set_ok */ + + /* Save index of correspsonding MLoop */ + CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true); + } while ((l_iter = l_iter->next) != l_first); + + /* Copy Custom Data */ + CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true); + + if (params->calc_face_normal) { + BM_face_normal_update(f); + } + } + if (is_new) { + bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* added in order, clear dirty flag */ + } + + /* -------------------------------------------------------------------- */ + /* MSelect clears the array elements (avoid adding multiple times). + * + * Take care to keep this last and not use (v/e/ftable) after this. + */ + + if (me->mselect && me->totselect != 0) { + MSelect *msel; + for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) { + BMElem **ele_p; + switch (msel->type) { + case ME_VSEL: + ele_p = (BMElem **)&vtable[msel->index]; + break; + case ME_ESEL: + ele_p = (BMElem **)&etable[msel->index]; + break; + case ME_FSEL: + ele_p = (BMElem **)&ftable[msel->index]; + break; + default: + continue; + } + + if (*ele_p != NULL) { + BM_select_history_store_notest(bm, *ele_p); + *ele_p = NULL; + } + } + } + else { + BM_select_history_clear(bm); + } + + MEM_freeN(vtable); + MEM_freeN(etable); + if (ftable) { + MEM_freeN(ftable); + } } - /** * \brief BMesh -> Mesh */ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert) { - const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); - BMVert **vertMap = NULL; - BMVert *eve; - int i = 0; - BMIter iter; - - /* caller needs to ensure this */ - BLI_assert(ototvert > 0); - - vertMap = MEM_callocN(sizeof(*vertMap) * ototvert, "vertMap"); - if (cd_shape_keyindex_offset != -1) { - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); - if ((keyi != ORIGINDEX_NONE) && - (keyi < ototvert) && - /* not fool-proof, but chances are if we have many verts with the same index, - * we will want to use the first one, since the second is more likely to be a duplicate. */ - (vertMap[keyi] == NULL)) - { - vertMap[keyi] = eve; - } - } - } - else { - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - if (i < ototvert) { - vertMap[i] = eve; - } - else { - break; - } - } - } - - return vertMap; + const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); + BMVert **vertMap = NULL; + BMVert *eve; + int i = 0; + BMIter iter; + + /* caller needs to ensure this */ + BLI_assert(ototvert > 0); + + vertMap = MEM_callocN(sizeof(*vertMap) * ototvert, "vertMap"); + if (cd_shape_keyindex_offset != -1) { + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); + if ((keyi != ORIGINDEX_NONE) && (keyi < ototvert) && + /* not fool-proof, but chances are if we have many verts with the same index, + * we will want to use the first one, since the second is more likely to be a duplicate. */ + (vertMap[keyi] == NULL)) { + vertMap[keyi] = eve; + } + } + } + else { + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + if (i < ototvert) { + vertMap[i] = eve; + } + else { + break; + } + } + } + + return vertMap; } /** @@ -519,475 +515,465 @@ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert) * \note could split this out into a more generic function */ static int bm_to_mesh_shape_layer_index_from_kb(BMesh *bm, KeyBlock *currkey) { - int i; - int j = 0; - - for (i = 0; i < bm->vdata.totlayer; i++) { - if (bm->vdata.layers[i].type == CD_SHAPEKEY) { - if (currkey->uid == bm->vdata.layers[i].uid) { - return j; - } - j++; - } - } - return -1; + int i; + int j = 0; + + for (i = 0; i < bm->vdata.totlayer; i++) { + if (bm->vdata.layers[i].type == CD_SHAPEKEY) { + if (currkey->uid == bm->vdata.layers[i].uid) { + return j; + } + j++; + } + } + return -1; } BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e) { - /* this is a cheap way to set the edge draw, its not precise and will - * pick the first 2 faces an edge uses. - * The dot comparison is a little arbitrary, but set so that a 5 subd - * IcoSphere won't vanish but subd 6 will (as with pre-bmesh blender) */ - - - if ( /* (med->flag & ME_EDGEDRAW) && */ /* assume to be true */ - (e->l && (e->l != e->l->radial_next)) && - (dot_v3v3(e->l->f->no, e->l->radial_next->f->no) > 0.9995f)) - { - med->flag &= ~ME_EDGEDRAW; - } - else { - med->flag |= ME_EDGEDRAW; - } + /* this is a cheap way to set the edge draw, its not precise and will + * pick the first 2 faces an edge uses. + * The dot comparison is a little arbitrary, but set so that a 5 subd + * IcoSphere won't vanish but subd 6 will (as with pre-bmesh blender) */ + + if (/* (med->flag & ME_EDGEDRAW) && */ /* assume to be true */ + (e->l && (e->l != e->l->radial_next)) && + (dot_v3v3(e->l->f->no, e->l->radial_next->f->no) > 0.9995f)) { + med->flag &= ~ME_EDGEDRAW; + } + else { + med->flag |= ME_EDGEDRAW; + } } /** * * \param bmain: May be NULL in case \a calc_object_remap parameter option is not set. */ -void BM_mesh_bm_to_me( - Main *bmain, BMesh *bm, Mesh *me, - const struct BMeshToMeshParams *params) +void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params) { - MLoop *mloop; - MPoly *mpoly; - MVert *mvert, *oldverts; - MEdge *med, *medge; - BMVert *v, *eve; - BMEdge *e; - BMFace *f; - BMIter iter; - int i, j, ototvert; - - const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); - const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); - - ototvert = me->totvert; - - /* new vertex block */ - if (bm->totvert == 0) { - mvert = NULL; - } - else { - mvert = MEM_callocN(bm->totvert * sizeof(MVert), "loadeditbMesh vert"); - } - - /* new edge block */ - if (bm->totedge == 0) { - medge = NULL; - } - else { - medge = MEM_callocN(bm->totedge * sizeof(MEdge), "loadeditbMesh edge"); - } - - /* new ngon face block */ - if (bm->totface == 0) { - mpoly = NULL; - } - else { - mpoly = MEM_callocN(bm->totface * sizeof(MPoly), "loadeditbMesh poly"); - } - - /* new loop block */ - if (bm->totloop == 0) { - mloop = NULL; - } - else { - mloop = MEM_callocN(bm->totloop * sizeof(MLoop), "loadeditbMesh loop"); - } - - /* lets save the old verts just in case we are actually working on - * a key ... we now do processing of the keys at the end */ - oldverts = me->mvert; - - /* don't free this yet */ - if (oldverts) { - CustomData_set_layer(&me->vdata, CD_MVERT, NULL); - } - - /* free custom data */ - CustomData_free(&me->vdata, me->totvert); - CustomData_free(&me->edata, me->totedge); - CustomData_free(&me->fdata, me->totface); - CustomData_free(&me->ldata, me->totloop); - CustomData_free(&me->pdata, me->totpoly); - - /* add new custom data */ - me->totvert = bm->totvert; - me->totedge = bm->totedge; - me->totloop = bm->totloop; - me->totpoly = bm->totface; - /* will be overwritten with a valid value if 'dotess' is set, otherwise we - * end up with 'me->totface' and me->mface == NULL which can crash [#28625] - */ - me->totface = 0; - me->act_face = -1; - - { - CustomData_MeshMasks mask = CD_MASK_MESH; - CustomData_MeshMasks_update(&mask, ¶ms->cd_mask_extra); - CustomData_copy(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert); - CustomData_copy(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge); - CustomData_copy(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop); - CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly); - } - - CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert); - CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge); - CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop); - CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly); - - me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm); - - /* this is called again, 'dotess' arg is used there */ - BKE_mesh_update_customdata_pointers(me, 0); - - i = 0; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - copy_v3_v3(mvert->co, v->co); - normal_float_to_short_v3(mvert->no, v->no); - - mvert->flag = BM_vert_flag_to_mflag(v); - - BM_elem_index_set(v, i); /* set_inline */ - - /* copy over customdat */ - CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i); - - if (cd_vert_bweight_offset != -1) { - mvert->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(v, cd_vert_bweight_offset); - } - - i++; - mvert++; - - BM_CHECK_ELEMENT(v); - } - bm->elem_index_dirty &= ~BM_VERT; - - med = medge; - i = 0; - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - med->v1 = BM_elem_index_get(e->v1); - med->v2 = BM_elem_index_get(e->v2); - - med->flag = BM_edge_flag_to_mflag(e); - - BM_elem_index_set(e, i); /* set_inline */ - - /* copy over customdata */ - CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i); - - bmesh_quick_edgedraw_flag(med, e); - - if (cd_edge_crease_offset != -1) { - med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_crease_offset); - } - if (cd_edge_bweight_offset != -1) { - med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_bweight_offset); - } - - i++; - med++; - BM_CHECK_ELEMENT(e); - } - bm->elem_index_dirty &= ~BM_EDGE; - - i = 0; - j = 0; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - mpoly->loopstart = j; - mpoly->totloop = f->len; - mpoly->mat_nr = f->mat_nr; - mpoly->flag = BM_face_flag_to_mflag(f); - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - mloop->e = BM_elem_index_get(l_iter->e); - mloop->v = BM_elem_index_get(l_iter->v); - - /* copy over customdata */ - CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j); - - j++; - mloop++; - BM_CHECK_ELEMENT(l_iter); - BM_CHECK_ELEMENT(l_iter->e); - BM_CHECK_ELEMENT(l_iter->v); - } while ((l_iter = l_iter->next) != l_first); - - if (f == bm->act_face) { - me->act_face = i; - } - - /* copy over customdata */ - CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i); - - i++; - mpoly++; - BM_CHECK_ELEMENT(f); - } - - /* patch hook indices and vertex parents */ - if (params->calc_object_remap && (ototvert > 0)) { - BLI_assert(bmain != NULL); - Object *ob; - ModifierData *md; - BMVert **vertMap = NULL; - - for (ob = bmain->objects.first; ob; ob = ob->id.next) { - if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) { - - if (vertMap == NULL) { - vertMap = bm_to_mesh_vertex_map(bm, ototvert); - } - - if (ob->par1 < ototvert) { - eve = vertMap[ob->par1]; - if (eve) { - ob->par1 = BM_elem_index_get(eve); - } - } - if (ob->par2 < ototvert) { - eve = vertMap[ob->par2]; - if (eve) { - ob->par2 = BM_elem_index_get(eve); - } - } - if (ob->par3 < ototvert) { - eve = vertMap[ob->par3]; - if (eve) { - ob->par3 = BM_elem_index_get(eve); - } - } - - } - if (ob->data == me) { - for (md = ob->modifiers.first; md; md = md->next) { - if (md->type == eModifierType_Hook) { - HookModifierData *hmd = (HookModifierData *) md; - - if (vertMap == NULL) { - vertMap = bm_to_mesh_vertex_map(bm, ototvert); - } - - for (i = j = 0; i < hmd->totindex; i++) { - if (hmd->indexar[i] < ototvert) { - eve = vertMap[hmd->indexar[i]]; - - if (eve) { - hmd->indexar[j++] = BM_elem_index_get(eve); - } - } - else { - j++; - } - } - - hmd->totindex = j; - } - } - } - } - - if (vertMap) { - MEM_freeN(vertMap); - } - } - - BKE_mesh_update_customdata_pointers(me, false); - - { - BMEditSelection *selected; - me->totselect = BLI_listbase_count(&(bm->selected)); - - MEM_SAFE_FREE(me->mselect); - if (me->totselect != 0) { - me->mselect = MEM_mallocN(sizeof(MSelect) * me->totselect, "Mesh selection history"); - } - - for (i = 0, selected = bm->selected.first; selected; i++, selected = selected->next) { - if (selected->htype == BM_VERT) { - me->mselect[i].type = ME_VSEL; - - } - else if (selected->htype == BM_EDGE) { - me->mselect[i].type = ME_ESEL; - - } - else if (selected->htype == BM_FACE) { - me->mselect[i].type = ME_FSEL; - } - - me->mselect[i].index = BM_elem_index_get(selected->ele); - } - } - - /* see comment below, this logic is in twice */ - - if (me->key) { - const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); - - KeyBlock *currkey; - KeyBlock *actkey = BLI_findlink(&me->key->block, bm->shapenr - 1); - - float (*ofs)[3] = NULL; - - /* go through and find any shapekey customdata layers - * that might not have corresponding KeyBlocks, and add them if - * necessary */ - j = 0; - for (i = 0; i < bm->vdata.totlayer; i++) { - if (bm->vdata.layers[i].type != CD_SHAPEKEY) { - continue; - } - - for (currkey = me->key->block.first; currkey; currkey = currkey->next) { - if (currkey->uid == bm->vdata.layers[i].uid) { - break; - } - } - - if (!currkey) { - currkey = BKE_keyblock_add(me->key, bm->vdata.layers[i].name); - currkey->uid = bm->vdata.layers[i].uid; - } - - j++; - } - - - /* editing the base key should update others */ - if ((me->key->type == KEY_RELATIVE) && /* only need offsets for relative shape keys */ - (actkey != NULL) && /* unlikely, but the active key may not be valid if the - * bmesh and the mesh are out of sync */ - (oldverts != NULL)) /* not used here, but 'oldverts' is used later for applying 'ofs' */ - { - const bool act_is_basis = BKE_keyblock_is_basis(me->key, bm->shapenr - 1); - - /* active key is a base */ - if (act_is_basis && (cd_shape_keyindex_offset != -1)) { - float (*fp)[3] = actkey->data; - - ofs = MEM_callocN(sizeof(float) * 3 * bm->totvert, "currkey->data"); - mvert = me->mvert; - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); - - if (keyi != ORIGINDEX_NONE) { - sub_v3_v3v3(ofs[i], mvert->co, fp[keyi]); - } - else { - /* if there are new vertices in the mesh, we can't propagate the offset - * because it will only work for the existing vertices and not the new - * ones, creating a mess when doing e.g. subdivide + translate */ - MEM_freeN(ofs); - ofs = NULL; - break; - } - - mvert++; - } - } - } - - for (currkey = me->key->block.first; currkey; currkey = currkey->next) { - const bool apply_offset = (ofs && (currkey != actkey) && (bm->shapenr - 1 == currkey->relative)); - int cd_shape_offset; - int keyi; - float (*ofs_pt)[3] = ofs; - float *newkey, (*oldkey)[3], *fp; - - j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey); - cd_shape_offset = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, j); - - - fp = newkey = MEM_callocN(me->key->elemsize * bm->totvert, "currkey->data"); - oldkey = currkey->data; - - mvert = me->mvert; - BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - - if (currkey == actkey) { - copy_v3_v3(fp, eve->co); - - if (actkey != me->key->refkey) { /* important see bug [#30771] */ - if (cd_shape_keyindex_offset != -1) { - if (oldverts) { - keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); - if (keyi != ORIGINDEX_NONE && keyi < currkey->totelem) { /* valid old vertex */ - copy_v3_v3(mvert->co, oldverts[keyi].co); - } - } - } - } - } - else if (j != -1) { - /* in most cases this runs */ - copy_v3_v3(fp, BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset)); - } - else if ((oldkey != NULL) && - (cd_shape_keyindex_offset != -1) && - ((keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset)) != ORIGINDEX_NONE) && - (keyi < currkey->totelem)) - { - /* old method of reconstructing keys via vertice's original key indices, - * currently used if the new method above fails (which is theoretically - * possible in certain cases of undo) */ - copy_v3_v3(fp, oldkey[keyi]); - } - else { - /* fail! fill in with dummy value */ - copy_v3_v3(fp, mvert->co); - } - - /* propagate edited basis offsets to other shapes */ - if (apply_offset) { - add_v3_v3(fp, *ofs_pt++); - /* Apply back new coordinates of offsetted shapekeys into BMesh. - * Otherwise, in case we call again BM_mesh_bm_to_me on same BMesh, we'll apply diff from previous - * call to BM_mesh_bm_to_me, to shapekey values from *original creation of the BMesh*. See T50524. */ - copy_v3_v3(BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset), fp); - } - - fp += 3; - mvert++; - } - - currkey->totelem = bm->totvert; - if (currkey->data) { - MEM_freeN(currkey->data); - } - currkey->data = newkey; - } - - if (ofs) { - MEM_freeN(ofs); - } - } - - if (oldverts) { - MEM_freeN(oldverts); - } - - /* topology could be changed, ensure mdisps are ok */ - multires_topology_changed(me); - - /* to be removed as soon as COW is enabled by default. */ - BKE_mesh_runtime_clear_geometry(me); + MLoop *mloop; + MPoly *mpoly; + MVert *mvert, *oldverts; + MEdge *med, *medge; + BMVert *v, *eve; + BMEdge *e; + BMFace *f; + BMIter iter; + int i, j, ototvert; + + const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); + const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); + const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); + + ototvert = me->totvert; + + /* new vertex block */ + if (bm->totvert == 0) { + mvert = NULL; + } + else { + mvert = MEM_callocN(bm->totvert * sizeof(MVert), "loadeditbMesh vert"); + } + + /* new edge block */ + if (bm->totedge == 0) { + medge = NULL; + } + else { + medge = MEM_callocN(bm->totedge * sizeof(MEdge), "loadeditbMesh edge"); + } + + /* new ngon face block */ + if (bm->totface == 0) { + mpoly = NULL; + } + else { + mpoly = MEM_callocN(bm->totface * sizeof(MPoly), "loadeditbMesh poly"); + } + + /* new loop block */ + if (bm->totloop == 0) { + mloop = NULL; + } + else { + mloop = MEM_callocN(bm->totloop * sizeof(MLoop), "loadeditbMesh loop"); + } + + /* lets save the old verts just in case we are actually working on + * a key ... we now do processing of the keys at the end */ + oldverts = me->mvert; + + /* don't free this yet */ + if (oldverts) { + CustomData_set_layer(&me->vdata, CD_MVERT, NULL); + } + + /* free custom data */ + CustomData_free(&me->vdata, me->totvert); + CustomData_free(&me->edata, me->totedge); + CustomData_free(&me->fdata, me->totface); + CustomData_free(&me->ldata, me->totloop); + CustomData_free(&me->pdata, me->totpoly); + + /* add new custom data */ + me->totvert = bm->totvert; + me->totedge = bm->totedge; + me->totloop = bm->totloop; + me->totpoly = bm->totface; + /* will be overwritten with a valid value if 'dotess' is set, otherwise we + * end up with 'me->totface' and me->mface == NULL which can crash [#28625] + */ + me->totface = 0; + me->act_face = -1; + + { + CustomData_MeshMasks mask = CD_MASK_MESH; + CustomData_MeshMasks_update(&mask, ¶ms->cd_mask_extra); + CustomData_copy(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert); + CustomData_copy(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge); + CustomData_copy(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop); + CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly); + } + + CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert); + CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge); + CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop); + CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly); + + me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm); + + /* this is called again, 'dotess' arg is used there */ + BKE_mesh_update_customdata_pointers(me, 0); + + i = 0; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + copy_v3_v3(mvert->co, v->co); + normal_float_to_short_v3(mvert->no, v->no); + + mvert->flag = BM_vert_flag_to_mflag(v); + + BM_elem_index_set(v, i); /* set_inline */ + + /* copy over customdat */ + CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i); + + if (cd_vert_bweight_offset != -1) { + mvert->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(v, cd_vert_bweight_offset); + } + + i++; + mvert++; + + BM_CHECK_ELEMENT(v); + } + bm->elem_index_dirty &= ~BM_VERT; + + med = medge; + i = 0; + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + med->v1 = BM_elem_index_get(e->v1); + med->v2 = BM_elem_index_get(e->v2); + + med->flag = BM_edge_flag_to_mflag(e); + + BM_elem_index_set(e, i); /* set_inline */ + + /* copy over customdata */ + CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i); + + bmesh_quick_edgedraw_flag(med, e); + + if (cd_edge_crease_offset != -1) { + med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_crease_offset); + } + if (cd_edge_bweight_offset != -1) { + med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_bweight_offset); + } + + i++; + med++; + BM_CHECK_ELEMENT(e); + } + bm->elem_index_dirty &= ~BM_EDGE; + + i = 0; + j = 0; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BMLoop *l_iter, *l_first; + mpoly->loopstart = j; + mpoly->totloop = f->len; + mpoly->mat_nr = f->mat_nr; + mpoly->flag = BM_face_flag_to_mflag(f); + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + mloop->e = BM_elem_index_get(l_iter->e); + mloop->v = BM_elem_index_get(l_iter->v); + + /* copy over customdata */ + CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j); + + j++; + mloop++; + BM_CHECK_ELEMENT(l_iter); + BM_CHECK_ELEMENT(l_iter->e); + BM_CHECK_ELEMENT(l_iter->v); + } while ((l_iter = l_iter->next) != l_first); + + if (f == bm->act_face) { + me->act_face = i; + } + + /* copy over customdata */ + CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i); + + i++; + mpoly++; + BM_CHECK_ELEMENT(f); + } + + /* patch hook indices and vertex parents */ + if (params->calc_object_remap && (ototvert > 0)) { + BLI_assert(bmain != NULL); + Object *ob; + ModifierData *md; + BMVert **vertMap = NULL; + + for (ob = bmain->objects.first; ob; ob = ob->id.next) { + if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) { + + if (vertMap == NULL) { + vertMap = bm_to_mesh_vertex_map(bm, ototvert); + } + + if (ob->par1 < ototvert) { + eve = vertMap[ob->par1]; + if (eve) { + ob->par1 = BM_elem_index_get(eve); + } + } + if (ob->par2 < ototvert) { + eve = vertMap[ob->par2]; + if (eve) { + ob->par2 = BM_elem_index_get(eve); + } + } + if (ob->par3 < ototvert) { + eve = vertMap[ob->par3]; + if (eve) { + ob->par3 = BM_elem_index_get(eve); + } + } + } + if (ob->data == me) { + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Hook) { + HookModifierData *hmd = (HookModifierData *)md; + + if (vertMap == NULL) { + vertMap = bm_to_mesh_vertex_map(bm, ototvert); + } + + for (i = j = 0; i < hmd->totindex; i++) { + if (hmd->indexar[i] < ototvert) { + eve = vertMap[hmd->indexar[i]]; + + if (eve) { + hmd->indexar[j++] = BM_elem_index_get(eve); + } + } + else { + j++; + } + } + + hmd->totindex = j; + } + } + } + } + + if (vertMap) { + MEM_freeN(vertMap); + } + } + + BKE_mesh_update_customdata_pointers(me, false); + + { + BMEditSelection *selected; + me->totselect = BLI_listbase_count(&(bm->selected)); + + MEM_SAFE_FREE(me->mselect); + if (me->totselect != 0) { + me->mselect = MEM_mallocN(sizeof(MSelect) * me->totselect, "Mesh selection history"); + } + + for (i = 0, selected = bm->selected.first; selected; i++, selected = selected->next) { + if (selected->htype == BM_VERT) { + me->mselect[i].type = ME_VSEL; + } + else if (selected->htype == BM_EDGE) { + me->mselect[i].type = ME_ESEL; + } + else if (selected->htype == BM_FACE) { + me->mselect[i].type = ME_FSEL; + } + + me->mselect[i].index = BM_elem_index_get(selected->ele); + } + } + + /* see comment below, this logic is in twice */ + + if (me->key) { + const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); + + KeyBlock *currkey; + KeyBlock *actkey = BLI_findlink(&me->key->block, bm->shapenr - 1); + + float(*ofs)[3] = NULL; + + /* go through and find any shapekey customdata layers + * that might not have corresponding KeyBlocks, and add them if + * necessary */ + j = 0; + for (i = 0; i < bm->vdata.totlayer; i++) { + if (bm->vdata.layers[i].type != CD_SHAPEKEY) { + continue; + } + + for (currkey = me->key->block.first; currkey; currkey = currkey->next) { + if (currkey->uid == bm->vdata.layers[i].uid) { + break; + } + } + + if (!currkey) { + currkey = BKE_keyblock_add(me->key, bm->vdata.layers[i].name); + currkey->uid = bm->vdata.layers[i].uid; + } + + j++; + } + + /* editing the base key should update others */ + if ((me->key->type == KEY_RELATIVE) && /* only need offsets for relative shape keys */ + (actkey != NULL) && /* unlikely, but the active key may not be valid if the + * bmesh and the mesh are out of sync */ + (oldverts != NULL)) /* not used here, but 'oldverts' is used later for applying 'ofs' */ + { + const bool act_is_basis = BKE_keyblock_is_basis(me->key, bm->shapenr - 1); + + /* active key is a base */ + if (act_is_basis && (cd_shape_keyindex_offset != -1)) { + float(*fp)[3] = actkey->data; + + ofs = MEM_callocN(sizeof(float) * 3 * bm->totvert, "currkey->data"); + mvert = me->mvert; + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); + + if (keyi != ORIGINDEX_NONE) { + sub_v3_v3v3(ofs[i], mvert->co, fp[keyi]); + } + else { + /* if there are new vertices in the mesh, we can't propagate the offset + * because it will only work for the existing vertices and not the new + * ones, creating a mess when doing e.g. subdivide + translate */ + MEM_freeN(ofs); + ofs = NULL; + break; + } + + mvert++; + } + } + } + + for (currkey = me->key->block.first; currkey; currkey = currkey->next) { + const bool apply_offset = (ofs && (currkey != actkey) && + (bm->shapenr - 1 == currkey->relative)); + int cd_shape_offset; + int keyi; + float(*ofs_pt)[3] = ofs; + float *newkey, (*oldkey)[3], *fp; + + j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey); + cd_shape_offset = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, j); + + fp = newkey = MEM_callocN(me->key->elemsize * bm->totvert, "currkey->data"); + oldkey = currkey->data; + + mvert = me->mvert; + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + + if (currkey == actkey) { + copy_v3_v3(fp, eve->co); + + if (actkey != me->key->refkey) { /* important see bug [#30771] */ + if (cd_shape_keyindex_offset != -1) { + if (oldverts) { + keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); + if (keyi != ORIGINDEX_NONE && keyi < currkey->totelem) { /* valid old vertex */ + copy_v3_v3(mvert->co, oldverts[keyi].co); + } + } + } + } + } + else if (j != -1) { + /* in most cases this runs */ + copy_v3_v3(fp, BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset)); + } + else if ((oldkey != NULL) && (cd_shape_keyindex_offset != -1) && + ((keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset)) != ORIGINDEX_NONE) && + (keyi < currkey->totelem)) { + /* old method of reconstructing keys via vertice's original key indices, + * currently used if the new method above fails (which is theoretically + * possible in certain cases of undo) */ + copy_v3_v3(fp, oldkey[keyi]); + } + else { + /* fail! fill in with dummy value */ + copy_v3_v3(fp, mvert->co); + } + + /* propagate edited basis offsets to other shapes */ + if (apply_offset) { + add_v3_v3(fp, *ofs_pt++); + /* Apply back new coordinates of offsetted shapekeys into BMesh. + * Otherwise, in case we call again BM_mesh_bm_to_me on same BMesh, we'll apply diff from previous + * call to BM_mesh_bm_to_me, to shapekey values from *original creation of the BMesh*. See T50524. */ + copy_v3_v3(BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset), fp); + } + + fp += 3; + mvert++; + } + + currkey->totelem = bm->totvert; + if (currkey->data) { + MEM_freeN(currkey->data); + } + currkey->data = newkey; + } + + if (ofs) { + MEM_freeN(ofs); + } + } + + if (oldverts) { + MEM_freeN(oldverts); + } + + /* topology could be changed, ensure mdisps are ok */ + multires_topology_changed(me); + + /* to be removed as soon as COW is enabled by default. */ + BKE_mesh_runtime_clear_geometry(me); } /** @@ -1007,150 +993,150 @@ void BM_mesh_bm_to_me( */ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *cd_mask_extra) { - /* must be an empty mesh. */ - BLI_assert(me->totvert == 0); - BLI_assert(cd_mask_extra == NULL || (cd_mask_extra->vmask & CD_MASK_SHAPEKEY) == 0); - - me->totvert = bm->totvert; - me->totedge = bm->totedge; - me->totface = 0; - me->totloop = bm->totloop; - me->totpoly = bm->totface; - - CustomData_add_layer(&me->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totvert); - CustomData_add_layer(&me->edata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totedge); - CustomData_add_layer(&me->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totface); - - CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, bm->totvert); - CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, bm->totedge); - CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, bm->totloop); - CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, bm->totface); - - /* don't process shapekeys, we only feed them through the modifier stack as needed, - * e.g. for applying modifiers or the like*/ - CustomData_MeshMasks mask = CD_MASK_DERIVEDMESH; - if (cd_mask_extra != NULL) { - CustomData_MeshMasks_update(&mask, cd_mask_extra); - } - mask.vmask &= ~CD_MASK_SHAPEKEY; - CustomData_merge(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert); - CustomData_merge(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge); - CustomData_merge(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop); - CustomData_merge(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly); - - BKE_mesh_update_customdata_pointers(me, false); - - BMIter iter; - BMVert *eve; - BMEdge *eed; - BMFace *efa; - MVert *mvert = me->mvert; - MEdge *medge = me->medge; - MLoop *mloop = me->mloop; - MPoly *mpoly = me->mpoly; - int *index, add_orig; - unsigned int i, j; - - const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); - const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); - - me->runtime.deformed_only = true; - - /* don't add origindex layer if one already exists */ - add_orig = !CustomData_has_layer(&bm->pdata, CD_ORIGINDEX); - - index = CustomData_get_layer(&me->vdata, CD_ORIGINDEX); - - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - MVert *mv = &mvert[i]; - - copy_v3_v3(mv->co, eve->co); - - BM_elem_index_set(eve, i); /* set_inline */ - - normal_float_to_short_v3(mv->no, eve->no); - - mv->flag = BM_vert_flag_to_mflag(eve); - - if (cd_vert_bweight_offset != -1) { - mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset); - } - - if (add_orig) { - *index++ = i; - } - - CustomData_from_bmesh_block(&bm->vdata, &me->vdata, eve->head.data, i); - } - bm->elem_index_dirty &= ~BM_VERT; - - index = CustomData_get_layer(&me->edata, CD_ORIGINDEX); - BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { - MEdge *med = &medge[i]; - - BM_elem_index_set(eed, i); /* set_inline */ - - med->v1 = BM_elem_index_get(eed->v1); - med->v2 = BM_elem_index_get(eed->v2); - - med->flag = BM_edge_flag_to_mflag(eed); - - /* handle this differently to editmode switching, - * only enable draw for single user edges rather then calculating angle */ - if ((med->flag & ME_EDGEDRAW) == 0) { - if (eed->l && eed->l == eed->l->radial_next) { - med->flag |= ME_EDGEDRAW; - } - } - - if (cd_edge_crease_offset != -1) { - med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset); - } - if (cd_edge_bweight_offset != -1) { - med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset); - } - - CustomData_from_bmesh_block(&bm->edata, &me->edata, eed->head.data, i); - if (add_orig) { - *index++ = i; - } - } - bm->elem_index_dirty &= ~BM_EDGE; - - index = CustomData_get_layer(&me->pdata, CD_ORIGINDEX); - j = 0; - BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { - BMLoop *l_iter; - BMLoop *l_first; - MPoly *mp = &mpoly[i]; - - BM_elem_index_set(efa, i); /* set_inline */ - - mp->totloop = efa->len; - mp->flag = BM_face_flag_to_mflag(efa); - mp->loopstart = j; - mp->mat_nr = efa->mat_nr; + /* must be an empty mesh. */ + BLI_assert(me->totvert == 0); + BLI_assert(cd_mask_extra == NULL || (cd_mask_extra->vmask & CD_MASK_SHAPEKEY) == 0); + + me->totvert = bm->totvert; + me->totedge = bm->totedge; + me->totface = 0; + me->totloop = bm->totloop; + me->totpoly = bm->totface; + + CustomData_add_layer(&me->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totvert); + CustomData_add_layer(&me->edata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totedge); + CustomData_add_layer(&me->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totface); + + CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, bm->totvert); + CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, bm->totedge); + CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, bm->totloop); + CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, bm->totface); + + /* don't process shapekeys, we only feed them through the modifier stack as needed, + * e.g. for applying modifiers or the like*/ + CustomData_MeshMasks mask = CD_MASK_DERIVEDMESH; + if (cd_mask_extra != NULL) { + CustomData_MeshMasks_update(&mask, cd_mask_extra); + } + mask.vmask &= ~CD_MASK_SHAPEKEY; + CustomData_merge(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert); + CustomData_merge(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge); + CustomData_merge(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop); + CustomData_merge(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly); + + BKE_mesh_update_customdata_pointers(me, false); + + BMIter iter; + BMVert *eve; + BMEdge *eed; + BMFace *efa; + MVert *mvert = me->mvert; + MEdge *medge = me->medge; + MLoop *mloop = me->mloop; + MPoly *mpoly = me->mpoly; + int *index, add_orig; + unsigned int i, j; + + const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); + const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); + const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); + + me->runtime.deformed_only = true; + + /* don't add origindex layer if one already exists */ + add_orig = !CustomData_has_layer(&bm->pdata, CD_ORIGINDEX); + + index = CustomData_get_layer(&me->vdata, CD_ORIGINDEX); + + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + MVert *mv = &mvert[i]; + + copy_v3_v3(mv->co, eve->co); + + BM_elem_index_set(eve, i); /* set_inline */ + + normal_float_to_short_v3(mv->no, eve->no); + + mv->flag = BM_vert_flag_to_mflag(eve); + + if (cd_vert_bweight_offset != -1) { + mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset); + } + + if (add_orig) { + *index++ = i; + } + + CustomData_from_bmesh_block(&bm->vdata, &me->vdata, eve->head.data, i); + } + bm->elem_index_dirty &= ~BM_VERT; + + index = CustomData_get_layer(&me->edata, CD_ORIGINDEX); + BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { + MEdge *med = &medge[i]; + + BM_elem_index_set(eed, i); /* set_inline */ + + med->v1 = BM_elem_index_get(eed->v1); + med->v2 = BM_elem_index_get(eed->v2); + + med->flag = BM_edge_flag_to_mflag(eed); + + /* handle this differently to editmode switching, + * only enable draw for single user edges rather then calculating angle */ + if ((med->flag & ME_EDGEDRAW) == 0) { + if (eed->l && eed->l == eed->l->radial_next) { + med->flag |= ME_EDGEDRAW; + } + } + + if (cd_edge_crease_offset != -1) { + med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset); + } + if (cd_edge_bweight_offset != -1) { + med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset); + } + + CustomData_from_bmesh_block(&bm->edata, &me->edata, eed->head.data, i); + if (add_orig) { + *index++ = i; + } + } + bm->elem_index_dirty &= ~BM_EDGE; + + index = CustomData_get_layer(&me->pdata, CD_ORIGINDEX); + j = 0; + BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { + BMLoop *l_iter; + BMLoop *l_first; + MPoly *mp = &mpoly[i]; + + BM_elem_index_set(efa, i); /* set_inline */ + + mp->totloop = efa->len; + mp->flag = BM_face_flag_to_mflag(efa); + mp->loopstart = j; + mp->mat_nr = efa->mat_nr; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - mloop->v = BM_elem_index_get(l_iter->v); - mloop->e = BM_elem_index_get(l_iter->e); - CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j); + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + mloop->v = BM_elem_index_get(l_iter->v); + mloop->e = BM_elem_index_get(l_iter->e); + CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j); - BM_elem_index_set(l_iter, j); /* set_inline */ + BM_elem_index_set(l_iter, j); /* set_inline */ - j++; - mloop++; - } while ((l_iter = l_iter->next) != l_first); + j++; + mloop++; + } while ((l_iter = l_iter->next) != l_first); - CustomData_from_bmesh_block(&bm->pdata, &me->pdata, efa->head.data, i); + CustomData_from_bmesh_block(&bm->pdata, &me->pdata, efa->head.data, i); - if (add_orig) { - *index++ = i; - } - } - bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); + if (add_orig) { + *index++ = i; + } + } + bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); - me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm); + me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm); } diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h index 30a1e8bffd5..f0302764a5f 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.h +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h @@ -33,33 +33,31 @@ void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag); char BM_mesh_cd_flag_from_bmesh(BMesh *bm); struct BMeshFromMeshParams { - uint calc_face_normal : 1; - /* add a vertex CD_SHAPE_KEYINDEX layer */ - uint add_key_index : 1; - /* set vertex coordinates from the shapekey */ - uint use_shapekey : 1; - /* define the active shape key (index + 1) */ - int active_shapekey; - struct CustomData_MeshMasks cd_mask_extra; + uint calc_face_normal : 1; + /* add a vertex CD_SHAPE_KEYINDEX layer */ + uint add_key_index : 1; + /* set vertex coordinates from the shapekey */ + uint use_shapekey : 1; + /* define the active shape key (index + 1) */ + int active_shapekey; + struct CustomData_MeshMasks cd_mask_extra; }; -void BM_mesh_bm_from_me( - BMesh *bm, const struct Mesh *me, - const struct BMeshFromMeshParams *params) -ATTR_NONNULL(1, 3); +void BM_mesh_bm_from_me(BMesh *bm, const struct Mesh *me, const struct BMeshFromMeshParams *params) + ATTR_NONNULL(1, 3); struct BMeshToMeshParams { - /** Update object hook indices & vertex parents. */ - uint calc_object_remap : 1; - struct CustomData_MeshMasks cd_mask_extra; + /** Update object hook indices & vertex parents. */ + uint calc_object_remap : 1; + struct CustomData_MeshMasks cd_mask_extra; }; -void BM_mesh_bm_to_me( - struct Main *bmain, BMesh *bm, struct Mesh *me, - const struct BMeshToMeshParams *params) -ATTR_NONNULL(2, 3, 4); - -void BM_mesh_bm_to_me_for_eval( - BMesh *bm, struct Mesh *me, const struct CustomData_MeshMasks *cd_mask_extra) -ATTR_NONNULL(1, 2); - +void BM_mesh_bm_to_me(struct Main *bmain, + BMesh *bm, + struct Mesh *me, + const struct BMeshToMeshParams *params) ATTR_NONNULL(2, 3, 4); + +void BM_mesh_bm_to_me_for_eval(BMesh *bm, + struct Mesh *me, + const struct CustomData_MeshMasks *cd_mask_extra) + ATTR_NONNULL(1, 2); #endif /* __BMESH_MESH_CONV_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.c b/source/blender/bmesh/intern/bmesh_mesh_validate.c index de0554c0cc2..3b6f63df089 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_validate.c +++ b/source/blender/bmesh/intern/bmesh_mesh_validate.c @@ -26,20 +26,29 @@ /* debug builds only */ #ifdef DEBUG -#include "BLI_utildefines.h" -#include "BLI_edgehash.h" +# include "BLI_utildefines.h" +# include "BLI_edgehash.h" -#include "bmesh.h" - -#include "bmesh_mesh_validate.h" +# include "bmesh.h" +# include "bmesh_mesh_validate.h" /* macro which inserts the function name */ -#if defined __GNUC__ -# define ERRMSG(format, args...) { fprintf(stderr, "%s: " format ", " AT "\n", __func__, ##args); errtot++; } (void)0 -#else -# define ERRMSG(format, ...) { fprintf(stderr, "%s: " format ", " AT "\n", __func__, __VA_ARGS__); errtot++; } (void)0 -#endif +# if defined __GNUC__ +# define ERRMSG(format, args...) \ + { \ + fprintf(stderr, "%s: " format ", " AT "\n", __func__, ##args); \ + errtot++; \ + } \ + (void)0 +# else +# define ERRMSG(format, ...) \ + { \ + fprintf(stderr, "%s: " format ", " AT "\n", __func__, __VA_ARGS__); \ + errtot++; \ + } \ + (void)0 +# endif /** * Check of this BMesh is valid, this function can be slow since its intended to help with debugging. @@ -48,156 +57,166 @@ */ bool BM_mesh_validate(BMesh *bm) { - EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, bm->totedge); - int errtot; - - BMIter iter; - BMVert *v; - BMEdge *e; - BMFace *f; - - int i, j; - - errtot = -1; /* 'ERRMSG' next line will set at zero */ - fprintf(stderr, "\n"); - ERRMSG("This is a debugging function and not intended for general use, running slow test!"); - - /* force recalc, even if tagged as valid, since this mesh is suspect! */ - bm->elem_index_dirty |= BM_ALL; - BM_mesh_elem_index_ensure(bm, BM_ALL); - - BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT | BM_ELEM_HIDDEN) == (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) { - ERRMSG("vert %d: is hidden and selected", i); - } - - if (v->e) { - if (!BM_vert_in_edge(v->e, v)) { - ERRMSG("vert %d: is not in its referenced edge: %d", i, BM_elem_index_get(v->e)); - } - } - } - - /* check edges */ - BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { - void **val_p; - - if (e->v1 == e->v2) { - ERRMSG("edge %d: duplicate index: %d", i, BM_elem_index_get(e->v1)); - } - - /* build edgehash at the same time */ - if (BLI_edgehash_ensure_p(edge_hash, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2), &val_p)) { - BMEdge *e_other = *val_p; - ERRMSG("edge %d, %d: are duplicates", i, BM_elem_index_get(e_other)); - } - else { - *val_p = e; - } - } - - /* edge radial structure */ - BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { - if (BM_elem_flag_test(e, BM_ELEM_SELECT | BM_ELEM_HIDDEN) == (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) { - ERRMSG("edge %d: is hidden and selected", i); - } - - if (e->l) { - BMLoop *l_iter; - BMLoop *l_first; - - j = 0; - - l_iter = l_first = e->l; - /* we could do more checks here, but save for face checks */ - do { - if (l_iter->e != e) { - ERRMSG("edge %d: has invalid loop, loop is of face %d", i, BM_elem_index_get(l_iter->f)); - } - else if (BM_vert_in_edge(e, l_iter->v) == false) { - ERRMSG("edge %d: has invalid loop with vert not in edge, loop is of face %d", - i, BM_elem_index_get(l_iter->f)); - } - else if (BM_vert_in_edge(e, l_iter->next->v) == false) { - ERRMSG("edge %d: has invalid loop with next vert not in edge, loop is of face %d", - i, BM_elem_index_get(l_iter->f)); - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - } - - /* face structure */ - BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { - BMLoop *l_iter; - BMLoop *l_first; - - if (BM_elem_flag_test(f, BM_ELEM_SELECT | BM_ELEM_HIDDEN) == (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) { - ERRMSG("face %d: is hidden and selected", i); - } - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - - do { - BM_elem_flag_disable(l_iter, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_disable(l_iter->e, BM_ELEM_INTERNAL_TAG); - } while ((l_iter = l_iter->next) != l_first); - - j = 0; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (BM_elem_flag_test(l_iter, BM_ELEM_INTERNAL_TAG)) { - ERRMSG("face %d: has duplicate loop at corner: %d", i, j); - } - if (BM_elem_flag_test(l_iter->v, BM_ELEM_INTERNAL_TAG)) { - ERRMSG("face %d: has duplicate vert: %d, at corner: %d", i, BM_elem_index_get(l_iter->v), j); - } - if (BM_elem_flag_test(l_iter->e, BM_ELEM_INTERNAL_TAG)) { - ERRMSG("face %d: has duplicate edge: %d, at corner: %d", i, BM_elem_index_get(l_iter->e), j); - } - - /* adjacent data checks */ - if (l_iter->f != f) { - ERRMSG("face %d: has loop that points to face: %d at corner: %d", i, BM_elem_index_get(l_iter->f), j); - } - if (l_iter != l_iter->prev->next) { - ERRMSG("face %d: has invalid 'prev/next' at corner: %d", i, j); - } - if (l_iter != l_iter->next->prev) { - ERRMSG("face %d: has invalid 'next/prev' at corner: %d", i, j); - } - if (l_iter != l_iter->radial_prev->radial_next) { - ERRMSG("face %d: has invalid 'radial_prev/radial_next' at corner: %d", i, j); - } - if (l_iter != l_iter->radial_next->radial_prev) { - ERRMSG("face %d: has invalid 'radial_next/radial_prev' at corner: %d", i, j); - } - - BM_elem_flag_enable(l_iter, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_enable(l_iter->v, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_enable(l_iter->e, BM_ELEM_INTERNAL_TAG); - j++; - } while ((l_iter = l_iter->next) != l_first); - - if (j != f->len) { - ERRMSG("face %d: has length of %d but should be %d", i, f->len, j); - } - - /* leave elements un-tagged, not essential but nice to avoid unintended dirty tag use later. */ - do { - BM_elem_flag_disable(l_iter, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG); - BM_elem_flag_disable(l_iter->e, BM_ELEM_INTERNAL_TAG); - } while ((l_iter = l_iter->next) != l_first); - } - - BLI_edgehash_free(edge_hash, NULL); - - const bool is_valid = (errtot == 0); - ERRMSG("Finished - errors %d", errtot); - return is_valid; + EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, bm->totedge); + int errtot; + + BMIter iter; + BMVert *v; + BMEdge *e; + BMFace *f; + + int i, j; + + errtot = -1; /* 'ERRMSG' next line will set at zero */ + fprintf(stderr, "\n"); + ERRMSG("This is a debugging function and not intended for general use, running slow test!"); + + /* force recalc, even if tagged as valid, since this mesh is suspect! */ + bm->elem_index_dirty |= BM_ALL; + BM_mesh_elem_index_ensure(bm, BM_ALL); + + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT | BM_ELEM_HIDDEN) == + (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) { + ERRMSG("vert %d: is hidden and selected", i); + } + + if (v->e) { + if (!BM_vert_in_edge(v->e, v)) { + ERRMSG("vert %d: is not in its referenced edge: %d", i, BM_elem_index_get(v->e)); + } + } + } + + /* check edges */ + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + void **val_p; + + if (e->v1 == e->v2) { + ERRMSG("edge %d: duplicate index: %d", i, BM_elem_index_get(e->v1)); + } + + /* build edgehash at the same time */ + if (BLI_edgehash_ensure_p( + edge_hash, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2), &val_p)) { + BMEdge *e_other = *val_p; + ERRMSG("edge %d, %d: are duplicates", i, BM_elem_index_get(e_other)); + } + else { + *val_p = e; + } + } + + /* edge radial structure */ + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT | BM_ELEM_HIDDEN) == + (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) { + ERRMSG("edge %d: is hidden and selected", i); + } + + if (e->l) { + BMLoop *l_iter; + BMLoop *l_first; + + j = 0; + + l_iter = l_first = e->l; + /* we could do more checks here, but save for face checks */ + do { + if (l_iter->e != e) { + ERRMSG("edge %d: has invalid loop, loop is of face %d", i, BM_elem_index_get(l_iter->f)); + } + else if (BM_vert_in_edge(e, l_iter->v) == false) { + ERRMSG("edge %d: has invalid loop with vert not in edge, loop is of face %d", + i, + BM_elem_index_get(l_iter->f)); + } + else if (BM_vert_in_edge(e, l_iter->next->v) == false) { + ERRMSG("edge %d: has invalid loop with next vert not in edge, loop is of face %d", + i, + BM_elem_index_get(l_iter->f)); + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + } + + /* face structure */ + BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { + BMLoop *l_iter; + BMLoop *l_first; + + if (BM_elem_flag_test(f, BM_ELEM_SELECT | BM_ELEM_HIDDEN) == + (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) { + ERRMSG("face %d: is hidden and selected", i); + } + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + + do { + BM_elem_flag_disable(l_iter, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_disable(l_iter->e, BM_ELEM_INTERNAL_TAG); + } while ((l_iter = l_iter->next) != l_first); + + j = 0; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter, BM_ELEM_INTERNAL_TAG)) { + ERRMSG("face %d: has duplicate loop at corner: %d", i, j); + } + if (BM_elem_flag_test(l_iter->v, BM_ELEM_INTERNAL_TAG)) { + ERRMSG( + "face %d: has duplicate vert: %d, at corner: %d", i, BM_elem_index_get(l_iter->v), j); + } + if (BM_elem_flag_test(l_iter->e, BM_ELEM_INTERNAL_TAG)) { + ERRMSG( + "face %d: has duplicate edge: %d, at corner: %d", i, BM_elem_index_get(l_iter->e), j); + } + + /* adjacent data checks */ + if (l_iter->f != f) { + ERRMSG("face %d: has loop that points to face: %d at corner: %d", + i, + BM_elem_index_get(l_iter->f), + j); + } + if (l_iter != l_iter->prev->next) { + ERRMSG("face %d: has invalid 'prev/next' at corner: %d", i, j); + } + if (l_iter != l_iter->next->prev) { + ERRMSG("face %d: has invalid 'next/prev' at corner: %d", i, j); + } + if (l_iter != l_iter->radial_prev->radial_next) { + ERRMSG("face %d: has invalid 'radial_prev/radial_next' at corner: %d", i, j); + } + if (l_iter != l_iter->radial_next->radial_prev) { + ERRMSG("face %d: has invalid 'radial_next/radial_prev' at corner: %d", i, j); + } + + BM_elem_flag_enable(l_iter, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_enable(l_iter->v, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_enable(l_iter->e, BM_ELEM_INTERNAL_TAG); + j++; + } while ((l_iter = l_iter->next) != l_first); + + if (j != f->len) { + ERRMSG("face %d: has length of %d but should be %d", i, f->len, j); + } + + /* leave elements un-tagged, not essential but nice to avoid unintended dirty tag use later. */ + do { + BM_elem_flag_disable(l_iter, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG); + BM_elem_flag_disable(l_iter->e, BM_ELEM_INTERNAL_TAG); + } while ((l_iter = l_iter->next) != l_first); + } + + BLI_edgehash_free(edge_hash, NULL); + + const bool is_valid = (errtot == 0); + ERRMSG("Finished - errors %d", errtot); + return is_valid; } - #endif diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index e1aa5fcfee1..1075b3753da 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -58,39 +58,39 @@ */ bool BM_vert_dissolve(BMesh *bm, BMVert *v) { - /* logic for 3 or more is identical */ - const int len = BM_vert_edge_count_at_most(v, 3); - - if (len == 1) { - BM_vert_kill(bm, v); /* will kill edges too */ - return true; - } - else if (!BM_vert_is_manifold(v)) { - if (!v->e) { - BM_vert_kill(bm, v); - return true; - } - else if (!v->e->l) { - if (len == 2) { - return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL); - } - else { - /* used to kill the vertex here, but it may be connected to faces. - * so better do nothing */ - return false; - } - } - else { - return false; - } - } - else if (len == 2 && BM_vert_face_count_is_equal(v, 1)) { - /* boundary vertex on a face */ - return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL); - } - else { - return BM_disk_dissolve(bm, v); - } + /* logic for 3 or more is identical */ + const int len = BM_vert_edge_count_at_most(v, 3); + + if (len == 1) { + BM_vert_kill(bm, v); /* will kill edges too */ + return true; + } + else if (!BM_vert_is_manifold(v)) { + if (!v->e) { + BM_vert_kill(bm, v); + return true; + } + else if (!v->e->l) { + if (len == 2) { + return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL); + } + else { + /* used to kill the vertex here, but it may be connected to faces. + * so better do nothing */ + return false; + } + } + else { + return false; + } + } + else if (len == 2 && BM_vert_face_count_is_equal(v, 1)) { + /* boundary vertex on a face */ + return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL); + } + else { + return BM_disk_dissolve(bm, v); + } } /** @@ -98,115 +98,115 @@ bool BM_vert_dissolve(BMesh *bm, BMVert *v) */ bool BM_disk_dissolve(BMesh *bm, BMVert *v) { - BMEdge *e, *keepedge = NULL, *baseedge = NULL; - int len = 0; - - if (!BM_vert_is_manifold(v)) { - return false; - } - - if (v->e) { - /* v->e we keep, what else */ - e = v->e; - do { - e = bmesh_disk_edge_next(e, v); - if (!(BM_edge_share_face_check(e, v->e))) { - keepedge = e; - baseedge = v->e; - break; - } - len++; - } while (e != v->e); - } - - /* this code for handling 2 and 3-valence verts - * may be totally bad */ - if (keepedge == NULL && len == 3) { + BMEdge *e, *keepedge = NULL, *baseedge = NULL; + int len = 0; + + if (!BM_vert_is_manifold(v)) { + return false; + } + + if (v->e) { + /* v->e we keep, what else */ + e = v->e; + do { + e = bmesh_disk_edge_next(e, v); + if (!(BM_edge_share_face_check(e, v->e))) { + keepedge = e; + baseedge = v->e; + break; + } + len++; + } while (e != v->e); + } + + /* this code for handling 2 and 3-valence verts + * may be totally bad */ + if (keepedge == NULL && len == 3) { #if 0 - /* handle specific case for three-valence. solve it by - * increasing valence to four. this may be hackish. . */ - BMLoop *l_a = BM_face_vert_share_loop(e->l->f, v); - BMLoop *l_b = (e->l->v == v) ? e->l->next : e->l; + /* handle specific case for three-valence. solve it by + * increasing valence to four. this may be hackish. . */ + BMLoop *l_a = BM_face_vert_share_loop(e->l->f, v); + BMLoop *l_b = (e->l->v == v) ? e->l->next : e->l; - if (!BM_face_split(bm, e->l->f, l_a, l_b, NULL, NULL, false)) - return false; + if (!BM_face_split(bm, e->l->f, l_a, l_b, NULL, NULL, false)) + return false; - if (!BM_disk_dissolve(bm, v)) { - return false; - } + if (!BM_disk_dissolve(bm, v)) { + return false; + } #else - if (UNLIKELY(!BM_faces_join_pair(bm, e->l, e->l->radial_next, true))) { - return false; - } - else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, true, false, true))) { - return false; - } + if (UNLIKELY(!BM_faces_join_pair(bm, e->l, e->l->radial_next, true))) { + return false; + } + else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, true, false, true))) { + return false; + } #endif - return true; - } - else if (keepedge == NULL && len == 2) { - /* collapse the vertex */ - e = BM_vert_collapse_faces(bm, v->e, v, 1.0, true, true, true); - - if (!e) { - return false; - } - - /* handle two-valence */ - if (e->l != e->l->radial_next) { - if (!BM_faces_join_pair(bm, e->l, e->l->radial_next, true)) { - return false; - } - } - - return true; - } - - if (keepedge) { - bool done = false; - - while (!done) { - done = true; - e = v->e; - do { - BMFace *f = NULL; - if (BM_edge_is_manifold(e) && (e != baseedge) && (e != keepedge)) { - f = BM_faces_join_pair(bm, e->l, e->l->radial_next, true); - /* return if couldn't join faces in manifold - * conditions */ - /* !disabled for testing why bad things happen */ - if (!f) { - return false; - } - } - - if (f) { - done = false; - break; - } - } while ((e = bmesh_disk_edge_next(e, v)) != v->e); - } - - /* collapse the vertex */ - /* note, the baseedge can be a boundary of manifold, use this as join_faces arg */ - e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, true, !BM_edge_is_boundary(baseedge), true); - - if (!e) { - return false; - } - - if (e->l) { - /* get remaining two faces */ - if (e->l != e->l->radial_next) { - /* join two remaining faces */ - if (!BM_faces_join_pair(bm, e->l, e->l->radial_next, true)) { - return false; - } - } - } - } - - return true; + return true; + } + else if (keepedge == NULL && len == 2) { + /* collapse the vertex */ + e = BM_vert_collapse_faces(bm, v->e, v, 1.0, true, true, true); + + if (!e) { + return false; + } + + /* handle two-valence */ + if (e->l != e->l->radial_next) { + if (!BM_faces_join_pair(bm, e->l, e->l->radial_next, true)) { + return false; + } + } + + return true; + } + + if (keepedge) { + bool done = false; + + while (!done) { + done = true; + e = v->e; + do { + BMFace *f = NULL; + if (BM_edge_is_manifold(e) && (e != baseedge) && (e != keepedge)) { + f = BM_faces_join_pair(bm, e->l, e->l->radial_next, true); + /* return if couldn't join faces in manifold + * conditions */ + /* !disabled for testing why bad things happen */ + if (!f) { + return false; + } + } + + if (f) { + done = false; + break; + } + } while ((e = bmesh_disk_edge_next(e, v)) != v->e); + } + + /* collapse the vertex */ + /* note, the baseedge can be a boundary of manifold, use this as join_faces arg */ + e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, true, !BM_edge_is_boundary(baseedge), true); + + if (!e) { + return false; + } + + if (e->l) { + /* get remaining two faces */ + if (e->l != e->l->radial_next) { + /* join two remaining faces */ + if (!BM_faces_join_pair(bm, e->l, e->l->radial_next, true)) { + return false; + } + } + } + } + + return true; } /** @@ -224,15 +224,15 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v) */ BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_del) { - BLI_assert((l_a != l_b) && (l_a->e == l_b->e)); + BLI_assert((l_a != l_b) && (l_a->e == l_b->e)); - if (l_a->v == l_b->v) { - const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); - bmesh_kernel_loop_reverse(bm, l_b->f, cd_loop_mdisp_offset, true); - } + if (l_a->v == l_b->v) { + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + bmesh_kernel_loop_reverse(bm, l_b->f, cd_loop_mdisp_offset, true); + } - BMFace *faces[2] = {l_a->f, l_b->f}; - return BM_faces_join(bm, faces, 2, do_del); + BMFace *faces[2] = {l_a->f, l_b->f}; + return BM_faces_join(bm, faces, 2, do_del); } /** @@ -253,67 +253,68 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_de * if the split is successful (and the original original face will be the * other side). NULL if the split fails. */ -BMFace *BM_face_split( - BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - BMLoop **r_l, BMEdge *example, - const bool no_double) +BMFace *BM_face_split(BMesh *bm, + BMFace *f, + BMLoop *l_a, + BMLoop *l_b, + BMLoop **r_l, + BMEdge *example, + const bool no_double) { - const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); - BMFace *f_new, *f_tmp; - - BLI_assert(l_a != l_b); - BLI_assert(f == l_a->f && f == l_b->f); - BLI_assert(!BM_loop_is_adjacent(l_a, l_b)); - - /* could be an assert */ - if (UNLIKELY(BM_loop_is_adjacent(l_a, l_b)) || - UNLIKELY((f != l_a->f || f != l_b->f))) - { - if (r_l) { - *r_l = NULL; - } - return NULL; - } - - /* do we have a multires layer? */ - if (cd_loop_mdisp_offset != -1) { - f_tmp = BM_face_copy(bm, bm, f, false, false); - } + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + BMFace *f_new, *f_tmp; + + BLI_assert(l_a != l_b); + BLI_assert(f == l_a->f && f == l_b->f); + BLI_assert(!BM_loop_is_adjacent(l_a, l_b)); + + /* could be an assert */ + if (UNLIKELY(BM_loop_is_adjacent(l_a, l_b)) || UNLIKELY((f != l_a->f || f != l_b->f))) { + if (r_l) { + *r_l = NULL; + } + return NULL; + } + + /* do we have a multires layer? */ + if (cd_loop_mdisp_offset != -1) { + f_tmp = BM_face_copy(bm, bm, f, false, false); + } #ifdef USE_BMESH_HOLES - f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, NULL, example, no_double); + f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, NULL, example, no_double); #else - f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, example, no_double); + f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, example, no_double); #endif - if (f_new) { - /* handle multires update */ - if (cd_loop_mdisp_offset != -1) { - float f_dst_center[3]; - float f_src_center[3]; + if (f_new) { + /* handle multires update */ + if (cd_loop_mdisp_offset != -1) { + float f_dst_center[3]; + float f_src_center[3]; - BM_face_calc_center_median(f_tmp, f_src_center); + BM_face_calc_center_median(f_tmp, f_src_center); - BM_face_calc_center_median(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_median(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_median(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); + BM_face_calc_center_median(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 */ - BM_face_multires_bounds_smooth(bm, f); - BM_face_multires_bounds_smooth(bm, f_new); + /* BM_face_multires_bounds_smooth doesn't flip displacement correct */ + BM_face_multires_bounds_smooth(bm, f); + BM_face_multires_bounds_smooth(bm, f_new); #endif - } - } + } + } - if (cd_loop_mdisp_offset != -1) { - BM_face_kill(bm, f_tmp); - } + if (cd_loop_mdisp_offset != -1) { + BM_face_kill(bm, f_tmp); + } - return f_new; + return f_new; } /** @@ -333,74 +334,75 @@ BMFace *BM_face_split( * if the split is successful (and the original original face will be the * other side). NULL if the split fails. */ -BMFace *BM_face_split_n( - BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - float cos[][3], int n, - BMLoop **r_l, BMEdge *example) +BMFace *BM_face_split_n(BMesh *bm, + BMFace *f, + BMLoop *l_a, + BMLoop *l_b, + float cos[][3], + int n, + BMLoop **r_l, + BMEdge *example) { - BMFace *f_new, *f_tmp; - BMLoop *l_new; - BMEdge *e, *e_new; - BMVert *v_new; - // BMVert *v_a = l_a->v; /* UNUSED */ - BMVert *v_b = l_b->v; - int i, j; - - BLI_assert(l_a != l_b); - BLI_assert(f == l_a->f && f == l_b->f); - BLI_assert(!((n == 0) && BM_loop_is_adjacent(l_a, l_b))); - - /* could be an assert */ - if (UNLIKELY((n == 0) && BM_loop_is_adjacent(l_a, l_b)) || - UNLIKELY(l_a->f != l_b->f)) - { - if (r_l) { - *r_l = NULL; - } - return NULL; - } - - f_tmp = BM_face_copy(bm, bm, f, true, true); + BMFace *f_new, *f_tmp; + BMLoop *l_new; + BMEdge *e, *e_new; + BMVert *v_new; + // BMVert *v_a = l_a->v; /* UNUSED */ + BMVert *v_b = l_b->v; + int i, j; + + BLI_assert(l_a != l_b); + BLI_assert(f == l_a->f && f == l_b->f); + BLI_assert(!((n == 0) && BM_loop_is_adjacent(l_a, l_b))); + + /* could be an assert */ + if (UNLIKELY((n == 0) && BM_loop_is_adjacent(l_a, l_b)) || UNLIKELY(l_a->f != l_b->f)) { + if (r_l) { + *r_l = NULL; + } + return NULL; + } + + f_tmp = BM_face_copy(bm, bm, f, true, true); #ifdef USE_BMESH_HOLES - f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, NULL, example, false); + f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, NULL, example, false); #else - f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, example, false); + f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, example, false); #endif - /* bmesh_kernel_split_face_make_edge returns in 'l_new' a Loop for f_new going from 'v_a' to 'v_b'. - * The radial_next is for 'f' and goes from 'v_b' to 'v_a' */ - - if (f_new) { - e = l_new->e; - for (i = 0; i < n; i++) { - v_new = bmesh_kernel_split_edge_make_vert(bm, v_b, e, &e_new); - BLI_assert(v_new != NULL); - /* bmesh_kernel_split_edge_make_vert returns in 'e_new' the edge going from 'v_new' to 'v_b' */ - copy_v3_v3(v_new->co, cos[i]); - - /* interpolate the loop data for the loops with (v == v_new), using orig face */ - for (j = 0; j < 2; j++) { - BMEdge *e_iter = (j == 0) ? e : e_new; - BMLoop *l_iter = e_iter->l; - do { - if (l_iter->v == v_new) { - /* this interpolates both loop and vertex data */ - BM_loop_interp_from_face(bm, l_iter, f_tmp, true, true); - } - } while ((l_iter = l_iter->radial_next) != e_iter->l); - } - e = e_new; - } - } - - BM_face_verts_kill(bm, f_tmp); - - if (r_l) { - *r_l = l_new; - } - - return f_new; + /* bmesh_kernel_split_face_make_edge returns in 'l_new' a Loop for f_new going from 'v_a' to 'v_b'. + * The radial_next is for 'f' and goes from 'v_b' to 'v_a' */ + + if (f_new) { + e = l_new->e; + for (i = 0; i < n; i++) { + v_new = bmesh_kernel_split_edge_make_vert(bm, v_b, e, &e_new); + BLI_assert(v_new != NULL); + /* bmesh_kernel_split_edge_make_vert returns in 'e_new' the edge going from 'v_new' to 'v_b' */ + copy_v3_v3(v_new->co, cos[i]); + + /* interpolate the loop data for the loops with (v == v_new), using orig face */ + for (j = 0; j < 2; j++) { + BMEdge *e_iter = (j == 0) ? e : e_new; + BMLoop *l_iter = e_iter->l; + do { + if (l_iter->v == v_new) { + /* this interpolates both loop and vertex data */ + BM_loop_interp_from_face(bm, l_iter, f_tmp, true, true); + } + } while ((l_iter = l_iter->radial_next) != e_iter->l); + } + e = e_new; + } + } + + BM_face_verts_kill(bm, f_tmp); + + if (r_l) { + *r_l = l_new; + } + + return f_new; } /** @@ -426,89 +428,90 @@ BMFace *BM_face_split_n( * * \returns The New Edge */ -BMEdge *BM_vert_collapse_faces( - BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, - const bool do_del, const bool join_faces, const bool kill_degenerate_faces) +BMEdge *BM_vert_collapse_faces(BMesh *bm, + BMEdge *e_kill, + BMVert *v_kill, + float fac, + const bool do_del, + const bool join_faces, + const bool kill_degenerate_faces) { - BMEdge *e_new = NULL; - BMVert *tv = BM_edge_other_vert(e_kill, v_kill); - - BMEdge *e2; - BMVert *tv2; - - /* Only intended to be called for 2-valence vertices */ - BLI_assert(bmesh_disk_count(v_kill) <= 2); - - - /* first modify the face loop data */ - - if (e_kill->l) { - BMLoop *l_iter; - const float w[2] = {1.0f - fac, fac}; - - l_iter = e_kill->l; - do { - if (l_iter->v == tv && l_iter->next->v == v_kill) { - const void *src[2]; - BMLoop *tvloop = l_iter; - BMLoop *kvloop = l_iter->next; - - src[0] = kvloop->head.data; - src[1] = tvloop->head.data; - CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, kvloop->head.data); - } - } while ((l_iter = l_iter->radial_next) != e_kill->l); - } - - /* now interpolate the vertex data */ - BM_data_interp_from_verts(bm, v_kill, tv, v_kill, fac); - - e2 = bmesh_disk_edge_next(e_kill, v_kill); - tv2 = BM_edge_other_vert(e2, v_kill); - - if (join_faces) { - BMIter fiter; - BMFace **faces = NULL; - BMFace *f; - BLI_array_staticdeclare(faces, BM_DEFAULT_ITER_STACK_SIZE); - - BM_ITER_ELEM (f, &fiter, v_kill, BM_FACES_OF_VERT) { - BLI_array_append(faces, f); - } - - if (BLI_array_len(faces) >= 2) { - BMFace *f2 = BM_faces_join(bm, faces, BLI_array_len(faces), true); - if (f2) { - BMLoop *l_a, *l_b; - - if ((l_a = BM_face_vert_share_loop(f2, tv)) && - (l_b = BM_face_vert_share_loop(f2, tv2))) - { - BMLoop *l_new; - - if (BM_face_split(bm, f2, l_a, l_b, &l_new, NULL, false)) { - e_new = l_new->e; - } - } - } - } - - BLI_assert(BLI_array_len(faces) < 8); - - BLI_array_free(faces); - } - else { - /* 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_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); - /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */ - } - - return e_new; + BMEdge *e_new = NULL; + BMVert *tv = BM_edge_other_vert(e_kill, v_kill); + + BMEdge *e2; + BMVert *tv2; + + /* Only intended to be called for 2-valence vertices */ + BLI_assert(bmesh_disk_count(v_kill) <= 2); + + /* first modify the face loop data */ + + if (e_kill->l) { + BMLoop *l_iter; + const float w[2] = {1.0f - fac, fac}; + + l_iter = e_kill->l; + do { + if (l_iter->v == tv && l_iter->next->v == v_kill) { + const void *src[2]; + BMLoop *tvloop = l_iter; + BMLoop *kvloop = l_iter->next; + + src[0] = kvloop->head.data; + src[1] = tvloop->head.data; + CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, kvloop->head.data); + } + } while ((l_iter = l_iter->radial_next) != e_kill->l); + } + + /* now interpolate the vertex data */ + BM_data_interp_from_verts(bm, v_kill, tv, v_kill, fac); + + e2 = bmesh_disk_edge_next(e_kill, v_kill); + tv2 = BM_edge_other_vert(e2, v_kill); + + if (join_faces) { + BMIter fiter; + BMFace **faces = NULL; + BMFace *f; + BLI_array_staticdeclare(faces, BM_DEFAULT_ITER_STACK_SIZE); + + BM_ITER_ELEM (f, &fiter, v_kill, BM_FACES_OF_VERT) { + BLI_array_append(faces, f); + } + + if (BLI_array_len(faces) >= 2) { + BMFace *f2 = BM_faces_join(bm, faces, BLI_array_len(faces), true); + if (f2) { + BMLoop *l_a, *l_b; + + if ((l_a = BM_face_vert_share_loop(f2, tv)) && (l_b = BM_face_vert_share_loop(f2, tv2))) { + BMLoop *l_new; + + if (BM_face_split(bm, f2, l_a, l_b, &l_new, NULL, false)) { + e_new = l_new->e; + } + } + } + } + + BLI_assert(BLI_array_len(faces) < 8); + + BLI_array_free(faces); + } + else { + /* 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_kernel_join_edge_kill_vert( + bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); + /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */ + } + + return e_new; } - /** * \brief Vert Collapse Faces * @@ -517,35 +520,34 @@ BMEdge *BM_vert_collapse_faces( * \return The New Edge */ BMEdge *BM_vert_collapse_edge( - BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool kill_degenerate_faces) + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces) { - /* nice example implementation but we want loops to have their customdata - * accounted for */ + /* nice example implementation but we want loops to have their customdata + * accounted for */ #if 0 - BMEdge *e_new = NULL; - - /* Collapse between 2 edges */ - - /* in this case we want to keep all faces and not join them, - * rather just get rid of the vertex - see bug [#28645] */ - BMVert *tv = BM_edge_other_vert(e_kill, v_kill); - if (tv) { - BMEdge *e2 = bmesh_disk_edge_next(e_kill, v_kill); - if (e2) { - BMVert *tv2 = BM_edge_other_vert(e2, v_kill); - if (tv2) { - /* only action, other calls here only get the edge to return */ - e_new = bmesh_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); - } - } - } - - return e_new; + BMEdge *e_new = NULL; + + /* Collapse between 2 edges */ + + /* in this case we want to keep all faces and not join them, + * rather just get rid of the vertex - see bug [#28645] */ + BMVert *tv = BM_edge_other_vert(e_kill, v_kill); + if (tv) { + BMEdge *e2 = bmesh_disk_edge_next(e_kill, v_kill); + if (e2) { + BMVert *tv2 = BM_edge_other_vert(e2, v_kill); + if (tv2) { + /* only action, other calls here only get the edge to return */ + e_new = bmesh_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); + } + } + } + + return e_new; #else - /* with these args faces are never joined, same as above - * but account for loop customdata */ - return BM_vert_collapse_faces(bm, e_kill, v_kill, 1.0f, do_del, false, kill_degenerate_faces); + /* with these args faces are never joined, same as above + * but account for loop customdata */ + return BM_vert_collapse_faces(bm, e_kill, v_kill, 1.0f, do_del, false, kill_degenerate_faces); #endif } @@ -555,10 +557,9 @@ BMEdge *BM_vert_collapse_edge( * 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) + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces) { - return bmesh_kernel_join_vert_kill_edge(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); + return bmesh_kernel_join_vert_kill_edge(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); } /** @@ -582,116 +583,117 @@ BMVert *BM_edge_collapse( */ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) { - BMVert *v_new, *v_other; - BMEdge *e_new; - BMFace **oldfaces = NULL; - BLI_array_staticdeclare(oldfaces, 32); - 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); - - /* do we have a multi-res layer? */ - if (cd_loop_mdisp_offset != -1) { - BMLoop *l; - int i; - - l = e->l; - do { - BLI_array_append(oldfaces, l->f); - l = l->radial_next; - } while (l != e->l); - - /* flag existing faces so we can differentiate oldfaces from new faces */ - for (i = 0; i < BLI_array_len(oldfaces); i++) { - BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP); - oldfaces[i] = BM_face_copy(bm, bm, oldfaces[i], true, true); - BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP); - } - } - - v_other = BM_edge_other_vert(e, v); - v_new = bmesh_kernel_split_edge_make_vert(bm, v, e, &e_new); - if (r_e != NULL) { - *r_e = e_new; - } - - BLI_assert(v_new != NULL); - BLI_assert(BM_vert_in_edge(e_new, v) && BM_vert_in_edge(e_new, v_new)); - BLI_assert(BM_vert_in_edge(e, v_new) && BM_vert_in_edge(e, v_other)); - - sub_v3_v3v3(v_new->co, v_other->co, v->co); - madd_v3_v3v3fl(v_new->co, v->co, v_new->co, fac); - - e_new->head.hflag = e->head.hflag; - BM_elem_attrs_copy(bm, bm, e, e_new); - - /* v->v_new->v2 */ - 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 (cd_loop_mdisp_offset != -1) { - int i, j; - - /* interpolate new/changed loop data from copied old faces */ - for (i = 0; i < BLI_array_len(oldfaces); i++) { - float f_center_old[3]; - - BM_face_calc_center_median(oldfaces[i], f_center_old); - - for (j = 0; j < 2; j++) { - BMEdge *e1 = j ? e_new : e; - BMLoop *l; - - l = e1->l; - - if (UNLIKELY(!l)) { - BMESH_ASSERT(0); - break; - } - - do { - /* check this is an old face */ - if (BM_ELEM_API_FLAG_TEST(l->f, _FLAG_OVERLAP)) { - float f_center[3]; - - BM_face_calc_center_median(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); - } - } - - /* destroy the old faces */ - for (i = 0; i < BLI_array_len(oldfaces); i++) { - BM_face_verts_kill(bm, oldfaces[i]); - } - - /* fix boundaries a bit, doesn't work too well quite yet */ + BMVert *v_new, *v_other; + BMEdge *e_new; + BMFace **oldfaces = NULL; + BLI_array_staticdeclare(oldfaces, 32); + 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); + + /* do we have a multi-res layer? */ + if (cd_loop_mdisp_offset != -1) { + BMLoop *l; + int i; + + l = e->l; + do { + BLI_array_append(oldfaces, l->f); + l = l->radial_next; + } while (l != e->l); + + /* flag existing faces so we can differentiate oldfaces from new faces */ + for (i = 0; i < BLI_array_len(oldfaces); i++) { + BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP); + oldfaces[i] = BM_face_copy(bm, bm, oldfaces[i], true, true); + BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP); + } + } + + v_other = BM_edge_other_vert(e, v); + v_new = bmesh_kernel_split_edge_make_vert(bm, v, e, &e_new); + if (r_e != NULL) { + *r_e = e_new; + } + + BLI_assert(v_new != NULL); + BLI_assert(BM_vert_in_edge(e_new, v) && BM_vert_in_edge(e_new, v_new)); + BLI_assert(BM_vert_in_edge(e, v_new) && BM_vert_in_edge(e, v_other)); + + sub_v3_v3v3(v_new->co, v_other->co, v->co); + madd_v3_v3v3fl(v_new->co, v->co, v_new->co, fac); + + e_new->head.hflag = e->head.hflag; + BM_elem_attrs_copy(bm, bm, e, e_new); + + /* v->v_new->v2 */ + 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 (cd_loop_mdisp_offset != -1) { + int i, j; + + /* interpolate new/changed loop data from copied old faces */ + for (i = 0; i < BLI_array_len(oldfaces); i++) { + float f_center_old[3]; + + BM_face_calc_center_median(oldfaces[i], f_center_old); + + for (j = 0; j < 2; j++) { + BMEdge *e1 = j ? e_new : e; + BMLoop *l; + + l = e1->l; + + if (UNLIKELY(!l)) { + BMESH_ASSERT(0); + break; + } + + do { + /* check this is an old face */ + if (BM_ELEM_API_FLAG_TEST(l->f, _FLAG_OVERLAP)) { + float f_center[3]; + + BM_face_calc_center_median(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); + } + } + + /* destroy the old faces */ + for (i = 0; i < BLI_array_len(oldfaces); i++) { + BM_face_verts_kill(bm, oldfaces[i]); + } + + /* fix boundaries a bit, doesn't work too well quite yet */ #if 0 - for (j = 0; j < 2; j++) { - BMEdge *e1 = j ? e_new : e; - BMLoop *l, *l2; - - l = e1->l; - if (UNLIKELY(!l)) { - BMESH_ASSERT(0); - break; - } - - do { - BM_face_multires_bounds_smooth(bm, l->f); - l = l->radial_next; - } while (l != e1->l); - } + for (j = 0; j < 2; j++) { + BMEdge *e1 = j ? e_new : e; + BMLoop *l, *l2; + + l = e1->l; + if (UNLIKELY(!l)) { + BMESH_ASSERT(0); + break; + } + + do { + BM_face_multires_bounds_smooth(bm, l->f); + l = l->radial_next; + } while (l != e1->l); + } #endif - BLI_array_free(oldfaces); - } + BLI_array_free(oldfaces); + } - return v_new; + return v_new; } /** @@ -699,21 +701,21 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) * * \param r_varr: Optional array, verts in between (v1 -> v2) */ -BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr) +BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr) { - int i; - float percent; - BMVert *v_new = NULL; - - for (i = 0; i < numcuts; i++) { - percent = 1.0f / (float)(numcuts + 1 - i); - v_new = BM_edge_split(bm, e, e->v2, NULL, percent); - if (r_varr) { - /* fill in reverse order (v1 -> v2) */ - r_varr[numcuts - i - 1] = v_new; - } - } - return v_new; + int i; + float percent; + BMVert *v_new = NULL; + + for (i = 0; i < numcuts; i++) { + percent = 1.0f / (float)(numcuts + 1 - i); + v_new = BM_edge_split(bm, e, e->v2, NULL, percent); + if (r_varr) { + /* fill in reverse order (v1 -> v2) */ + r_varr[numcuts - i - 1] = v_new; + } + } + return v_new; } /** @@ -723,8 +725,8 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr) */ void BM_edge_verts_swap(BMEdge *e) { - SWAP(BMVert *, e->v1, e->v2); - SWAP(BMDiskLink, e->v1_disk_link, e->v2_disk_link); + SWAP(BMVert *, e->v1, e->v2); + SWAP(BMDiskLink, e->v1_disk_link, e->v2_disk_link); } #if 0 @@ -733,46 +735,46 @@ void BM_edge_verts_swap(BMEdge *e) */ bool BM_face_validate(BMFace *face, FILE *err) { - BMIter iter; - BLI_array_declare(verts); - BMVert **verts = NULL; - BMLoop *l; - int i, j; - bool ret = true; - - if (face->len == 2) { - fprintf(err, "warning: found two-edged face. face ptr: %p\n", face); - fflush(err); - } - - BLI_array_grow_items(verts, face->len); - BM_ITER_ELEM_INDEX (l, &iter, face, BM_LOOPS_OF_FACE, i) { - verts[i] = l->v; - if (l->e->v1 == l->e->v2) { - fprintf(err, "Found bmesh edge with identical verts!\n"); - fprintf(err, " edge ptr: %p, vert: %p\n", l->e, l->e->v1); - fflush(err); - ret = false; - } - } - - for (i = 0; i < face->len; i++) { - for (j = 0; j < face->len; j++) { - if (j == i) { - continue; - } - - if (verts[i] == verts[j]) { - fprintf(err, "Found duplicate verts in bmesh face!\n"); - fprintf(err, " face ptr: %p, vert: %p\n", face, verts[i]); - fflush(err); - ret = false; - } - } - } - - BLI_array_free(verts); - return ret; + BMIter iter; + BLI_array_declare(verts); + BMVert **verts = NULL; + BMLoop *l; + int i, j; + bool ret = true; + + if (face->len == 2) { + fprintf(err, "warning: found two-edged face. face ptr: %p\n", face); + fflush(err); + } + + BLI_array_grow_items(verts, face->len); + BM_ITER_ELEM_INDEX (l, &iter, face, BM_LOOPS_OF_FACE, i) { + verts[i] = l->v; + if (l->e->v1 == l->e->v2) { + fprintf(err, "Found bmesh edge with identical verts!\n"); + fprintf(err, " edge ptr: %p, vert: %p\n", l->e, l->e->v1); + fflush(err); + ret = false; + } + } + + for (i = 0; i < face->len; i++) { + for (j = 0; j < face->len; j++) { + if (j == i) { + continue; + } + + if (verts[i] == verts[j]) { + fprintf(err, "Found duplicate verts in bmesh face!\n"); + fprintf(err, " face ptr: %p, vert: %p\n", face, verts[i]); + fflush(err); + ret = false; + } + } + } + + BLI_array_free(verts); + return ret; } #endif @@ -790,32 +792,30 @@ bool BM_face_validate(BMFace *face, FILE *err) * * \note #BM_edge_rotate_check must have already run. */ -void BM_edge_calc_rotate( - BMEdge *e, const bool ccw, - BMLoop **r_l1, BMLoop **r_l2) +void BM_edge_calc_rotate(BMEdge *e, const bool ccw, BMLoop **r_l1, BMLoop **r_l2) { - BMVert *v1, *v2; - BMFace *fa, *fb; + BMVert *v1, *v2; + BMFace *fa, *fb; - /* this should have already run */ - BLI_assert(BM_edge_rotate_check(e) == true); + /* this should have already run */ + BLI_assert(BM_edge_rotate_check(e) == true); - /* we know this will work */ - BM_edge_face_pair(e, &fa, &fb); + /* we know this will work */ + BM_edge_face_pair(e, &fa, &fb); - /* so we can use ccw variable correctly, - * otherwise we could use the edges verts direct */ - BM_edge_ordered_verts(e, &v1, &v2); + /* so we can use ccw variable correctly, + * otherwise we could use the edges verts direct */ + BM_edge_ordered_verts(e, &v1, &v2); - /* we could swap the verts _or_ the faces, swapping faces - * gives more predictable results since that way the next vert - * just stitches from face fa / fb */ - if (!ccw) { - SWAP(BMFace *, fa, fb); - } + /* we could swap the verts _or_ the faces, swapping faces + * gives more predictable results since that way the next vert + * just stitches from face fa / fb */ + if (!ccw) { + SWAP(BMFace *, fa, fb); + } - *r_l1 = BM_face_other_vert_loop(fb, v2, v1); - *r_l2 = BM_face_other_vert_loop(fa, v1, v2); + *r_l1 = BM_face_other_vert_loop(fb, v2, v1); + *r_l2 = BM_face_other_vert_loop(fa, v1, v2); } /** @@ -826,33 +826,33 @@ void BM_edge_calc_rotate( */ bool BM_edge_rotate_check(BMEdge *e) { - BMFace *fa, *fb; - if (BM_edge_face_pair(e, &fa, &fb)) { - BMLoop *la, *lb; - - la = BM_face_other_vert_loop(fa, e->v2, e->v1); - lb = BM_face_other_vert_loop(fb, e->v2, e->v1); - - /* check that the next vert in both faces isn't the same - * (ie - the next edge doesn't share the same faces). - * since we can't rotate usefully in this case. */ - if (la->v == lb->v) { - return false; - } - - /* mirror of the check above but in the opposite direction */ - la = BM_face_other_vert_loop(fa, e->v1, e->v2); - lb = BM_face_other_vert_loop(fb, e->v1, e->v2); - - if (la->v == lb->v) { - return false; - } - - return true; - } - else { - return false; - } + BMFace *fa, *fb; + if (BM_edge_face_pair(e, &fa, &fb)) { + BMLoop *la, *lb; + + la = BM_face_other_vert_loop(fa, e->v2, e->v1); + lb = BM_face_other_vert_loop(fb, e->v2, e->v1); + + /* check that the next vert in both faces isn't the same + * (ie - the next edge doesn't share the same faces). + * since we can't rotate usefully in this case. */ + if (la->v == lb->v) { + return false; + } + + /* mirror of the check above but in the opposite direction */ + la = BM_face_other_vert_loop(fa, e->v1, e->v2); + lb = BM_face_other_vert_loop(fb, e->v1, e->v2); + + if (la->v == lb->v) { + return false; + } + + return true; + } + else { + return false; + } } /** @@ -868,101 +868,97 @@ bool BM_edge_rotate_check(BMEdge *e) */ bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2) { - /* note: for these vars 'old' just means initial edge state. */ + /* note: for these vars 'old' just means initial edge state. */ - float ed_dir_old[3]; /* edge vector */ - float ed_dir_new[3]; /* edge vector */ - float ed_dir_new_flip[3]; /* edge vector */ + float ed_dir_old[3]; /* edge vector */ + float ed_dir_new[3]; /* edge vector */ + float ed_dir_new_flip[3]; /* edge vector */ - float ed_dir_v1_old[3]; - float ed_dir_v2_old[3]; + float ed_dir_v1_old[3]; + float ed_dir_v2_old[3]; - float ed_dir_v1_new[3]; - float ed_dir_v2_new[3]; + float ed_dir_v1_new[3]; + float ed_dir_v2_new[3]; - float cross_old[3]; - float cross_new[3]; + float cross_old[3]; + float cross_new[3]; - /* original verts - these will be in the edge 'e' */ - BMVert *v1_old, *v2_old; + /* original verts - these will be in the edge 'e' */ + BMVert *v1_old, *v2_old; - /* verts from the loops passed */ + /* verts from the loops passed */ - BMVert *v1, *v2; - /* these are the opposite verts - the verts that _would_ be used if 'ccw' was inverted*/ - BMVert *v1_alt, *v2_alt; + BMVert *v1, *v2; + /* these are the opposite verts - the verts that _would_ be used if 'ccw' was inverted*/ + BMVert *v1_alt, *v2_alt; - /* this should have already run */ - BLI_assert(BM_edge_rotate_check(e) == true); + /* this should have already run */ + BLI_assert(BM_edge_rotate_check(e) == true); - BM_edge_ordered_verts(e, &v1_old, &v2_old); + BM_edge_ordered_verts(e, &v1_old, &v2_old); - v1 = l1->v; - v2 = l2->v; + v1 = l1->v; + v2 = l2->v; - /* get the next vert along */ - v1_alt = BM_face_other_vert_loop(l1->f, v1_old, v1)->v; - v2_alt = BM_face_other_vert_loop(l2->f, v2_old, v2)->v; + /* get the next vert along */ + v1_alt = BM_face_other_vert_loop(l1->f, v1_old, v1)->v; + v2_alt = BM_face_other_vert_loop(l2->f, v2_old, v2)->v; - /* normalize all so comparisons are scale independent */ + /* normalize all so comparisons are scale independent */ - BLI_assert(BM_edge_exists(v1_old, v1)); - BLI_assert(BM_edge_exists(v1, v1_alt)); + BLI_assert(BM_edge_exists(v1_old, v1)); + BLI_assert(BM_edge_exists(v1, v1_alt)); - BLI_assert(BM_edge_exists(v2_old, v2)); - BLI_assert(BM_edge_exists(v2, v2_alt)); + BLI_assert(BM_edge_exists(v2_old, v2)); + BLI_assert(BM_edge_exists(v2, v2_alt)); - /* old and new edge vecs */ - sub_v3_v3v3(ed_dir_old, v1_old->co, v2_old->co); - sub_v3_v3v3(ed_dir_new, v1->co, v2->co); - normalize_v3(ed_dir_old); - normalize_v3(ed_dir_new); + /* old and new edge vecs */ + sub_v3_v3v3(ed_dir_old, v1_old->co, v2_old->co); + sub_v3_v3v3(ed_dir_new, v1->co, v2->co); + normalize_v3(ed_dir_old); + normalize_v3(ed_dir_new); - /* old edge corner vecs */ - sub_v3_v3v3(ed_dir_v1_old, v1_old->co, v1->co); - sub_v3_v3v3(ed_dir_v2_old, v2_old->co, v2->co); - normalize_v3(ed_dir_v1_old); - normalize_v3(ed_dir_v2_old); + /* old edge corner vecs */ + sub_v3_v3v3(ed_dir_v1_old, v1_old->co, v1->co); + sub_v3_v3v3(ed_dir_v2_old, v2_old->co, v2->co); + normalize_v3(ed_dir_v1_old); + normalize_v3(ed_dir_v2_old); - /* old edge corner vecs */ - sub_v3_v3v3(ed_dir_v1_new, v1->co, v1_alt->co); - sub_v3_v3v3(ed_dir_v2_new, v2->co, v2_alt->co); - normalize_v3(ed_dir_v1_new); - normalize_v3(ed_dir_v2_new); + /* old edge corner vecs */ + sub_v3_v3v3(ed_dir_v1_new, v1->co, v1_alt->co); + sub_v3_v3v3(ed_dir_v2_new, v2->co, v2_alt->co); + normalize_v3(ed_dir_v1_new); + normalize_v3(ed_dir_v2_new); - /* compare */ - cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v1_old); - cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v1_new); - if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */ - return false; - } - cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v2_old); - cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v2_new); - if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */ - return false; - } + /* compare */ + cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v1_old); + cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v1_new); + if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */ + return false; + } + cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v2_old); + cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v2_new); + if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */ + return false; + } - negate_v3_v3(ed_dir_new_flip, ed_dir_new); + negate_v3_v3(ed_dir_new_flip, ed_dir_new); - /* result is zero area corner */ - if ((dot_v3v3(ed_dir_new, ed_dir_v1_new) > 0.999f) || - (dot_v3v3(ed_dir_new_flip, ed_dir_v2_new) > 0.999f)) - { - return false; - } + /* result is zero area corner */ + if ((dot_v3v3(ed_dir_new, ed_dir_v1_new) > 0.999f) || + (dot_v3v3(ed_dir_new_flip, ed_dir_v2_new) > 0.999f)) { + return false; + } - return true; + return true; } -bool BM_edge_rotate_check_beauty( - BMEdge *e, - BMLoop *l1, BMLoop *l2) +bool BM_edge_rotate_check_beauty(BMEdge *e, BMLoop *l1, BMLoop *l2) { - /* Stupid check for now: - * Could compare angles of surrounding edges - * before & after, but this is OK.*/ - return (len_squared_v3v3(e->v1->co, e->v2->co) > - len_squared_v3v3(l1->v->co, l2->v->co)); + /* Stupid check for now: + * Could compare angles of surrounding edges + * before & after, but this is OK.*/ + return (len_squared_v3v3(e->v1->co, e->v2->co) > len_squared_v3v3(l1->v->co, l2->v->co)); } /** @@ -981,115 +977,113 @@ bool BM_edge_rotate_check_beauty( */ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag) { - BMVert *v1, *v2; - BMLoop *l1, *l2; - BMFace *f; - BMEdge *e_new = NULL; - char f_active_prev = 0; - char f_hflag_prev_1; - char f_hflag_prev_2; - - if (!BM_edge_rotate_check(e)) { - return NULL; - } - - BM_edge_calc_rotate(e, ccw, &l1, &l2); - - /* the loops will be freed so assign verts */ - v1 = l1->v; - v2 = l2->v; - - /* --------------------------------------- */ - /* Checking Code - make sure we can rotate */ - - if (check_flag & BM_EDGEROT_CHECK_BEAUTY) { - if (!BM_edge_rotate_check_beauty(e, l1, l2)) { - return NULL; - } - } - - /* check before applying */ - if (check_flag & BM_EDGEROT_CHECK_EXISTS) { - if (BM_edge_exists(v1, v2)) { - return NULL; - } - } - - /* slowest, check last */ - if (check_flag & BM_EDGEROT_CHECK_DEGENERATE) { - if (!BM_edge_rotate_check_degenerate(e, l1, l2)) { - return NULL; - } - } - /* Done Checking */ - /* ------------- */ - - - - /* --------------- */ - /* Rotate The Edge */ - - /* first create the new edge, this is so we can copy the customdata from the old one - * if splice if disabled, always add in a new edge even if theres one there. */ - e_new = BM_edge_create(bm, v1, v2, e, (check_flag & BM_EDGEROT_CHECK_SPLICE) ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP); - - f_hflag_prev_1 = l1->f->head.hflag; - f_hflag_prev_2 = l2->f->head.hflag; - - /* maintain active face */ - if (bm->act_face == l1->f) { - f_active_prev = 1; - } - else if (bm->act_face == l2->f) { - f_active_prev = 2; - } - - const bool is_flipped = !BM_edge_is_contiguous(e); - - /* don't delete the edge, manually remove the edge after so we can copy its attributes */ - f = BM_faces_join_pair(bm, BM_face_edge_share_loop(l1->f, e), BM_face_edge_share_loop(l2->f, e), true); - - if (f == NULL) { - return NULL; - } - - /* note, this assumes joining the faces _didnt_ also remove the verts. - * the #BM_edge_rotate_check will ensure this, but its possibly corrupt state or future edits - * break this */ - if ((l1 = BM_face_vert_share_loop(f, v1)) && - (l2 = BM_face_vert_share_loop(f, v2)) && - BM_face_split(bm, f, l1, l2, NULL, NULL, true)) - { - /* we should really be able to know the faces some other way, - * rather then fetching them back from the edge, but this is predictable - * where using the return values from face split isn't. - campbell */ - BMFace *fa, *fb; - if (BM_edge_face_pair(e_new, &fa, &fb)) { - fa->head.hflag = f_hflag_prev_1; - fb->head.hflag = f_hflag_prev_2; - - if (f_active_prev == 1) { - bm->act_face = fa; - } - else if (f_active_prev == 2) { - bm->act_face = fb; - } - - if (is_flipped) { - BM_face_normal_flip(bm, fb); - - if (ccw) { - /* needed otherwise ccw toggles direction */ - e_new->l = e_new->l->radial_next; - } - } - } - } - else { - return NULL; - } - - return e_new; + BMVert *v1, *v2; + BMLoop *l1, *l2; + BMFace *f; + BMEdge *e_new = NULL; + char f_active_prev = 0; + char f_hflag_prev_1; + char f_hflag_prev_2; + + if (!BM_edge_rotate_check(e)) { + return NULL; + } + + BM_edge_calc_rotate(e, ccw, &l1, &l2); + + /* the loops will be freed so assign verts */ + v1 = l1->v; + v2 = l2->v; + + /* --------------------------------------- */ + /* Checking Code - make sure we can rotate */ + + if (check_flag & BM_EDGEROT_CHECK_BEAUTY) { + if (!BM_edge_rotate_check_beauty(e, l1, l2)) { + return NULL; + } + } + + /* check before applying */ + if (check_flag & BM_EDGEROT_CHECK_EXISTS) { + if (BM_edge_exists(v1, v2)) { + return NULL; + } + } + + /* slowest, check last */ + if (check_flag & BM_EDGEROT_CHECK_DEGENERATE) { + if (!BM_edge_rotate_check_degenerate(e, l1, l2)) { + return NULL; + } + } + /* Done Checking */ + /* ------------- */ + + /* --------------- */ + /* Rotate The Edge */ + + /* first create the new edge, this is so we can copy the customdata from the old one + * if splice if disabled, always add in a new edge even if theres one there. */ + e_new = BM_edge_create( + bm, v1, v2, e, (check_flag & BM_EDGEROT_CHECK_SPLICE) ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP); + + f_hflag_prev_1 = l1->f->head.hflag; + f_hflag_prev_2 = l2->f->head.hflag; + + /* maintain active face */ + if (bm->act_face == l1->f) { + f_active_prev = 1; + } + else if (bm->act_face == l2->f) { + f_active_prev = 2; + } + + const bool is_flipped = !BM_edge_is_contiguous(e); + + /* don't delete the edge, manually remove the edge after so we can copy its attributes */ + f = BM_faces_join_pair( + bm, BM_face_edge_share_loop(l1->f, e), BM_face_edge_share_loop(l2->f, e), true); + + if (f == NULL) { + return NULL; + } + + /* note, this assumes joining the faces _didnt_ also remove the verts. + * the #BM_edge_rotate_check will ensure this, but its possibly corrupt state or future edits + * break this */ + if ((l1 = BM_face_vert_share_loop(f, v1)) && (l2 = BM_face_vert_share_loop(f, v2)) && + BM_face_split(bm, f, l1, l2, NULL, NULL, true)) { + /* we should really be able to know the faces some other way, + * rather then fetching them back from the edge, but this is predictable + * where using the return values from face split isn't. - campbell */ + BMFace *fa, *fb; + if (BM_edge_face_pair(e_new, &fa, &fb)) { + fa->head.hflag = f_hflag_prev_1; + fb->head.hflag = f_hflag_prev_2; + + if (f_active_prev == 1) { + bm->act_face = fa; + } + else if (f_active_prev == 2) { + bm->act_face = fb; + } + + if (is_flipped) { + BM_face_normal_flip(bm, fb); + + if (ccw) { + /* needed otherwise ccw toggles direction */ + e_new->l = e_new->l->radial_next; + } + } + } + } + else { + return NULL; + } + + return e_new; } /** @@ -1097,15 +1091,15 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_f */ BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep) { - return bmesh_kernel_unglue_region_make_vert(bm, l_sep); + return bmesh_kernel_unglue_region_make_vert(bm, l_sep); } BMVert *BM_face_loop_separate_multi_isolated(BMesh *bm, BMLoop *l_sep) { - return bmesh_kernel_unglue_region_make_vert_multi_isolated(bm, l_sep); + return bmesh_kernel_unglue_region_make_vert_multi_isolated(bm, l_sep); } BMVert *BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len) { - return bmesh_kernel_unglue_region_make_vert_multi(bm, larr, larr_len); + return bmesh_kernel_unglue_region_make_vert_multi(bm, larr, larr_len); } diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h index 425770a8c32..3d4eefbb598 100644 --- a/source/blender/bmesh/intern/bmesh_mods.h +++ b/source/blender/bmesh/intern/bmesh_mods.h @@ -27,31 +27,43 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v); BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_del); - /** see: bmesh_polygon_edgenet.h for #BM_face_split_edgenet */ -BMFace *BM_face_split( - BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - BMLoop **r_l, - BMEdge *example, const bool no_double); - -BMFace *BM_face_split_n( - BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - float cos[][3], int n, -BMLoop **r_l, BMEdge *example); - -BMEdge *BM_vert_collapse_faces( - BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, - const bool do_del, const bool join_faces, const bool kill_degenerate_faces); -BMEdge *BM_vert_collapse_edge( - BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool kill_degenerate_faces); - -BMVert *BM_edge_collapse( - BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool kill_degenerate_faces); +BMFace *BM_face_split(BMesh *bm, + BMFace *f, + BMLoop *l_a, + BMLoop *l_b, + BMLoop **r_l, + BMEdge *example, + const bool no_double); + +BMFace *BM_face_split_n(BMesh *bm, + BMFace *f, + BMLoop *l_a, + BMLoop *l_b, + float cos[][3], + int n, + BMLoop **r_l, + BMEdge *example); + +BMEdge *BM_vert_collapse_faces(BMesh *bm, + BMEdge *e_kill, + BMVert *v_kill, + float fac, + const bool do_del, + const bool join_faces, + const bool kill_degenerate_faces); +BMEdge *BM_vert_collapse_edge(BMesh *bm, + BMEdge *e_kill, + BMVert *v_kill, + const bool do_del, + const bool kill_degenerate_faces); + +BMVert *BM_edge_collapse(BMesh *bm, + BMEdge *e_kill, + BMVert *v_kill, + const bool do_del, + const bool kill_degenerate_faces); BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent); @@ -59,29 +71,25 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr); void BM_edge_verts_swap(BMEdge *e); -bool BM_face_validate(BMFace *face, FILE *err); - -void BM_edge_calc_rotate( - BMEdge *e, const bool ccw, - BMLoop **r_l1, BMLoop **r_l2); -bool BM_edge_rotate_check(BMEdge *e); -bool BM_edge_rotate_check_degenerate( - BMEdge *e, - BMLoop *l1, BMLoop *l2); -bool BM_edge_rotate_check_beauty( - BMEdge *e, - BMLoop *l1, BMLoop *l2); +bool BM_face_validate(BMFace *face, FILE *err); + +void BM_edge_calc_rotate(BMEdge *e, const bool ccw, BMLoop **r_l1, BMLoop **r_l2); +bool BM_edge_rotate_check(BMEdge *e); +bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2); +bool BM_edge_rotate_check_beauty(BMEdge *e, BMLoop *l1, BMLoop *l2); BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag); /* flags for BM_edge_rotate */ enum { - BM_EDGEROT_CHECK_EXISTS = (1 << 0), /* disallow to rotate when the new edge matches an existing one */ - BM_EDGEROT_CHECK_SPLICE = (1 << 1), /* overrides existing check, if the edge already, rotate and merge them */ - BM_EDGEROT_CHECK_DEGENERATE = (1 << 2), /* disallow creating bow-tie, concave or zero area faces */ - BM_EDGEROT_CHECK_BEAUTY = (1 << 3), /* disallow to rotate into ugly topology */ + BM_EDGEROT_CHECK_EXISTS = + (1 << 0), /* disallow to rotate when the new edge matches an existing one */ + BM_EDGEROT_CHECK_SPLICE = + (1 << 1), /* overrides existing check, if the edge already, rotate and merge them */ + BM_EDGEROT_CHECK_DEGENERATE = (1 + << 2), /* disallow creating bow-tie, concave or zero area faces */ + BM_EDGEROT_CHECK_BEAUTY = (1 << 3), /* disallow to rotate into ugly topology */ }; - BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep); BMVert *BM_face_loop_separate_multi_isolated(BMesh *bm, BMLoop *l_sep); BMVert *BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len); diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 4ca8e02e94d..2114f9ebd3d 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -96,20 +96,20 @@ /* enums shared between multiple operators */ static BMO_FlagSet bmo_enum_axis_xyz[] = { - {0, "X"}, - {1, "Y"}, - {2, "Z"}, - {0, NULL}, + {0, "X"}, + {1, "Y"}, + {2, "Z"}, + {0, NULL}, }; static BMO_FlagSet bmo_enum_falloff_type[] = { - {SUBD_FALLOFF_SMOOTH, "SMOOTH"}, - {SUBD_FALLOFF_SPHERE, "SPHERE"}, - {SUBD_FALLOFF_ROOT, "ROOT"}, - {SUBD_FALLOFF_SHARP, "SHARP"}, - {SUBD_FALLOFF_LIN, "LINEAR"}, - {SUBD_FALLOFF_INVSQUARE, "INVERSE_SQUARE"}, - {0, NULL}, + {SUBD_FALLOFF_SMOOTH, "SMOOTH"}, + {SUBD_FALLOFF_SPHERE, "SPHERE"}, + {SUBD_FALLOFF_ROOT, "ROOT"}, + {SUBD_FALLOFF_SHARP, "SHARP"}, + {SUBD_FALLOFF_LIN, "LINEAR"}, + {SUBD_FALLOFF_INVSQUARE, "INVERSE_SQUARE"}, + {0, NULL}, }; /* @@ -118,22 +118,22 @@ static BMO_FlagSet bmo_enum_falloff_type[] = { * Smooths vertices by using a basic vertex averaging scheme. */ static BMOpDefine bmo_smooth_vert_def = { - "smooth_vert", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {"factor", BMO_OP_SLOT_FLT}, /* smoothing factor */ - {"mirror_clip_x", BMO_OP_SLOT_BOOL}, /* set vertices close to the x axis before the operation to 0 */ - {"mirror_clip_y", BMO_OP_SLOT_BOOL}, /* set vertices close to the y axis before the operation to 0 */ - {"mirror_clip_z", BMO_OP_SLOT_BOOL}, /* set vertices close to the z axis before the operation to 0 */ - {"clip_dist", BMO_OP_SLOT_FLT}, /* clipping threshold for the above three slots */ - {"use_axis_x", BMO_OP_SLOT_BOOL}, /* smooth vertices along X axis */ - {"use_axis_y", BMO_OP_SLOT_BOOL}, /* smooth vertices along Y axis */ - {"use_axis_z", BMO_OP_SLOT_BOOL}, /* smooth vertices along Z axis */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_smooth_vert_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC), + "smooth_vert", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"factor", BMO_OP_SLOT_FLT}, /* smoothing factor */ + {"mirror_clip_x", BMO_OP_SLOT_BOOL}, /* set vertices close to the x axis before the operation to 0 */ + {"mirror_clip_y", BMO_OP_SLOT_BOOL}, /* set vertices close to the y axis before the operation to 0 */ + {"mirror_clip_z", BMO_OP_SLOT_BOOL}, /* set vertices close to the z axis before the operation to 0 */ + {"clip_dist", BMO_OP_SLOT_FLT}, /* clipping threshold for the above three slots */ + {"use_axis_x", BMO_OP_SLOT_BOOL}, /* smooth vertices along X axis */ + {"use_axis_y", BMO_OP_SLOT_BOOL}, /* smooth vertices along Y axis */ + {"use_axis_z", BMO_OP_SLOT_BOOL}, /* smooth vertices along Z axis */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_smooth_vert_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* @@ -143,20 +143,20 @@ static BMOpDefine bmo_smooth_vert_def = { * Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow. */ static BMOpDefine bmo_smooth_laplacian_vert_def = { - "smooth_laplacian_vert", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {"lambda_factor", BMO_OP_SLOT_FLT}, /* lambda param */ - {"lambda_border", BMO_OP_SLOT_FLT}, /* lambda param in border */ - {"use_x", BMO_OP_SLOT_BOOL}, /* Smooth object along X axis */ - {"use_y", BMO_OP_SLOT_BOOL}, /* Smooth object along Y axis */ - {"use_z", BMO_OP_SLOT_BOOL}, /* Smooth object along Z axis */ - {"preserve_volume", BMO_OP_SLOT_BOOL}, /* Apply volume preservation after smooth */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_smooth_laplacian_vert_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC), + "smooth_laplacian_vert", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"lambda_factor", BMO_OP_SLOT_FLT}, /* lambda param */ + {"lambda_border", BMO_OP_SLOT_FLT}, /* lambda param in border */ + {"use_x", BMO_OP_SLOT_BOOL}, /* Smooth object along X axis */ + {"use_y", BMO_OP_SLOT_BOOL}, /* Smooth object along Y axis */ + {"use_z", BMO_OP_SLOT_BOOL}, /* Smooth object along Z axis */ + {"preserve_volume", BMO_OP_SLOT_BOOL}, /* Apply volume preservation after smooth */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_smooth_laplacian_vert_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* @@ -165,15 +165,15 @@ static BMOpDefine bmo_smooth_laplacian_vert_def = { * Computes an "outside" normal for the specified input faces. */ static BMOpDefine bmo_recalc_face_normals_def = { - "recalc_face_normals", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_recalc_face_normals_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC), + "recalc_face_normals", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_recalc_face_normals_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* @@ -182,20 +182,20 @@ static BMOpDefine bmo_recalc_face_normals_def = { * Iteratively flatten faces. */ static BMOpDefine bmo_planar_faces_def = { - "planar_faces", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */ - {"iterations", BMO_OP_SLOT_INT}, /* Number of times to flatten faces (for when connected faces are used) */ - {"factor", BMO_OP_SLOT_FLT}, /* Influence for making planar each iteration */ - {{'\0'}}, - }, - /* slots_out */ - {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */ - {{'\0'}}, - }, - bmo_planar_faces_exec, - (BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "planar_faces", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */ + {"iterations", BMO_OP_SLOT_INT}, /* Number of times to flatten faces (for when connected faces are used) */ + {"factor", BMO_OP_SLOT_FLT}, /* Influence for making planar each iteration */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */ + {{'\0'}}, + }, + bmo_planar_faces_exec, + (BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -209,21 +209,21 @@ static BMOpDefine bmo_planar_faces_def = { * otherwise it spits out faces. */ static BMOpDefine bmo_region_extend_def = { - "region_extend", - /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ - {"use_contract", BMO_OP_SLOT_BOOL}, /* find boundary inside the regions, not outside. */ - {"use_faces", BMO_OP_SLOT_BOOL}, /* extend from faces instead of edges */ - {"use_face_step", BMO_OP_SLOT_BOOL}, /* step over connected faces */ - {{'\0'}}, - }, - /* slots_out */ - {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */ - {{'\0'}}, - }, - bmo_region_extend_exec, - (BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "region_extend", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"use_contract", BMO_OP_SLOT_BOOL}, /* find boundary inside the regions, not outside. */ + {"use_faces", BMO_OP_SLOT_BOOL}, /* extend from faces instead of edges */ + {"use_face_step", BMO_OP_SLOT_BOOL}, /* step over connected faces */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */ + {{'\0'}}, + }, + bmo_region_extend_exec, + (BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -233,21 +233,21 @@ static BMOpDefine bmo_region_extend_def = { * Simple example: ``[/] becomes [|] then [\]``. */ static BMOpDefine bmo_rotate_edges_def = { - "rotate_edges", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate edge counter-clockwise if true, otherwise clockwise */ - {{'\0'}}, - }, - /* slots_out */ - {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly spun edges */ - {{'\0'}}, - }, - bmo_rotate_edges_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "rotate_edges", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate edge counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly spun edges */ + {{'\0'}}, + }, + bmo_rotate_edges_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -257,16 +257,16 @@ static BMOpDefine bmo_rotate_edges_def = { * This has the effect of flipping the normal. */ static BMOpDefine bmo_reverse_faces_def = { - "reverse_faces", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"flip_multires", BMO_OP_SLOT_BOOL}, /* maintain multi-res offset */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_reverse_faces_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC), + "reverse_faces", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"flip_multires", BMO_OP_SLOT_BOOL}, /* maintain multi-res offset */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_reverse_faces_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* @@ -276,22 +276,22 @@ static BMOpDefine bmo_reverse_faces_def = { * This creates a 2-valence vert. */ static BMOpDefine bmo_bisect_edges_def = { - "bisect_edges", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - {"cuts", BMO_OP_SLOT_INT}, /* number of cuts */ - {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}}, - {{'\0'}}, - }, - /* slots_out */ - {{"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* newly created vertices and edges */ - {{'\0'}}, - }, - bmo_bisect_edges_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "bisect_edges", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"cuts", BMO_OP_SLOT_INT}, /* number of cuts */ + {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* newly created vertices and edges */ + {{'\0'}}, + }, + bmo_bisect_edges_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -302,24 +302,24 @@ static BMOpDefine bmo_bisect_edges_def = { * parameter (which defines the minimum distance for welding to happen). */ static BMOpDefine bmo_mirror_def = { - "mirror", - /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ - {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining the mirror transformation */ - {"merge_dist", BMO_OP_SLOT_FLT}, /* maximum distance for merging. does no merging if 0. */ - {"axis", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_axis_xyz}, /* the axis to use. */ - {"mirror_u", BMO_OP_SLOT_BOOL}, /* mirror UVs across the u axis */ - {"mirror_v", BMO_OP_SLOT_BOOL}, /* mirror UVs across the v axis */ - {{'\0'}}, - }, - /* slots_out */ - {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry, mirrored */ - {{'\0'}}, - }, - bmo_mirror_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "mirror", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining the mirror transformation */ + {"merge_dist", BMO_OP_SLOT_FLT}, /* maximum distance for merging. does no merging if 0. */ + {"axis", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_axis_xyz}, /* the axis to use. */ + {"mirror_u", BMO_OP_SLOT_BOOL}, /* mirror UVs across the u axis */ + {"mirror_v", BMO_OP_SLOT_BOOL}, /* mirror UVs across the v axis */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry, mirrored */ + {{'\0'}}, + }, + bmo_mirror_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -332,19 +332,19 @@ static BMOpDefine bmo_mirror_def = { * with vertices in that set. */ static BMOpDefine bmo_find_doubles_def = { - "find_doubles", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {"keep_verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* list of verts to keep */ - {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ - {{'\0'}}, - }, - /* slots_out */ - {{"targetmap.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, - {{'\0'}}, - }, - bmo_find_doubles_exec, - (BMO_OPTYPE_FLAG_NOP), + "find_doubles", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"keep_verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* list of verts to keep */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, + }, + /* slots_out */ + {{"targetmap.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, + bmo_find_doubles_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -354,18 +354,18 @@ static BMOpDefine bmo_find_doubles_def = { * using the weld verts bmop. */ static BMOpDefine bmo_remove_doubles_def = { - "remove_doubles", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ - {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_remove_doubles_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "remove_doubles", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_remove_doubles_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -376,18 +376,18 @@ static BMOpDefine bmo_remove_doubles_def = { * **verts** to one in **verts**. */ static BMOpDefine bmo_automerge_def = { - "automerge", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ - {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_automerge_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "automerge", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_automerge_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -396,18 +396,18 @@ static BMOpDefine bmo_automerge_def = { * Collapses connected vertices */ static BMOpDefine bmo_collapse_def = { - "collapse", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - {"uvs", BMO_OP_SLOT_BOOL}, /* also collapse UVs and such */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_collapse_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "collapse", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"uvs", BMO_OP_SLOT_BOOL}, /* also collapse UVs and such */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_collapse_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -416,15 +416,15 @@ static BMOpDefine bmo_collapse_def = { * Merge uv/vcols at a specific vertex. */ static BMOpDefine bmo_pointmerge_facedata_def = { - "pointmerge_facedata", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {"vert_snap", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | (int)BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* snap vertex */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_pointmerge_facedata_exec, - (BMO_OPTYPE_FLAG_NOP), + "pointmerge_facedata", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"vert_snap", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | (int)BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* snap vertex */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_pointmerge_facedata_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -435,14 +435,14 @@ static BMOpDefine bmo_pointmerge_facedata_def = { * the vert_snap_to_bb_center is just too long). */ static BMOpDefine bmo_average_vert_facedata_def = { - "average_vert_facedata", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_average_vert_facedata_exec, - (BMO_OPTYPE_FLAG_NOP), + "average_vert_facedata", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_average_vert_facedata_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -451,18 +451,18 @@ static BMOpDefine bmo_average_vert_facedata_def = { * Merge verts together at a point. */ static BMOpDefine bmo_pointmerge_def = { - "pointmerge", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices (all verts will be merged into the first). */ - {"merge_co", BMO_OP_SLOT_VEC}, /* Position to merge at. */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_pointmerge_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "pointmerge", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices (all verts will be merged into the first). */ + {"merge_co", BMO_OP_SLOT_VEC}, /* Position to merge at. */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_pointmerge_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -471,14 +471,14 @@ static BMOpDefine bmo_pointmerge_def = { * Collapses connected UV vertices. */ static BMOpDefine bmo_collapse_uvs_def = { - "collapse_uvs", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_collapse_uvs_exec, - (BMO_OPTYPE_FLAG_NOP), + "collapse_uvs", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_collapse_uvs_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -489,18 +489,18 @@ static BMOpDefine bmo_collapse_uvs_def = { * they weld with. */ static BMOpDefine bmo_weld_verts_def = { - "weld_verts", - /* slots_in */ - /* maps welded vertices to verts they should weld to */ - {{"targetmap", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_weld_verts_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "weld_verts", + /* slots_in */ + /* maps welded vertices to verts they should weld to */ + {{"targetmap", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_weld_verts_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -510,17 +510,17 @@ static BMOpDefine bmo_weld_verts_def = { * for click-create-vertex. */ static BMOpDefine bmo_create_vert_def = { - "create_vert", - /* slots_in */ - {{"co", BMO_OP_SLOT_VEC}, /* the coordinate of the new vert */ - {{'\0'}}, - }, - /* slots_out */ - {{"vert.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* the new vert */ - {{'\0'}}, - }, - bmo_create_vert_exec, - (BMO_OPTYPE_FLAG_NOP), + "create_vert", + /* slots_in */ + {{"co", BMO_OP_SLOT_VEC}, /* the coordinate of the new vert */ + {{'\0'}}, + }, + /* slots_out */ + {{"vert.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* the new vert */ + {{'\0'}}, + }, + bmo_create_vert_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -530,27 +530,27 @@ static BMOpDefine bmo_create_vert_def = { * to angle threshold and delimiters. */ static BMOpDefine bmo_join_triangles_def = { - "join_triangles", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */ - {"cmp_seam", BMO_OP_SLOT_BOOL}, - {"cmp_sharp", BMO_OP_SLOT_BOOL}, - {"cmp_uvs", BMO_OP_SLOT_BOOL}, - {"cmp_vcols", BMO_OP_SLOT_BOOL}, - {"cmp_materials", BMO_OP_SLOT_BOOL}, - {"angle_face_threshold", BMO_OP_SLOT_FLT}, - {"angle_shape_threshold", BMO_OP_SLOT_FLT}, - {{'\0'}}, - }, - /* slots_out */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* joined faces */ - {{'\0'}}, - }, - bmo_join_triangles_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "join_triangles", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */ + {"cmp_seam", BMO_OP_SLOT_BOOL}, + {"cmp_sharp", BMO_OP_SLOT_BOOL}, + {"cmp_uvs", BMO_OP_SLOT_BOOL}, + {"cmp_vcols", BMO_OP_SLOT_BOOL}, + {"cmp_materials", BMO_OP_SLOT_BOOL}, + {"angle_face_threshold", BMO_OP_SLOT_FLT}, + {"angle_shape_threshold", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* joined faces */ + {{'\0'}}, + }, + bmo_join_triangles_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -564,49 +564,49 @@ static BMOpDefine bmo_join_triangles_def = { * become a wire edge. */ static BMOpDefine bmo_contextual_create_def = { - "contextual_create", - /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry. */ - {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ - {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth to use */ - {{'\0'}}, - }, - /* slots_out */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* newly-made face(s) */ - /* note, this is for stand-alone edges only, not edges which are apart of newly created faces */ - {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly-made edge(s) */ - {{'\0'}}, - }, - bmo_contextual_create_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "contextual_create", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry. */ + {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ + {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth to use */ + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* newly-made face(s) */ + /* note, this is for stand-alone edges only, not edges which are apart of newly created faces */ + {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly-made edge(s) */ + {{'\0'}}, + }, + bmo_contextual_create_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* * Bridge edge loops with faces. */ static BMOpDefine bmo_bridge_loops_def = { - "bridge_loops", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - {"use_pairs", BMO_OP_SLOT_BOOL}, - {"use_cyclic", BMO_OP_SLOT_BOOL}, - {"use_merge", BMO_OP_SLOT_BOOL}, - {"merge_factor", BMO_OP_SLOT_FLT}, - {"twist_offset", BMO_OP_SLOT_INT}, - {{'\0'}}, - }, - /* slots_out */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ - {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */ - {{'\0'}}, - }, - bmo_bridge_loops_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "bridge_loops", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"use_pairs", BMO_OP_SLOT_BOOL}, + {"use_cyclic", BMO_OP_SLOT_BOOL}, + {"use_merge", BMO_OP_SLOT_BOOL}, + {"merge_factor", BMO_OP_SLOT_FLT}, + {"twist_offset", BMO_OP_SLOT_INT}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ + {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */ + {{'\0'}}, + }, + bmo_bridge_loops_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -615,23 +615,23 @@ static BMOpDefine bmo_bridge_loops_def = { * Create faces defined by 2 disconnected edge loops (which share edges). */ static BMOpDefine bmo_grid_fill_def = { - "grid_fill", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - /* restricts edges to groups. maps edges to integer */ - {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ - {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */ - {"use_interp_simple", BMO_OP_SLOT_BOOL}, /* use simple interpolation */ - {{'\0'}}, - }, - /* slots_out */ - /* maps new faces to the group numbers they came from */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ - {{'\0'}}, - }, - bmo_grid_fill_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "grid_fill", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + /* restricts edges to groups. maps edges to integer */ + {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ + {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */ + {"use_interp_simple", BMO_OP_SLOT_BOOL}, /* use simple interpolation */ + {{'\0'}}, + }, + /* slots_out */ + /* maps new faces to the group numbers they came from */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ + {{'\0'}}, + }, + bmo_grid_fill_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; @@ -641,20 +641,20 @@ static BMOpDefine bmo_grid_fill_def = { * Fill boundary edges with faces, copying surrounding customdata. */ static BMOpDefine bmo_holes_fill_def = { - "holes_fill", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - {"sides", BMO_OP_SLOT_INT}, /* number of face sides to fill */ - {{'\0'}}, - }, - /* slots_out */ - /* maps new faces to the group numbers they came from */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ - {{'\0'}}, - }, - bmo_holes_fill_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "holes_fill", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"sides", BMO_OP_SLOT_INT}, /* number of face sides to fill */ + {{'\0'}}, + }, + /* slots_out */ + /* maps new faces to the group numbers they came from */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ + {{'\0'}}, + }, + bmo_holes_fill_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; @@ -664,20 +664,20 @@ static BMOpDefine bmo_holes_fill_def = { * Fill in faces with data from adjacent faces. */ static BMOpDefine bmo_face_attribute_fill_def = { - "face_attribute_fill", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"use_normals", BMO_OP_SLOT_BOOL}, /* copy face winding */ - {"use_data", BMO_OP_SLOT_BOOL}, /* copy face data */ - {{'\0'}}, - }, - /* slots_out */ - /* maps new faces to the group numbers they came from */ - {{"faces_fail.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* faces that could not be handled */ - {{'\0'}}, - }, - bmo_face_attribute_fill_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC), + "face_attribute_fill", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_normals", BMO_OP_SLOT_BOOL}, /* copy face winding */ + {"use_data", BMO_OP_SLOT_BOOL}, /* copy face data */ + {{'\0'}}, + }, + /* slots_out */ + /* maps new faces to the group numbers they came from */ + {{"faces_fail.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* faces that could not be handled */ + {{'\0'}}, + }, + bmo_face_attribute_fill_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* @@ -686,22 +686,22 @@ static BMOpDefine bmo_face_attribute_fill_def = { * Create faces defined by one or more non overlapping edge loops. */ static BMOpDefine bmo_edgeloop_fill_def = { - "edgeloop_fill", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - /* restricts edges to groups. maps edges to integer */ - {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ - {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */ - {{'\0'}}, - }, - /* slots_out */ - /* maps new faces to the group numbers they came from */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ - {{'\0'}}, - }, - bmo_edgeloop_fill_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "edgeloop_fill", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + /* restricts edges to groups. maps edges to integer */ + {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ + {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */ + {{'\0'}}, + }, + /* slots_out */ + /* maps new faces to the group numbers they came from */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ + {{'\0'}}, + }, + bmo_edgeloop_fill_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; @@ -711,22 +711,22 @@ static BMOpDefine bmo_edgeloop_fill_def = { * Create faces defined by enclosed edges. */ static BMOpDefine bmo_edgenet_fill_def = { - "edgenet_fill", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ - {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */ - {"sides", BMO_OP_SLOT_INT}, /* number of sides */ - {{'\0'}}, - }, - /* slots_out */ - /* maps new faces to the group numbers they came from */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ - {{'\0'}}, - }, - bmo_edgenet_fill_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "edgenet_fill", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ + {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */ + {"sides", BMO_OP_SLOT_INT}, /* number of sides */ + {{'\0'}}, + }, + /* slots_out */ + /* maps new faces to the group numbers they came from */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ + {{'\0'}}, + }, + bmo_edgenet_fill_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -740,17 +740,17 @@ static BMOpDefine bmo_edgenet_fill_def = { * shortest distance between each endpont). */ static BMOpDefine bmo_edgenet_prepare_def = { - "edgenet_prepare", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - {{'\0'}}, - }, - /* slots_out */ - {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */ - {{'\0'}}, - }, - bmo_edgenet_prepare_exec, - (BMO_OPTYPE_FLAG_NOP), + "edgenet_prepare", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */ + {{'\0'}}, + }, + bmo_edgenet_prepare_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -759,17 +759,17 @@ static BMOpDefine bmo_edgenet_prepare_def = { * Rotate vertices around a center, using a 3x3 rotation matrix. */ static BMOpDefine bmo_rotate_def = { - "rotate", - /* slots_in */ - {{"cent", BMO_OP_SLOT_VEC}, /* center of rotation */ - {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining rotation */ - {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_rotate_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC), + "rotate", + /* slots_in */ + {{"cent", BMO_OP_SLOT_VEC}, /* center of rotation */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining rotation */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_rotate_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* @@ -778,16 +778,16 @@ static BMOpDefine bmo_rotate_def = { * Translate vertices by an offset. */ static BMOpDefine bmo_translate_def = { - "translate", - /* slots_in */ - {{"vec", BMO_OP_SLOT_VEC}, /* translation offset */ - {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */ - {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_translate_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC), + "translate", + /* slots_in */ + {{"vec", BMO_OP_SLOT_VEC}, /* translation offset */ + {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_translate_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* @@ -796,16 +796,16 @@ static BMOpDefine bmo_translate_def = { * Scales vertices by an offset. */ static BMOpDefine bmo_scale_def = { - "scale", - /* slots_in */ - {{"vec", BMO_OP_SLOT_VEC}, /* scale factor */ - {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */ - {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_scale_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC), + "scale", + /* slots_in */ + {{"vec", BMO_OP_SLOT_VEC}, /* scale factor */ + {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_scale_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC), }; @@ -816,16 +816,16 @@ static BMOpDefine bmo_scale_def = { * the vertex coordinates with the matrix. */ static BMOpDefine bmo_transform_def = { - "transform", - /* slots_in */ - {{"matrix", BMO_OP_SLOT_MAT}, /* transform matrix */ - {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */ - {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_transform_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC), + "transform", + /* slots_in */ + {{"matrix", BMO_OP_SLOT_MAT}, /* transform matrix */ + {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_transform_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* @@ -835,15 +835,15 @@ static BMOpDefine bmo_transform_def = { * bmop. */ static BMOpDefine bmo_object_load_bmesh_def = { - "object_load_bmesh", - /* slots_in */ - {{"scene", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_SCENE}}, - {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_object_load_bmesh_exec, - (BMO_OPTYPE_FLAG_NOP), + "object_load_bmesh", + /* slots_in */ + {{"scene", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_SCENE}}, + {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_object_load_bmesh_exec, + (BMO_OPTYPE_FLAG_NOP), }; @@ -853,18 +853,18 @@ static BMOpDefine bmo_object_load_bmesh_def = { * Converts a bmesh to a Mesh. This is reserved for exiting editmode. */ static BMOpDefine bmo_bmesh_to_mesh_def = { - "bmesh_to_mesh", - /* slots_in */ - { - /* pointer to a mesh structure to fill in */ - {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, - /* pointer to an object structure */ - {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_bmesh_to_mesh_exec, - (BMO_OPTYPE_FLAG_NOP), + "bmesh_to_mesh", + /* slots_in */ + { + /* pointer to a mesh structure to fill in */ + {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, + /* pointer to an object structure */ + {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_bmesh_to_mesh_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -874,19 +874,19 @@ static BMOpDefine bmo_bmesh_to_mesh_def = { * reserved exclusively for entering editmode. */ static BMOpDefine bmo_mesh_to_bmesh_def = { - "mesh_to_bmesh", - /* slots_in */ - { - /* pointer to a Mesh structure */ - {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, - /* pointer to an Object structure */ - {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, - {"use_shapekey", BMO_OP_SLOT_BOOL}, /* load active shapekey coordinates into verts */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_mesh_to_bmesh_exec, - (BMO_OPTYPE_FLAG_NOP), + "mesh_to_bmesh", + /* slots_in */ + { + /* pointer to a Mesh structure */ + {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, + /* pointer to an Object structure */ + {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {"use_shapekey", BMO_OP_SLOT_BOOL}, /* load active shapekey coordinates into verts */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_mesh_to_bmesh_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -895,19 +895,19 @@ static BMOpDefine bmo_mesh_to_bmesh_def = { * Extrudes faces individually. */ static BMOpDefine bmo_extrude_discrete_faces_def = { - "extrude_discrete_faces", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ - {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ - {{'\0'}}, - }, - /* slots_out */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ - {{'\0'}}, - }, - bmo_extrude_discrete_faces_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC), + "extrude_discrete_faces", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ + {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, + bmo_extrude_discrete_faces_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* @@ -917,19 +917,19 @@ static BMOpDefine bmo_extrude_discrete_faces_def = { * winged extrusion. */ static BMOpDefine bmo_extrude_edge_only_def = { - "extrude_edge_only", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */ - {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ - {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ - {{'\0'}}, - }, - /* slots_out */ - {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry */ - {{'\0'}}, - }, - bmo_extrude_edge_only_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC), + "extrude_edge_only", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */ + {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ + {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry */ + {{'\0'}}, + }, + bmo_extrude_edge_only_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* @@ -938,19 +938,19 @@ static BMOpDefine bmo_extrude_edge_only_def = { * Extrudes wire edges from vertices. */ static BMOpDefine bmo_extrude_vert_indiv_def = { - "extrude_vert_indiv", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ - {{'\0'}}, - }, - /* slots_out */ - {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output wire edges */ - {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */ - {{'\0'}}, - }, - bmo_extrude_vert_indiv_exec, - (BMO_OPTYPE_FLAG_SELECT_FLUSH), + "extrude_vert_indiv", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output wire edges */ + {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */ + {{'\0'}}, + }, + bmo_extrude_vert_indiv_exec, + (BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -959,21 +959,21 @@ static BMOpDefine bmo_extrude_vert_indiv_def = { * Split faces by adding edges that connect **verts**. */ static BMOpDefine bmo_connect_verts_def = { - "connect_verts", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, - {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {"check_degenerate", BMO_OP_SLOT_BOOL}, /* prevent splits with overlaps & intersections */ - {{'\0'}}, - }, - /* slots_out */ - {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {{'\0'}}, - }, - bmo_connect_verts_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "connect_verts", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"check_degenerate", BMO_OP_SLOT_BOOL}, /* prevent splits with overlaps & intersections */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, + }, + bmo_connect_verts_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -982,20 +982,20 @@ static BMOpDefine bmo_connect_verts_def = { * Ensures all faces are convex **faces**. */ static BMOpDefine bmo_connect_verts_concave_def = { - "connect_verts_concave", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {{'\0'}}, - }, - /* slots_out */ - {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {{'\0'}}, - }, - bmo_connect_verts_concave_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "connect_verts_concave", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, + bmo_connect_verts_concave_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1004,21 +1004,21 @@ static BMOpDefine bmo_connect_verts_concave_def = { * Split faces by connecting edges along non planer **faces**. */ static BMOpDefine bmo_connect_verts_nonplanar_def = { - "connect_verts_nonplanar", - /* slots_in */ - {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ - {"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {{'\0'}}, - }, - /* slots_out */ - {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {{'\0'}}, - }, - bmo_connect_verts_nonplanar_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "connect_verts_nonplanar", + /* slots_in */ + {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ + {"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, + bmo_connect_verts_nonplanar_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1027,21 +1027,21 @@ static BMOpDefine bmo_connect_verts_nonplanar_def = { * Split faces by adding edges that connect **verts**. */ static BMOpDefine bmo_connect_vert_pair_def = { - "connect_vert_pair", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, - {"verts_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, - {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {{'\0'}}, - }, - /* slots_out */ - {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {{'\0'}}, - }, - bmo_connect_vert_pair_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "connect_vert_pair", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {"verts_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, + }, + bmo_connect_vert_pair_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; @@ -1051,93 +1051,93 @@ static BMOpDefine bmo_connect_vert_pair_def = { * Extrude operator (does not transform) */ static BMOpDefine bmo_extrude_face_region_def = { - "extrude_face_region", - /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */ - {"edges_exclude", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}}, - {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */ - {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ - {"use_normal_from_adjacent", BMO_OP_SLOT_BOOL}, /* Use winding from surrounding faces instead of this region. */ - {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ - {{'\0'}}, - }, - /* slots_out */ - {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {{'\0'}}, - }, - bmo_extrude_face_region_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC), + "extrude_face_region", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */ + {"edges_exclude", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}}, + {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */ + {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ + {"use_normal_from_adjacent", BMO_OP_SLOT_BOOL}, /* Use winding from surrounding faces instead of this region. */ + {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, + bmo_extrude_face_region_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* * Dissolve Verts. */ static BMOpDefine bmo_dissolve_verts_def = { - "dissolve_verts", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, - {"use_face_split", BMO_OP_SLOT_BOOL}, - {"use_boundary_tear", BMO_OP_SLOT_BOOL}, - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_dissolve_verts_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "dissolve_verts", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {"use_face_split", BMO_OP_SLOT_BOOL}, + {"use_boundary_tear", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_dissolve_verts_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* * Dissolve Edges. */ static BMOpDefine bmo_dissolve_edges_def = { - "dissolve_edges", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ - {"use_face_split", BMO_OP_SLOT_BOOL}, - {{'\0'}}, - }, - /* slots_out */ - {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {{'\0'}}, - }, - bmo_dissolve_edges_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "dissolve_edges", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ + {"use_face_split", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, + bmo_dissolve_edges_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* * Dissolve Faces. */ static BMOpDefine bmo_dissolve_faces_def = { - "dissolve_faces", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ - {{'\0'}}, - }, - /* slots_out */ - {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {{'\0'}}, - }, - bmo_dissolve_faces_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "dissolve_faces", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ + {{'\0'}}, + }, + /* slots_out */ + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, + bmo_dissolve_faces_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; static BMO_FlagSet bmo_enum_dissolve_limit_flags[] = { - {BMO_DELIM_NORMAL, "NORMAL"}, - {BMO_DELIM_MATERIAL, "MATERIAL"}, - {BMO_DELIM_SEAM, "SEAM"}, - {BMO_DELIM_SHARP, "SHARP"}, - {BMO_DELIM_UV, "UV"}, - {0, NULL}, + {BMO_DELIM_NORMAL, "NORMAL"}, + {BMO_DELIM_MATERIAL, "MATERIAL"}, + {BMO_DELIM_SEAM, "SEAM"}, + {BMO_DELIM_SHARP, "SHARP"}, + {BMO_DELIM_UV, "UV"}, + {0, NULL}, }; /* @@ -1146,23 +1146,23 @@ static BMO_FlagSet bmo_enum_dissolve_limit_flags[] = { * Dissolve planar faces and co-linear edges. */ static BMOpDefine bmo_dissolve_limit_def = { - "dissolve_limit", - /* slots_in */ - {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ - {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL}, - {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, - {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {"delimit", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_FLAG}, bmo_enum_dissolve_limit_flags}, - {{'\0'}}, - }, - /* slots_out */ - {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {{'\0'}}}, - bmo_dissolve_limit_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "dissolve_limit", + /* slots_in */ + {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ + {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL}, + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"delimit", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_FLAG}, bmo_enum_dissolve_limit_flags}, + {{'\0'}}, + }, + /* slots_out */ + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}}, + bmo_dissolve_limit_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -1171,57 +1171,57 @@ static BMOpDefine bmo_dissolve_limit_def = { * Dissolve edges with no length, faces with no area. */ static BMOpDefine bmo_dissolve_degenerate_def = { - "dissolve_degenerate", - /* slots_in */ - {{"dist", BMO_OP_SLOT_FLT}, /* minimum distance to consider degenerate */ - {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {{'\0'}}, - }, - /* slots_out */ - {{{'\0'}}}, - bmo_dissolve_degenerate_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "dissolve_degenerate", + /* slots_in */ + {{"dist", BMO_OP_SLOT_FLT}, /* minimum distance to consider degenerate */ + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, + }, + /* slots_out */ + {{{'\0'}}}, + bmo_dissolve_degenerate_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; static BMO_FlagSet bmo_enum_triangulate_quad_method[] = { - {MOD_TRIANGULATE_QUAD_BEAUTY, "BEAUTY"}, - {MOD_TRIANGULATE_QUAD_FIXED, "FIXED"}, - {MOD_TRIANGULATE_QUAD_ALTERNATE, "ALTERNATE"}, - {MOD_TRIANGULATE_QUAD_SHORTEDGE, "SHORT_EDGE"}, - {0, NULL}, + {MOD_TRIANGULATE_QUAD_BEAUTY, "BEAUTY"}, + {MOD_TRIANGULATE_QUAD_FIXED, "FIXED"}, + {MOD_TRIANGULATE_QUAD_ALTERNATE, "ALTERNATE"}, + {MOD_TRIANGULATE_QUAD_SHORTEDGE, "SHORT_EDGE"}, + {0, NULL}, }; static BMO_FlagSet bmo_enum_triangulate_ngon_method[] = { - {MOD_TRIANGULATE_NGON_BEAUTY, "BEAUTY"}, - {MOD_TRIANGULATE_NGON_EARCLIP, "EAR_CLIP"}, - {0, NULL}, + {MOD_TRIANGULATE_NGON_BEAUTY, "BEAUTY"}, + {MOD_TRIANGULATE_NGON_EARCLIP, "EAR_CLIP"}, + {0, NULL}, }; /* * Triangulate. */ static BMOpDefine bmo_triangulate_def = { - "triangulate", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {"quad_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_quad_method}, - {"ngon_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_ngon_method}, - {{'\0'}}, - }, - /* slots_out */ - {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, - {"face_map_double.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, /* duplicate faces */ - {{'\0'}}, - }, - bmo_triangulate_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "triangulate", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"quad_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_quad_method}, + {"ngon_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_ngon_method}, + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"face_map_double.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, /* duplicate faces */ + {{'\0'}}, + }, + bmo_triangulate_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1230,26 +1230,26 @@ static BMOpDefine bmo_triangulate_def = { * Reduce detail in geometry containing grids. */ static BMOpDefine bmo_unsubdivide_def = { - "unsubdivide", - /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ - {"iterations", BMO_OP_SLOT_INT}, - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_unsubdivide_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "unsubdivide", + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"iterations", BMO_OP_SLOT_INT}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_unsubdivide_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; static BMO_FlagSet bmo_enum_subdivide_edges_quad_corner_type[] = { - {SUBD_CORNER_STRAIGHT_CUT, "STRAIGHT_CUT"}, - {SUBD_CORNER_INNERVERT, "INNER_VERT"}, - {SUBD_CORNER_PATH, "PATH"}, - {SUBD_CORNER_FAN, "FAN"}, - {0, NULL}, + {SUBD_CORNER_STRAIGHT_CUT, "STRAIGHT_CUT"}, + {SUBD_CORNER_INNERVERT, "INNER_VERT"}, + {SUBD_CORNER_PATH, "PATH"}, + {SUBD_CORNER_FAN, "FAN"}, + {0, NULL}, }; /* @@ -1259,44 +1259,44 @@ static BMO_FlagSet bmo_enum_subdivide_edges_quad_corner_type[] = { * with options for face patterns, smoothing and randomization. */ static BMOpDefine bmo_subdivide_edges_def = { - "subdivide_edges", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {"smooth", BMO_OP_SLOT_FLT}, - {"smooth_falloff", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_falloff_type}, /* smooth falloff type */ - {"fractal", BMO_OP_SLOT_FLT}, - {"along_normal", BMO_OP_SLOT_FLT}, - {"cuts", BMO_OP_SLOT_INT}, - {"seed", BMO_OP_SLOT_INT}, - {"custom_patterns", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}}, /* uses custom pointers */ - {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}}, - {"quad_corner_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_subdivide_edges_quad_corner_type}, /* quad corner type */ - {"use_grid_fill", BMO_OP_SLOT_BOOL}, /* fill in fully-selected faces with a grid */ - {"use_single_edge", BMO_OP_SLOT_BOOL}, /* tessellate the case of one edge selected in a quad or triangle */ - {"use_only_quads", BMO_OP_SLOT_BOOL}, /* only subdivide quads (for loopcut) */ - {"use_sphere", BMO_OP_SLOT_BOOL}, /* for making new primitives only */ - {"use_smooth_even", BMO_OP_SLOT_BOOL}, /* maintain even offset when smoothing */ - {{'\0'}}, - }, - /* slots_out */ - {/* these next three can have multiple types of elements in them */ - {"geom_inner.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* contains all output geometry */ - {{'\0'}}, - }, - bmo_subdivide_edges_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "subdivide_edges", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"smooth", BMO_OP_SLOT_FLT}, + {"smooth_falloff", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_falloff_type}, /* smooth falloff type */ + {"fractal", BMO_OP_SLOT_FLT}, + {"along_normal", BMO_OP_SLOT_FLT}, + {"cuts", BMO_OP_SLOT_INT}, + {"seed", BMO_OP_SLOT_INT}, + {"custom_patterns", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}}, /* uses custom pointers */ + {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}}, + {"quad_corner_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_subdivide_edges_quad_corner_type}, /* quad corner type */ + {"use_grid_fill", BMO_OP_SLOT_BOOL}, /* fill in fully-selected faces with a grid */ + {"use_single_edge", BMO_OP_SLOT_BOOL}, /* tessellate the case of one edge selected in a quad or triangle */ + {"use_only_quads", BMO_OP_SLOT_BOOL}, /* only subdivide quads (for loopcut) */ + {"use_sphere", BMO_OP_SLOT_BOOL}, /* for making new primitives only */ + {"use_smooth_even", BMO_OP_SLOT_BOOL}, /* maintain even offset when smoothing */ + {{'\0'}}, + }, + /* slots_out */ + {/* these next three can have multiple types of elements in them */ + {"geom_inner.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* contains all output geometry */ + {{'\0'}}, + }, + bmo_subdivide_edges_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; static BMO_FlagSet bmo_enum_subdivide_edgering_interp_mode[] = { - {SUBD_RING_INTERP_LINEAR, "LINEAR"}, - {SUBD_RING_INTERP_PATH, "PATH"}, - {SUBD_RING_INTERP_SURF, "SURFACE"}, - {0, NULL}, + {SUBD_RING_INTERP_LINEAR, "LINEAR"}, + {SUBD_RING_INTERP_PATH, "PATH"}, + {SUBD_RING_INTERP_SURF, "SURFACE"}, + {0, NULL}, }; /* @@ -1305,23 +1305,23 @@ static BMO_FlagSet bmo_enum_subdivide_edgering_interp_mode[] = { * Take an edge-ring, and subdivide with interpolation options. */ static BMOpDefine bmo_subdivide_edgering_def = { - "subdivide_edgering", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */ - {"interp_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_subdivide_edgering_interp_mode}, /* interpolation method */ - {"smooth", BMO_OP_SLOT_FLT}, - {"cuts", BMO_OP_SLOT_INT}, - {"profile_shape", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_falloff_type}, /* profile shape type */ - {"profile_shape_factor", BMO_OP_SLOT_FLT}, - {{'\0'}}, - }, - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ - {{'\0'}}}, - bmo_subdivide_edgering_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "subdivide_edgering", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */ + {"interp_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_subdivide_edgering_interp_mode}, /* interpolation method */ + {"smooth", BMO_OP_SLOT_FLT}, + {"cuts", BMO_OP_SLOT_INT}, + {"profile_shape", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_falloff_type}, /* profile shape type */ + {"profile_shape_factor", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}}, + bmo_subdivide_edgering_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -1330,36 +1330,36 @@ static BMOpDefine bmo_subdivide_edgering_def = { * Bisects the mesh by a plane (cut the mesh in half). */ static BMOpDefine bmo_bisect_plane_def = { - "bisect_plane", - /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"dist", BMO_OP_SLOT_FLT}, /* minimum distance when testing if a vert is exactly on the plane */ - {"plane_co", BMO_OP_SLOT_VEC}, /* point on the plane */ - {"plane_no", BMO_OP_SLOT_VEC}, /* direction of the plane */ - {"use_snap_center", BMO_OP_SLOT_BOOL}, /* snap axis aligned verts to the center */ - {"clear_outer", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the positive side of the plane */ - {"clear_inner", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the negative side of the plane */ - {{'\0'}}, - }, - {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output geometry aligned with the plane (new and existing) */ - {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */ - {{'\0'}}}, - bmo_bisect_plane_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "bisect_plane", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance when testing if a vert is exactly on the plane */ + {"plane_co", BMO_OP_SLOT_VEC}, /* point on the plane */ + {"plane_no", BMO_OP_SLOT_VEC}, /* direction of the plane */ + {"use_snap_center", BMO_OP_SLOT_BOOL}, /* snap axis aligned verts to the center */ + {"clear_outer", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the positive side of the plane */ + {"clear_inner", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the negative side of the plane */ + {{'\0'}}, + }, + {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output geometry aligned with the plane (new and existing) */ + {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */ + {{'\0'}}}, + bmo_bisect_plane_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; static BMO_FlagSet bmo_enum_delete_context[] = { - {DEL_VERTS, "VERTS"}, - {DEL_EDGES, "EDGES"}, - {DEL_ONLYFACES, "FACES_ONLY"}, - {DEL_EDGESFACES, "EDGES_FACES"}, - {DEL_FACES, "FACES"}, - {DEL_FACES_KEEP_BOUNDARY, "FACES_KEEP_BOUNDARY"}, - {DEL_ONLYTAGGED, "TAGGED_ONLY"}, - {0, NULL}, + {DEL_VERTS, "VERTS"}, + {DEL_EDGES, "EDGES"}, + {DEL_ONLYFACES, "FACES_ONLY"}, + {DEL_EDGESFACES, "EDGES_FACES"}, + {DEL_FACES, "FACES"}, + {DEL_FACES_KEEP_BOUNDARY, "FACES_KEEP_BOUNDARY"}, + {DEL_ONLYTAGGED, "TAGGED_ONLY"}, + {0, NULL}, }; /* @@ -1368,17 +1368,17 @@ static BMO_FlagSet bmo_enum_delete_context[] = { * Utility operator to delete geometry. */ static BMOpDefine bmo_delete_def = { - "delete", - /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"context", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_delete_context}, /* geometry types to delete */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_delete_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "delete", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"context", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_delete_context}, /* geometry types to delete */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_delete_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -1388,30 +1388,30 @@ static BMOpDefine bmo_delete_def = { * optionally into a destination mesh. */ static BMOpDefine bmo_duplicate_def = { - "duplicate", - /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - /* destination bmesh, if NULL will use current on */ - {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, - {"use_select_history", BMO_OP_SLOT_BOOL}, - {"use_edge_flip_from_face", BMO_OP_SLOT_BOOL}, - {{'\0'}}, - }, - /* slots_out */ - {{"geom_orig.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - /* facemap maps from source faces to dupe - * faces, and from dupe faces to source faces */ - {"vert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, - {"edge_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, - {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, - {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, - {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, - {{'\0'}}, - }, - bmo_duplicate_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "duplicate", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + /* destination bmesh, if NULL will use current on */ + {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, + {"use_select_history", BMO_OP_SLOT_BOOL}, + {"use_edge_flip_from_face", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom_orig.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + /* facemap maps from source faces to dupe + * faces, and from dupe faces to source faces */ + {"vert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"edge_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, + bmo_duplicate_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1421,23 +1421,23 @@ static BMOpDefine bmo_duplicate_def = { * optionally into a destination mesh. */ static BMOpDefine bmo_split_def = { - "split", - /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - /* destination bmesh, if NULL will use current one */ - {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, - {"use_only_faces", BMO_OP_SLOT_BOOL}, /* when enabled. don't duplicate loose verts/edges */ - {{'\0'}}, - }, - /* slots_out */ - {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, - {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, - {{'\0'}}, - }, - bmo_split_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "split", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + /* destination bmesh, if NULL will use current one */ + {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, + {"use_only_faces", BMO_OP_SLOT_BOOL}, /* when enabled. don't duplicate loose verts/edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, + bmo_split_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1447,27 +1447,27 @@ static BMOpDefine bmo_split_def = { * rotating and possibly translating after each step */ static BMOpDefine bmo_spin_def = { - "spin", - /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"cent", BMO_OP_SLOT_VEC}, /* rotation center */ - {"axis", BMO_OP_SLOT_VEC}, /* rotation axis */ - {"dvec", BMO_OP_SLOT_VEC}, /* translation delta per step */ - {"angle", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ - {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */ - {"steps", BMO_OP_SLOT_INT}, /* number of steps */ - {"use_merge", BMO_OP_SLOT_BOOL}, /* Merge first/last when the angle is a full revolution. */ - {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ - {"use_duplicate", BMO_OP_SLOT_BOOL}, /* duplicate or extrude? */ - {{'\0'}}, - }, - /* slots_out */ - {{"geom_last.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* result of last step */ - {{'\0'}}, - }, - bmo_spin_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "spin", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"cent", BMO_OP_SLOT_VEC}, /* rotation center */ + {"axis", BMO_OP_SLOT_VEC}, /* rotation axis */ + {"dvec", BMO_OP_SLOT_VEC}, /* translation delta per step */ + {"angle", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ + {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */ + {"steps", BMO_OP_SLOT_INT}, /* number of steps */ + {"use_merge", BMO_OP_SLOT_BOOL}, /* Merge first/last when the angle is a full revolution. */ + {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ + {"use_duplicate", BMO_OP_SLOT_BOOL}, /* duplicate or extrude? */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom_last.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* result of last step */ + {{'\0'}}, + }, + bmo_spin_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1476,15 +1476,15 @@ static BMOpDefine bmo_spin_def = { * Cycle the loop UV's */ static BMOpDefine bmo_rotate_uvs_def = { - "rotate_uvs", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_rotate_uvs_exec, - (BMO_OPTYPE_FLAG_NOP), + "rotate_uvs", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_rotate_uvs_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -1493,14 +1493,14 @@ static BMOpDefine bmo_rotate_uvs_def = { * Reverse the UV's */ static BMOpDefine bmo_reverse_uvs_def = { - "reverse_uvs", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_reverse_uvs_exec, - (BMO_OPTYPE_FLAG_NOP), + "reverse_uvs", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_reverse_uvs_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -1509,15 +1509,15 @@ static BMOpDefine bmo_reverse_uvs_def = { * Cycle the loop colors */ static BMOpDefine bmo_rotate_colors_def = { - "rotate_colors", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_rotate_colors_exec, - (BMO_OPTYPE_FLAG_NOP), + "rotate_colors", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_rotate_colors_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -1526,14 +1526,14 @@ static BMOpDefine bmo_rotate_colors_def = { * Reverse the loop colors. */ static BMOpDefine bmo_reverse_colors_def = { - "reverse_colors", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {{'\0'}}, - }, - {{{'\0'}}}, /* no output */ - bmo_reverse_colors_exec, - (BMO_OPTYPE_FLAG_NOP), + "reverse_colors", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ + bmo_reverse_colors_exec, + (BMO_OPTYPE_FLAG_NOP), }; /* @@ -1542,22 +1542,22 @@ static BMOpDefine bmo_reverse_colors_def = { * Disconnects faces along input edges. */ static BMOpDefine bmo_split_edges_def = { - "split_edges", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - /* needed for vertex rip so we can rip only half an edge at a boundary wich would otherwise split off */ - {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* optional tag verts, use to have greater control of splits */ - {"use_verts", BMO_OP_SLOT_BOOL}, /* use 'verts' for splitting, else just find verts to split from edges */ - {{'\0'}}, - }, - /* slots_out */ - {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* old output disconnected edges */ - {{'\0'}}, - }, - bmo_split_edges_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "split_edges", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + /* needed for vertex rip so we can rip only half an edge at a boundary wich would otherwise split off */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* optional tag verts, use to have greater control of splits */ + {"use_verts", BMO_OP_SLOT_BOOL}, /* use 'verts' for splitting, else just find verts to split from edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* old output disconnected edges */ + {{'\0'}}, + }, + bmo_split_edges_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1566,22 +1566,22 @@ static BMOpDefine bmo_split_edges_def = { * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_grid_def = { - "create_grid", - /* slots_in */ - {{"x_segments", BMO_OP_SLOT_INT}, /* number of x segments */ - {"y_segments", BMO_OP_SLOT_INT}, /* number of y segments */ - {"size", BMO_OP_SLOT_FLT}, /* size of the grid */ - {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ - {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ - {{'\0'}}, - }, - /* slots_out */ - {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ - {{'\0'}}, - }, - bmo_create_grid_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "create_grid", + /* slots_in */ + {{"x_segments", BMO_OP_SLOT_INT}, /* number of x segments */ + {"y_segments", BMO_OP_SLOT_INT}, /* number of y segments */ + {"size", BMO_OP_SLOT_FLT}, /* size of the grid */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, + bmo_create_grid_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1590,22 +1590,22 @@ static BMOpDefine bmo_create_grid_def = { * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_uvsphere_def = { - "create_uvsphere", - /* slots_in */ - {{"u_segments", BMO_OP_SLOT_INT}, /* number of u segments */ - {"v_segments", BMO_OP_SLOT_INT}, /* number of v segment */ - {"diameter", BMO_OP_SLOT_FLT}, /* diameter */ - {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ - {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ - {{'\0'}}, - }, - /* slots_out */ - {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ - {{'\0'}}, - }, - bmo_create_uvsphere_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "create_uvsphere", + /* slots_in */ + {{"u_segments", BMO_OP_SLOT_INT}, /* number of u segments */ + {"v_segments", BMO_OP_SLOT_INT}, /* number of v segment */ + {"diameter", BMO_OP_SLOT_FLT}, /* diameter */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, + bmo_create_uvsphere_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1614,21 +1614,21 @@ static BMOpDefine bmo_create_uvsphere_def = { * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_icosphere_def = { - "create_icosphere", - /* slots_in */ - {{"subdivisions", BMO_OP_SLOT_INT}, /* how many times to recursively subdivide the sphere */ - {"diameter", BMO_OP_SLOT_FLT}, /* diameter */ - {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ - {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ - {{'\0'}}, - }, - /* slots_out */ - {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ - {{'\0'}}, - }, - bmo_create_icosphere_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "create_icosphere", + /* slots_in */ + {{"subdivisions", BMO_OP_SLOT_INT}, /* how many times to recursively subdivide the sphere */ + {"diameter", BMO_OP_SLOT_FLT}, /* diameter */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, + bmo_create_icosphere_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1637,19 +1637,19 @@ static BMOpDefine bmo_create_icosphere_def = { * Creates a monkey (standard blender primitive). */ static BMOpDefine bmo_create_monkey_def = { - "create_monkey", - /* slots_in */ - {{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ - {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ - {{'\0'}}, - }, - /* slots_out */ - {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ - {{'\0'}}, - }, - bmo_create_monkey_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "create_monkey", + /* slots_in */ + {{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, + bmo_create_monkey_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1658,48 +1658,48 @@ static BMOpDefine bmo_create_monkey_def = { * Creates a cone with variable depth at both ends */ static BMOpDefine bmo_create_cone_def = { - "create_cone", - /* slots_in */ - {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ - {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ - {"segments", BMO_OP_SLOT_INT}, - {"diameter1", BMO_OP_SLOT_FLT}, /* diameter of one end */ - {"diameter2", BMO_OP_SLOT_FLT}, /* diameter of the opposite */ - {"depth", BMO_OP_SLOT_FLT}, /* distance between ends */ - {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ - {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ - {{'\0'}}, - }, - /* slots_out */ - {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ - {{'\0'}}, - }, - bmo_create_cone_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "create_cone", + /* slots_in */ + {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ + {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ + {"segments", BMO_OP_SLOT_INT}, + {"diameter1", BMO_OP_SLOT_FLT}, /* diameter of one end */ + {"diameter2", BMO_OP_SLOT_FLT}, /* diameter of the opposite */ + {"depth", BMO_OP_SLOT_FLT}, /* distance between ends */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, + bmo_create_cone_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* * Creates a Circle. */ static BMOpDefine bmo_create_circle_def = { - "create_circle", - /* slots_in */ - {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ - {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ - {"segments", BMO_OP_SLOT_INT}, - {"radius", BMO_OP_SLOT_FLT}, /* Radius of the circle. */ - {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ - {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ - {{'\0'}}, - }, - /* slots_out */ - {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ - {{'\0'}}, - }, - bmo_create_circle_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "create_circle", + /* slots_in */ + {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ + {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ + {"segments", BMO_OP_SLOT_INT}, + {"radius", BMO_OP_SLOT_FLT}, /* Radius of the circle. */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, + bmo_create_circle_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1708,43 +1708,43 @@ static BMOpDefine bmo_create_circle_def = { * Creates a cube. */ static BMOpDefine bmo_create_cube_def = { - "create_cube", - /* slots_in */ - {{"size", BMO_OP_SLOT_FLT}, /* size of the cube */ - {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ - {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ - {{'\0'}}, - }, - /* slots_out */ - {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ - {{'\0'}}, - }, - bmo_create_cube_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "create_cube", + /* slots_in */ + {{"size", BMO_OP_SLOT_FLT}, /* size of the cube */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, + bmo_create_cube_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; static BMO_FlagSet bmo_enum_bevel_offset_type[] = { - {BEVEL_AMT_OFFSET, "OFFSET"}, - {BEVEL_AMT_WIDTH, "WIDTH"}, - {BEVEL_AMT_DEPTH, "DEPTH"}, - {BEVEL_AMT_PERCENT, "PERCENT"}, - {0, NULL}, + {BEVEL_AMT_OFFSET, "OFFSET"}, + {BEVEL_AMT_WIDTH, "WIDTH"}, + {BEVEL_AMT_DEPTH, "DEPTH"}, + {BEVEL_AMT_PERCENT, "PERCENT"}, + {0, NULL}, }; static BMO_FlagSet bmo_enum_bevel_face_strength_type[] = { - {BEVEL_FACE_STRENGTH_NONE, "NONE"}, - {BEVEL_FACE_STRENGTH_NEW, "NEW"}, - {BEVEL_FACE_STRENGTH_AFFECTED, "AFFECTED"}, - {BEVEL_FACE_STRENGTH_ALL, "ALL"}, - {0, NULL}, + {BEVEL_FACE_STRENGTH_NONE, "NONE"}, + {BEVEL_FACE_STRENGTH_NEW, "NEW"}, + {BEVEL_FACE_STRENGTH_AFFECTED, "AFFECTED"}, + {BEVEL_FACE_STRENGTH_ALL, "ALL"}, + {0, NULL}, }; static BMO_FlagSet bmo_enum_bevel_miter_type[] = { - {BEVEL_MITER_SHARP, "SHARP"}, - {BEVEL_MITER_PATCH, "PATCH"}, - {BEVEL_MITER_ARC, "ARC"}, - {0, NULL}, + {BEVEL_MITER_SHARP, "SHARP"}, + {BEVEL_MITER_PATCH, "PATCH"}, + {BEVEL_MITER_ARC, "ARC"}, + {0, NULL}, }; /* @@ -1753,49 +1753,49 @@ static BMO_FlagSet bmo_enum_bevel_miter_type[] = { * Bevels edges and vertices */ static BMOpDefine bmo_bevel_def = { - "bevel", - /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */ - {"offset", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */ - {"offset_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_bevel_offset_type}, /* how to measure the offset */ - {"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */ - {"profile", BMO_OP_SLOT_FLT}, /* profile shape, 0->1 (.5=>round) */ - {"vertex_only", BMO_OP_SLOT_BOOL}, /* only bevel vertices, not edges */ - {"clamp_overlap", BMO_OP_SLOT_BOOL}, /* do not allow beveled edges/vertices to overlap each other */ - {"material", BMO_OP_SLOT_INT}, /* material for bevel faces, -1 means get from adjacent faces */ - {"loop_slide", BMO_OP_SLOT_BOOL}, /* prefer to slide along edges to having even widths */ - {"mark_seam", BMO_OP_SLOT_BOOL}, /* extend edge data to allow seams to run across bevels */ - {"mark_sharp", BMO_OP_SLOT_BOOL}, /* extend edge data to allow sharp edges to run across bevels */ - {"harden_normals", BMO_OP_SLOT_BOOL}, /* harden normals */ - {"face_strength_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, - bmo_enum_bevel_face_strength_type}, /* whether to set face strength, and which faces to set if so */ - {"miter_outer", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, - bmo_enum_bevel_miter_type}, /* outer miter kind */ - {"miter_inner", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, - bmo_enum_bevel_miter_type}, /* outer miter kind */ - {"spread", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */ - {"smoothresh", BMO_OP_SLOT_FLT}, /* for passing mesh's smoothresh, used in hardening */ - {{'\0'}}, - }, - /* slots_out */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ - {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */ - {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ - {{'\0'}}, - }, - - bmo_bevel_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "bevel", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */ + {"offset", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */ + {"offset_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_bevel_offset_type}, /* how to measure the offset */ + {"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */ + {"profile", BMO_OP_SLOT_FLT}, /* profile shape, 0->1 (.5=>round) */ + {"vertex_only", BMO_OP_SLOT_BOOL}, /* only bevel vertices, not edges */ + {"clamp_overlap", BMO_OP_SLOT_BOOL}, /* do not allow beveled edges/vertices to overlap each other */ + {"material", BMO_OP_SLOT_INT}, /* material for bevel faces, -1 means get from adjacent faces */ + {"loop_slide", BMO_OP_SLOT_BOOL}, /* prefer to slide along edges to having even widths */ + {"mark_seam", BMO_OP_SLOT_BOOL}, /* extend edge data to allow seams to run across bevels */ + {"mark_sharp", BMO_OP_SLOT_BOOL}, /* extend edge data to allow sharp edges to run across bevels */ + {"harden_normals", BMO_OP_SLOT_BOOL}, /* harden normals */ + {"face_strength_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, + bmo_enum_bevel_face_strength_type}, /* whether to set face strength, and which faces to set if so */ + {"miter_outer", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, + bmo_enum_bevel_miter_type}, /* outer miter kind */ + {"miter_inner", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, + bmo_enum_bevel_miter_type}, /* outer miter kind */ + {"spread", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */ + {"smoothresh", BMO_OP_SLOT_FLT}, /* for passing mesh's smoothresh, used in hardening */ + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */ + {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, + + bmo_bevel_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* no enum is defined for this */ static BMO_FlagSet bmo_enum_beautify_fill_method[] = { - {0, "AREA"}, - {1, "ANGLE"}, - {0, NULL}, + {0, "AREA"}, + {1, "ANGLE"}, + {0, NULL}, }; /* @@ -1804,23 +1804,23 @@ static BMO_FlagSet bmo_enum_beautify_fill_method[] = { * Rotate edges to create more evenly spaced triangles. */ static BMOpDefine bmo_beautify_fill_def = { - "beautify_fill", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can be flipped */ - {"use_restrict_tag", BMO_OP_SLOT_BOOL}, /* restrict edge rotation to mixed tagged vertices */ - {"method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_beautify_fill_method}, /* method to define what is beautiful */ - {{'\0'}}, - }, - /* slots_out */ - {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new flipped faces and edges */ - {{'\0'}}, - }, - bmo_beautify_fill_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "beautify_fill", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can be flipped */ + {"use_restrict_tag", BMO_OP_SLOT_BOOL}, /* restrict edge rotation to mixed tagged vertices */ + {"method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_beautify_fill_method}, /* method to define what is beautiful */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new flipped faces and edges */ + {{'\0'}}, + }, + bmo_beautify_fill_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* @@ -1829,22 +1829,22 @@ static BMOpDefine bmo_beautify_fill_def = { * Fill edges with triangles */ static BMOpDefine bmo_triangle_fill_def = { - "triangle_fill", - /* slots_in */ - {{"use_beauty", BMO_OP_SLOT_BOOL}, - {"use_dissolve", BMO_OP_SLOT_BOOL}, /* dissolve resulting faces */ - {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - {"normal", BMO_OP_SLOT_VEC}, /* optionally pass the fill normal to use */ - {{'\0'}}, - }, - /* slots_out */ - {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new faces and edges */ - {{'\0'}}, - }, - bmo_triangle_fill_exec, - (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | - BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "triangle_fill", + /* slots_in */ + {{"use_beauty", BMO_OP_SLOT_BOOL}, + {"use_dissolve", BMO_OP_SLOT_BOOL}, /* dissolve resulting faces */ + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"normal", BMO_OP_SLOT_VEC}, /* optionally pass the fill normal to use */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new faces and edges */ + {{'\0'}}, + }, + bmo_triangle_fill_exec, + (BMO_OPTYPE_FLAG_UNTAN_MULTIRES | + BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1853,19 +1853,19 @@ static BMOpDefine bmo_triangle_fill_def = { * Turns a mesh into a shell with thickness */ static BMOpDefine bmo_solidify_def = { - "solidify", - /* slots_in */ - {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"thickness", BMO_OP_SLOT_FLT}, - {{'\0'}}, - }, - /* slots_out */ - {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {{'\0'}}, - }, - bmo_solidify_face_region_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "solidify", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"thickness", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, + bmo_solidify_face_region_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1874,23 +1874,23 @@ static BMOpDefine bmo_solidify_def = { * Insets individual faces. */ static BMOpDefine bmo_inset_individual_def = { - "inset_individual", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"thickness", BMO_OP_SLOT_FLT}, - {"depth", BMO_OP_SLOT_FLT}, - {"use_even_offset", BMO_OP_SLOT_BOOL}, - {"use_interpolate", BMO_OP_SLOT_BOOL}, - {"use_relative_offset", BMO_OP_SLOT_BOOL}, - {{'\0'}}, - }, - /* slots_out */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ - {{'\0'}}, - }, - bmo_inset_individual_exec, - /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */ - (BMO_OPTYPE_FLAG_NORMALS_CALC), + "inset_individual", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"thickness", BMO_OP_SLOT_FLT}, + {"depth", BMO_OP_SLOT_FLT}, + {"use_even_offset", BMO_OP_SLOT_BOOL}, + {"use_interpolate", BMO_OP_SLOT_BOOL}, + {"use_relative_offset", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, + bmo_inset_individual_exec, + /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */ + (BMO_OPTYPE_FLAG_NORMALS_CALC), }; /* @@ -1899,27 +1899,27 @@ static BMOpDefine bmo_inset_individual_def = { * Inset or outset face regions. */ static BMOpDefine bmo_inset_region_def = { - "inset_region", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, - {"use_boundary", BMO_OP_SLOT_BOOL}, - {"use_even_offset", BMO_OP_SLOT_BOOL}, - {"use_interpolate", BMO_OP_SLOT_BOOL}, - {"use_relative_offset", BMO_OP_SLOT_BOOL}, - {"use_edge_rail", BMO_OP_SLOT_BOOL}, - {"thickness", BMO_OP_SLOT_FLT}, - {"depth", BMO_OP_SLOT_FLT}, - {"use_outset", BMO_OP_SLOT_BOOL}, - {{'\0'}}, - }, - /* slots_out */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ - {{'\0'}}, - }, - bmo_inset_region_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "inset_region", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_boundary", BMO_OP_SLOT_BOOL}, + {"use_even_offset", BMO_OP_SLOT_BOOL}, + {"use_interpolate", BMO_OP_SLOT_BOOL}, + {"use_relative_offset", BMO_OP_SLOT_BOOL}, + {"use_edge_rail", BMO_OP_SLOT_BOOL}, + {"thickness", BMO_OP_SLOT_FLT}, + {"depth", BMO_OP_SLOT_FLT}, + {"use_outset", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, + bmo_inset_region_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1928,19 +1928,19 @@ static BMOpDefine bmo_inset_region_def = { * Creates edge loops based on simple edge-outset method. */ static BMOpDefine bmo_offset_edgeloops_def = { - "offset_edgeloops", - /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input faces */ - {"use_cap_endpoint", BMO_OP_SLOT_BOOL}, - {{'\0'}}, - }, - /* slots_out */ - {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output faces */ - {{'\0'}}, - }, - bmo_offset_edgeloops_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH), + "offset_edgeloops", + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input faces */ + {"use_cap_endpoint", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output faces */ + {{'\0'}}, + }, + bmo_offset_edgeloops_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH), }; /* @@ -1949,35 +1949,35 @@ static BMOpDefine bmo_offset_edgeloops_def = { * Makes a wire-frame copy of faces. */ static BMOpDefine bmo_wireframe_def = { - "wireframe", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"thickness", BMO_OP_SLOT_FLT}, - {"offset", BMO_OP_SLOT_FLT}, - {"use_replace", BMO_OP_SLOT_BOOL}, - {"use_boundary", BMO_OP_SLOT_BOOL}, - {"use_even_offset", BMO_OP_SLOT_BOOL}, - {"use_crease", BMO_OP_SLOT_BOOL}, - {"crease_weight", BMO_OP_SLOT_FLT}, - {"use_relative_offset", BMO_OP_SLOT_BOOL}, - {"material_offset", BMO_OP_SLOT_INT}, - {{'\0'}}, - }, - /* slots_out */ - {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ - {{'\0'}}, - }, - bmo_wireframe_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "wireframe", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"thickness", BMO_OP_SLOT_FLT}, + {"offset", BMO_OP_SLOT_FLT}, + {"use_replace", BMO_OP_SLOT_BOOL}, + {"use_boundary", BMO_OP_SLOT_BOOL}, + {"use_even_offset", BMO_OP_SLOT_BOOL}, + {"use_crease", BMO_OP_SLOT_BOOL}, + {"crease_weight", BMO_OP_SLOT_FLT}, + {"use_relative_offset", BMO_OP_SLOT_BOOL}, + {"material_offset", BMO_OP_SLOT_INT}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, + bmo_wireframe_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; static BMO_FlagSet bmo_enum_poke_center_mode[] = { - {BMOP_POKE_MEDIAN_WEIGHTED, "MEAN_WEIGHTED"}, - {BMOP_POKE_MEDIAN, "MEAN"}, - {BMOP_POKE_BOUNDS, "BOUNDS"}, - {0, NULL}, + {BMOP_POKE_MEDIAN_WEIGHTED, "MEAN_WEIGHTED"}, + {BMOP_POKE_MEDIAN, "MEAN"}, + {BMOP_POKE_BOUNDS, "BOUNDS"}, + {0, NULL}, }; /* @@ -1986,23 +1986,23 @@ static BMO_FlagSet bmo_enum_poke_center_mode[] = { * Splits a face into a triangle fan. */ static BMOpDefine bmo_poke_def = { - "poke", - /* slots_in */ - {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ - {"offset", BMO_OP_SLOT_FLT}, /* center vertex offset along normal */ - {"center_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_poke_center_mode}, /* calculation mode for center vertex */ - {"use_relative_offset", BMO_OP_SLOT_BOOL}, /* apply offset */ - {{'\0'}}, - }, - /* slots_out */ - {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ - {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ - {{'\0'}}, - }, - bmo_poke_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "poke", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"offset", BMO_OP_SLOT_FLT}, /* center vertex offset along normal */ + {"center_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_poke_center_mode}, /* calculation mode for center vertex */ + {"use_relative_offset", BMO_OP_SLOT_BOOL}, /* apply offset */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, + bmo_poke_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; #ifdef WITH_BULLET @@ -2022,23 +2022,23 @@ static BMOpDefine bmo_poke_def = { * that were in the input and are part of the hull. */ static BMOpDefine bmo_convex_hull_def = { - "convex_hull", - /* slots_in */ - {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"use_existing_faces", BMO_OP_SLOT_BOOL}, - {{'\0'}}, - }, - /* slots_out */ - {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"geom_interior.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"geom_unused.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"geom_holes.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {{'\0'}}, - }, - bmo_convex_hull_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "convex_hull", + /* slots_in */ + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"use_existing_faces", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_interior.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_unused.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_holes.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, + bmo_convex_hull_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; #endif @@ -2053,108 +2053,108 @@ static BMOpDefine bmo_convex_hull_def = { * All new vertices, edges, and faces are added to the "geom.out" slot. */ static BMOpDefine bmo_symmetrize_def = { - "symmetrize", - /* slots_in */ - {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"direction", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_axis_xyz}, /* axis to use */ - {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ - {{'\0'}}, - }, - /* slots_out */ - {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {{'\0'}}, - }, - bmo_symmetrize_exec, - (BMO_OPTYPE_FLAG_NORMALS_CALC | - BMO_OPTYPE_FLAG_SELECT_FLUSH | - BMO_OPTYPE_FLAG_SELECT_VALIDATE), + "symmetrize", + /* slots_in */ + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"direction", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_axis_xyz}, /* axis to use */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, + bmo_symmetrize_exec, + (BMO_OPTYPE_FLAG_NORMALS_CALC | + BMO_OPTYPE_FLAG_SELECT_FLUSH | + BMO_OPTYPE_FLAG_SELECT_VALIDATE), }; /* clang-format on */ const BMOpDefine *bmo_opdefines[] = { - &bmo_automerge_def, - &bmo_average_vert_facedata_def, - &bmo_beautify_fill_def, - &bmo_bevel_def, - &bmo_bisect_edges_def, - &bmo_bmesh_to_mesh_def, - &bmo_bridge_loops_def, - &bmo_collapse_def, - &bmo_collapse_uvs_def, - &bmo_connect_verts_def, - &bmo_connect_verts_concave_def, - &bmo_connect_verts_nonplanar_def, - &bmo_connect_vert_pair_def, - &bmo_contextual_create_def, + &bmo_automerge_def, + &bmo_average_vert_facedata_def, + &bmo_beautify_fill_def, + &bmo_bevel_def, + &bmo_bisect_edges_def, + &bmo_bmesh_to_mesh_def, + &bmo_bridge_loops_def, + &bmo_collapse_def, + &bmo_collapse_uvs_def, + &bmo_connect_verts_def, + &bmo_connect_verts_concave_def, + &bmo_connect_verts_nonplanar_def, + &bmo_connect_vert_pair_def, + &bmo_contextual_create_def, #ifdef WITH_BULLET - &bmo_convex_hull_def, + &bmo_convex_hull_def, #endif - &bmo_create_circle_def, - &bmo_create_cone_def, - &bmo_create_cube_def, - &bmo_create_grid_def, - &bmo_create_icosphere_def, - &bmo_create_monkey_def, - &bmo_create_uvsphere_def, - &bmo_create_vert_def, - &bmo_delete_def, - &bmo_dissolve_edges_def, - &bmo_dissolve_faces_def, - &bmo_dissolve_verts_def, - &bmo_dissolve_limit_def, - &bmo_dissolve_degenerate_def, - &bmo_duplicate_def, - &bmo_holes_fill_def, - &bmo_face_attribute_fill_def, - &bmo_offset_edgeloops_def, - &bmo_edgeloop_fill_def, - &bmo_edgenet_fill_def, - &bmo_edgenet_prepare_def, - &bmo_extrude_discrete_faces_def, - &bmo_extrude_edge_only_def, - &bmo_extrude_face_region_def, - &bmo_extrude_vert_indiv_def, - &bmo_find_doubles_def, - &bmo_grid_fill_def, - &bmo_inset_individual_def, - &bmo_inset_region_def, - &bmo_join_triangles_def, - &bmo_mesh_to_bmesh_def, - &bmo_mirror_def, - &bmo_object_load_bmesh_def, - &bmo_pointmerge_def, - &bmo_pointmerge_facedata_def, - &bmo_poke_def, - &bmo_recalc_face_normals_def, - &bmo_planar_faces_def, - &bmo_region_extend_def, - &bmo_remove_doubles_def, - &bmo_reverse_colors_def, - &bmo_reverse_faces_def, - &bmo_reverse_uvs_def, - &bmo_rotate_colors_def, - &bmo_rotate_def, - &bmo_rotate_edges_def, - &bmo_rotate_uvs_def, - &bmo_scale_def, - &bmo_smooth_vert_def, - &bmo_smooth_laplacian_vert_def, - &bmo_solidify_def, - &bmo_spin_def, - &bmo_split_def, - &bmo_split_edges_def, - &bmo_subdivide_edges_def, - &bmo_subdivide_edgering_def, - &bmo_bisect_plane_def, - &bmo_symmetrize_def, - &bmo_transform_def, - &bmo_translate_def, - &bmo_triangle_fill_def, - &bmo_triangulate_def, - &bmo_unsubdivide_def, - &bmo_weld_verts_def, - &bmo_wireframe_def, + &bmo_create_circle_def, + &bmo_create_cone_def, + &bmo_create_cube_def, + &bmo_create_grid_def, + &bmo_create_icosphere_def, + &bmo_create_monkey_def, + &bmo_create_uvsphere_def, + &bmo_create_vert_def, + &bmo_delete_def, + &bmo_dissolve_edges_def, + &bmo_dissolve_faces_def, + &bmo_dissolve_verts_def, + &bmo_dissolve_limit_def, + &bmo_dissolve_degenerate_def, + &bmo_duplicate_def, + &bmo_holes_fill_def, + &bmo_face_attribute_fill_def, + &bmo_offset_edgeloops_def, + &bmo_edgeloop_fill_def, + &bmo_edgenet_fill_def, + &bmo_edgenet_prepare_def, + &bmo_extrude_discrete_faces_def, + &bmo_extrude_edge_only_def, + &bmo_extrude_face_region_def, + &bmo_extrude_vert_indiv_def, + &bmo_find_doubles_def, + &bmo_grid_fill_def, + &bmo_inset_individual_def, + &bmo_inset_region_def, + &bmo_join_triangles_def, + &bmo_mesh_to_bmesh_def, + &bmo_mirror_def, + &bmo_object_load_bmesh_def, + &bmo_pointmerge_def, + &bmo_pointmerge_facedata_def, + &bmo_poke_def, + &bmo_recalc_face_normals_def, + &bmo_planar_faces_def, + &bmo_region_extend_def, + &bmo_remove_doubles_def, + &bmo_reverse_colors_def, + &bmo_reverse_faces_def, + &bmo_reverse_uvs_def, + &bmo_rotate_colors_def, + &bmo_rotate_def, + &bmo_rotate_edges_def, + &bmo_rotate_uvs_def, + &bmo_scale_def, + &bmo_smooth_vert_def, + &bmo_smooth_laplacian_vert_def, + &bmo_solidify_def, + &bmo_spin_def, + &bmo_split_def, + &bmo_split_edges_def, + &bmo_subdivide_edges_def, + &bmo_subdivide_edgering_def, + &bmo_bisect_plane_def, + &bmo_symmetrize_def, + &bmo_transform_def, + &bmo_translate_def, + &bmo_triangle_fill_def, + &bmo_triangulate_def, + &bmo_unsubdivide_def, + &bmo_weld_verts_def, + &bmo_wireframe_def, }; const int bmo_opdefines_total = ARRAY_SIZE(bmo_opdefines); diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 9894252a53a..5085eb801ce 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -71,222 +71,274 @@ struct GHashIterator; BLI_INLINE BMFlagLayer *BMO_elem_flag_from_header(BMHeader *ele_head) { - switch (ele_head->htype) { - case BM_VERT: return ((BMVert_OFlag *)ele_head)->oflags; - case BM_EDGE: return ((BMEdge_OFlag *)ele_head)->oflags; - default: return ((BMFace_OFlag *)ele_head)->oflags; - } + switch (ele_head->htype) { + case BM_VERT: + return ((BMVert_OFlag *)ele_head)->oflags; + case BM_EDGE: + return ((BMEdge_OFlag *)ele_head)->oflags; + default: + return ((BMFace_OFlag *)ele_head)->oflags; + } } #define BMO_elem_flag_test(bm, ele, oflag) \ - _bmo_elem_flag_test(bm, BMO_elem_flag_from_header(&(ele)->head), oflag) + _bmo_elem_flag_test(bm, BMO_elem_flag_from_header(&(ele)->head), oflag) #define BMO_elem_flag_test_bool(bm, ele, oflag) \ - _bmo_elem_flag_test_bool(bm, BMO_elem_flag_from_header(&(ele)->head), oflag) + _bmo_elem_flag_test_bool(bm, BMO_elem_flag_from_header(&(ele)->head), oflag) #define BMO_elem_flag_enable(bm, ele, oflag) \ - _bmo_elem_flag_enable(bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag) + _bmo_elem_flag_enable( \ + bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag) #define BMO_elem_flag_disable(bm, ele, oflag) \ - _bmo_elem_flag_disable(bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag) + _bmo_elem_flag_disable( \ + bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag) #define BMO_elem_flag_set(bm, ele, oflag, val) \ - _bmo_elem_flag_set(bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag, val) + _bmo_elem_flag_set(bm, \ + (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), \ + oflag, \ + val) #define BMO_elem_flag_toggle(bm, ele, oflag) \ - _bmo_elem_flag_toggle(bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag) + _bmo_elem_flag_toggle( \ + bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag) /* take care not to instansiate args multiple times */ #ifdef __GNUC___ -#define _BMO_CAST_V_CONST(e) ({ typeof(e) _e = e; \ - (BM_CHECK_TYPE_VERT(_e), BLI_assert(((const BMHeader *)_e)->htype == BM_VERT), (const BMVert_OFlag *)_e); }) -#define _BMO_CAST_E_CONST(e) ({ typeof(e) _e = e; \ - (BM_CHECK_TYPE_EDGE(_e), BLI_assert(((const BMHeader *)_e)->htype == BM_EDGE), (const BMEdge_OFlag *)_e); }) -#define _BMO_CAST_F_CONST(e) ({ typeof(e) _e = e; \ - (BM_CHECK_TYPE_FACE(_e), BLI_assert(((const BMHeader *)_e)->htype == BM_FACE), (const BMFace_OFlag *)_e); }) -#define _BMO_CAST_V(e) ({ typeof(e) _e = e; \ - (BM_CHECK_TYPE_VERT_NONCONST(_e), BLI_assert(((BMHeader *)_e)->htype == BM_VERT), (BMVert_OFlag *)_e); }) -#define _BMO_CAST_E(e) ({ typeof(e) _e = e; \ - (BM_CHECK_TYPE_EDGE_NONCONST(_e), BLI_assert(((BMHeader *)_e)->htype == BM_EDGE), (BMEdge_OFlag *)_e); }) -#define _BMO_CAST_F(e) ({ typeof(e) _e = e; \ - (BM_CHECK_TYPE_FACE_NONCONST(_e), BLI_assert(((BMHeader *)_e)->htype == BM_FACE), (BMFace_OFlag *)_e); }) +# define _BMO_CAST_V_CONST(e) \ + ({ \ + typeof(e) _e = e; \ + (BM_CHECK_TYPE_VERT(_e), \ + BLI_assert(((const BMHeader *)_e)->htype == BM_VERT), \ + (const BMVert_OFlag *)_e); \ + }) +# define _BMO_CAST_E_CONST(e) \ + ({ \ + typeof(e) _e = e; \ + (BM_CHECK_TYPE_EDGE(_e), \ + BLI_assert(((const BMHeader *)_e)->htype == BM_EDGE), \ + (const BMEdge_OFlag *)_e); \ + }) +# define _BMO_CAST_F_CONST(e) \ + ({ \ + typeof(e) _e = e; \ + (BM_CHECK_TYPE_FACE(_e), \ + BLI_assert(((const BMHeader *)_e)->htype == BM_FACE), \ + (const BMFace_OFlag *)_e); \ + }) +# define _BMO_CAST_V(e) \ + ({ \ + typeof(e) _e = e; \ + (BM_CHECK_TYPE_VERT_NONCONST(_e), \ + BLI_assert(((BMHeader *)_e)->htype == BM_VERT), \ + (BMVert_OFlag *)_e); \ + }) +# define _BMO_CAST_E(e) \ + ({ \ + typeof(e) _e = e; \ + (BM_CHECK_TYPE_EDGE_NONCONST(_e), \ + BLI_assert(((BMHeader *)_e)->htype == BM_EDGE), \ + (BMEdge_OFlag *)_e); \ + }) +# define _BMO_CAST_F(e) \ + ({ \ + typeof(e) _e = e; \ + (BM_CHECK_TYPE_FACE_NONCONST(_e), \ + BLI_assert(((BMHeader *)_e)->htype == BM_FACE), \ + (BMFace_OFlag *)_e); \ + }) #else -#define _BMO_CAST_V_CONST(e) (BM_CHECK_TYPE_VERT(e), (const BMVert_OFlag *)e) -#define _BMO_CAST_E_CONST(e) (BM_CHECK_TYPE_EDGE(e), (const BMEdge_OFlag *)e) -#define _BMO_CAST_F_CONST(e) (BM_CHECK_TYPE_FACE(e), (const BMFace_OFlag *)e) -#define _BMO_CAST_V(e) (BM_CHECK_TYPE_VERT_NONCONST(e), (BMVert_OFlag *)e) -#define _BMO_CAST_E(e) (BM_CHECK_TYPE_EDGE_NONCONST(e), (BMEdge_OFlag *)e) -#define _BMO_CAST_F(e) (BM_CHECK_TYPE_FACE_NONCONST(e), (BMFace_OFlag *)e) +# define _BMO_CAST_V_CONST(e) (BM_CHECK_TYPE_VERT(e), (const BMVert_OFlag *)e) +# define _BMO_CAST_E_CONST(e) (BM_CHECK_TYPE_EDGE(e), (const BMEdge_OFlag *)e) +# define _BMO_CAST_F_CONST(e) (BM_CHECK_TYPE_FACE(e), (const BMFace_OFlag *)e) +# define _BMO_CAST_V(e) (BM_CHECK_TYPE_VERT_NONCONST(e), (BMVert_OFlag *)e) +# define _BMO_CAST_E(e) (BM_CHECK_TYPE_EDGE_NONCONST(e), (BMEdge_OFlag *)e) +# define _BMO_CAST_F(e) (BM_CHECK_TYPE_FACE_NONCONST(e), (BMFace_OFlag *)e) #endif -#define BMO_vert_flag_test( bm, e, oflag) _bmo_elem_flag_test (bm, _BMO_CAST_V_CONST(e)->oflags, oflag) -#define BMO_vert_flag_test_bool(bm, e, oflag) _bmo_elem_flag_test_bool(bm, _BMO_CAST_V_CONST(e)->oflags, oflag) -#define BMO_vert_flag_enable( bm, e, oflag) _bmo_elem_flag_enable (bm, _BMO_CAST_V(e)->oflags, oflag) -#define BMO_vert_flag_disable( bm, e, oflag) _bmo_elem_flag_disable (bm, _BMO_CAST_V(e)->oflags, oflag) -#define BMO_vert_flag_set( bm, e, oflag, val) _bmo_elem_flag_set (bm, _BMO_CAST_V(e)->oflags, oflag, val) -#define BMO_vert_flag_toggle( bm, e, oflag) _bmo_elem_flag_toggle (bm, _BMO_CAST_V(e)->oflags, oflag) - -#define BMO_edge_flag_test( bm, e, oflag) _bmo_elem_flag_test (bm, _BMO_CAST_E_CONST(e)->oflags, oflag) -#define BMO_edge_flag_test_bool(bm, e, oflag) _bmo_elem_flag_test_bool(bm, _BMO_CAST_E_CONST(e)->oflags, oflag) -#define BMO_edge_flag_enable( bm, e, oflag) _bmo_elem_flag_enable (bm, _BMO_CAST_E(e)->oflags, oflag) -#define BMO_edge_flag_disable( bm, e, oflag) _bmo_elem_flag_disable (bm, _BMO_CAST_E(e)->oflags, oflag) -#define BMO_edge_flag_set( bm, e, oflag, val) _bmo_elem_flag_set (bm, _BMO_CAST_E(e)->oflags, oflag, val) -#define BMO_edge_flag_toggle( bm, e, oflag) _bmo_elem_flag_toggle (bm, _BMO_CAST_E(e)->oflags, oflag) - -#define BMO_face_flag_test( bm, e, oflag) _bmo_elem_flag_test (bm, _BMO_CAST_F_CONST(e)->oflags, oflag) -#define BMO_face_flag_test_bool(bm, e, oflag) _bmo_elem_flag_test_bool(bm, _BMO_CAST_F_CONST(e)->oflags, oflag) -#define BMO_face_flag_enable( bm, e, oflag) _bmo_elem_flag_enable (bm, _BMO_CAST_F(e)->oflags, oflag) -#define BMO_face_flag_disable( bm, e, oflag) _bmo_elem_flag_disable (bm, _BMO_CAST_F(e)->oflags, oflag) -#define BMO_face_flag_set( bm, e, oflag, val) _bmo_elem_flag_set (bm, _BMO_CAST_F(e)->oflags, oflag, val) -#define BMO_face_flag_toggle( bm, e, oflag) _bmo_elem_flag_toggle (bm, _BMO_CAST_F(e)->oflags, oflag) - -BLI_INLINE short _bmo_elem_flag_test( BMesh *bm, const BMFlagLayer *oflags, const short oflag); -BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, const BMFlagLayer *oflags, const short oflag); -BLI_INLINE void _bmo_elem_flag_enable( BMesh *bm, BMFlagLayer *oflags, const short oflag); -BLI_INLINE void _bmo_elem_flag_disable( BMesh *bm, BMFlagLayer *oflags, const short oflag); -BLI_INLINE void _bmo_elem_flag_set( BMesh *bm, BMFlagLayer *oflags, const short oflag, int val); -BLI_INLINE void _bmo_elem_flag_toggle( BMesh *bm, BMFlagLayer *oflags, const short oflag); +#define BMO_vert_flag_test(bm, e, oflag) \ + _bmo_elem_flag_test(bm, _BMO_CAST_V_CONST(e)->oflags, oflag) +#define BMO_vert_flag_test_bool(bm, e, oflag) \ + _bmo_elem_flag_test_bool(bm, _BMO_CAST_V_CONST(e)->oflags, oflag) +#define BMO_vert_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_V(e)->oflags, oflag) +#define BMO_vert_flag_disable(bm, e, oflag) \ + _bmo_elem_flag_disable(bm, _BMO_CAST_V(e)->oflags, oflag) +#define BMO_vert_flag_set(bm, e, oflag, val) \ + _bmo_elem_flag_set(bm, _BMO_CAST_V(e)->oflags, oflag, val) +#define BMO_vert_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_V(e)->oflags, oflag) + +#define BMO_edge_flag_test(bm, e, oflag) \ + _bmo_elem_flag_test(bm, _BMO_CAST_E_CONST(e)->oflags, oflag) +#define BMO_edge_flag_test_bool(bm, e, oflag) \ + _bmo_elem_flag_test_bool(bm, _BMO_CAST_E_CONST(e)->oflags, oflag) +#define BMO_edge_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_E(e)->oflags, oflag) +#define BMO_edge_flag_disable(bm, e, oflag) \ + _bmo_elem_flag_disable(bm, _BMO_CAST_E(e)->oflags, oflag) +#define BMO_edge_flag_set(bm, e, oflag, val) \ + _bmo_elem_flag_set(bm, _BMO_CAST_E(e)->oflags, oflag, val) +#define BMO_edge_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_E(e)->oflags, oflag) + +#define BMO_face_flag_test(bm, e, oflag) \ + _bmo_elem_flag_test(bm, _BMO_CAST_F_CONST(e)->oflags, oflag) +#define BMO_face_flag_test_bool(bm, e, oflag) \ + _bmo_elem_flag_test_bool(bm, _BMO_CAST_F_CONST(e)->oflags, oflag) +#define BMO_face_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_F(e)->oflags, oflag) +#define BMO_face_flag_disable(bm, e, oflag) \ + _bmo_elem_flag_disable(bm, _BMO_CAST_F(e)->oflags, oflag) +#define BMO_face_flag_set(bm, e, oflag, val) \ + _bmo_elem_flag_set(bm, _BMO_CAST_F(e)->oflags, oflag, val) +#define BMO_face_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_F(e)->oflags, oflag) + +BLI_INLINE short _bmo_elem_flag_test(BMesh *bm, const BMFlagLayer *oflags, const short oflag); +BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, const BMFlagLayer *oflags, const short oflag); +BLI_INLINE void _bmo_elem_flag_enable(BMesh *bm, BMFlagLayer *oflags, const short oflag); +BLI_INLINE void _bmo_elem_flag_disable(BMesh *bm, BMFlagLayer *oflags, const short oflag); +BLI_INLINE void _bmo_elem_flag_set(BMesh *bm, BMFlagLayer *oflags, const short oflag, int val); +BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const short oflag); /* slot type arrays are terminated by the last member * having a slot type of 0 */ typedef enum eBMOpSlotType { - /* BMO_OP_SLOT_SENTINEL = 0, */ - BMO_OP_SLOT_BOOL = 1, - BMO_OP_SLOT_INT = 2, - BMO_OP_SLOT_FLT = 3, - - /* normally store pointers to object, scene, - * _never_ store arrays corresponding to mesh elements with this */ - BMO_OP_SLOT_PTR = 4, /* requres subtype BMO_OP_SLOT_SUBTYPE_PTR_xxx */ - BMO_OP_SLOT_MAT = 5, - BMO_OP_SLOT_VEC = 8, - - /* after BMO_OP_SLOT_VEC, everything is dynamically allocated arrays. - * We leave a space in the identifiers for future growth. - * - * it's very important this remain a power of two */ - BMO_OP_SLOT_ELEMENT_BUF = 9, /* list of verts/edges/faces */ - BMO_OP_SLOT_MAPPING = 10 /* simple hash map, requres subtype BMO_OP_SLOT_SUBTYPE_MAP_xxx */ + /* BMO_OP_SLOT_SENTINEL = 0, */ + BMO_OP_SLOT_BOOL = 1, + BMO_OP_SLOT_INT = 2, + BMO_OP_SLOT_FLT = 3, + + /* normally store pointers to object, scene, + * _never_ store arrays corresponding to mesh elements with this */ + BMO_OP_SLOT_PTR = 4, /* requres subtype BMO_OP_SLOT_SUBTYPE_PTR_xxx */ + BMO_OP_SLOT_MAT = 5, + BMO_OP_SLOT_VEC = 8, + + /* after BMO_OP_SLOT_VEC, everything is dynamically allocated arrays. + * We leave a space in the identifiers for future growth. + * + * it's very important this remain a power of two */ + BMO_OP_SLOT_ELEMENT_BUF = 9, /* list of verts/edges/faces */ + BMO_OP_SLOT_MAPPING = 10 /* simple hash map, requres subtype BMO_OP_SLOT_SUBTYPE_MAP_xxx */ } eBMOpSlotType; #define BMO_OP_SLOT_TOTAL_TYPES 11 /* don't overlap values to avoid confusion */ typedef enum eBMOpSlotSubType_Elem { - /* use as flags */ - BMO_OP_SLOT_SUBTYPE_ELEM_VERT = BM_VERT, - BMO_OP_SLOT_SUBTYPE_ELEM_EDGE = BM_EDGE, - BMO_OP_SLOT_SUBTYPE_ELEM_FACE = BM_FACE, - BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE = (BM_FACE << 1), + /* use as flags */ + BMO_OP_SLOT_SUBTYPE_ELEM_VERT = BM_VERT, + BMO_OP_SLOT_SUBTYPE_ELEM_EDGE = BM_EDGE, + BMO_OP_SLOT_SUBTYPE_ELEM_FACE = BM_FACE, + BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE = (BM_FACE << 1), } eBMOpSlotSubType_Elem; typedef enum eBMOpSlotSubType_Map { - BMO_OP_SLOT_SUBTYPE_MAP_EMPTY = 64, /* use as a set(), unused value */ - BMO_OP_SLOT_SUBTYPE_MAP_ELEM = 65, - BMO_OP_SLOT_SUBTYPE_MAP_FLT = 66, - BMO_OP_SLOT_SUBTYPE_MAP_INT = 67, - BMO_OP_SLOT_SUBTYPE_MAP_BOOL = 68, - BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL = 69, /* python can't convert these */ + BMO_OP_SLOT_SUBTYPE_MAP_EMPTY = 64, /* use as a set(), unused value */ + BMO_OP_SLOT_SUBTYPE_MAP_ELEM = 65, + BMO_OP_SLOT_SUBTYPE_MAP_FLT = 66, + BMO_OP_SLOT_SUBTYPE_MAP_INT = 67, + BMO_OP_SLOT_SUBTYPE_MAP_BOOL = 68, + BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL = 69, /* python can't convert these */ } eBMOpSlotSubType_Map; typedef enum eBMOpSlotSubType_Ptr { - BMO_OP_SLOT_SUBTYPE_PTR_BMESH = 100, - BMO_OP_SLOT_SUBTYPE_PTR_SCENE = 101, - BMO_OP_SLOT_SUBTYPE_PTR_OBJECT = 102, - BMO_OP_SLOT_SUBTYPE_PTR_MESH = 103, + BMO_OP_SLOT_SUBTYPE_PTR_BMESH = 100, + BMO_OP_SLOT_SUBTYPE_PTR_SCENE = 101, + BMO_OP_SLOT_SUBTYPE_PTR_OBJECT = 102, + BMO_OP_SLOT_SUBTYPE_PTR_MESH = 103, } eBMOpSlotSubType_Ptr; typedef enum eBMOpSlotSubType_Int { - BMO_OP_SLOT_SUBTYPE_INT_ENUM = 200, - BMO_OP_SLOT_SUBTYPE_INT_FLAG = 201, + BMO_OP_SLOT_SUBTYPE_INT_ENUM = 200, + BMO_OP_SLOT_SUBTYPE_INT_FLAG = 201, } eBMOpSlotSubType_Int; typedef union eBMOpSlotSubType_Union { - eBMOpSlotSubType_Elem elem; - eBMOpSlotSubType_Ptr ptr; - eBMOpSlotSubType_Map map; - eBMOpSlotSubType_Int intg; + eBMOpSlotSubType_Elem elem; + eBMOpSlotSubType_Ptr ptr; + eBMOpSlotSubType_Map map; + eBMOpSlotSubType_Int intg; } eBMOpSlotSubType_Union; typedef struct BMO_FlagSet { - int value; - const char *identifier; + int value; + const char *identifier; } BMO_FlagSet; /* please ignore all these structures, don't touch them in tool code, except * for when your defining an operator with BMOpDefine.*/ typedef struct BMOpSlot { - const char *slot_name; /* pointer to BMOpDefine.slot_args */ - eBMOpSlotType slot_type; - eBMOpSlotSubType_Union slot_subtype; - - int len; -// int flag; /* UNUSED */ -// int index; /* index within slot array */ /* UNUSED */ - union { - int i; - float f; - void *p; - float vec[3]; - void **buf; - GHash *ghash; - struct { - /** Don't clobber (i) when assigning flags, see #eBMOpSlotSubType_Int. */ - int _i; - BMO_FlagSet *flags; - } enum_data; - } data; + const char *slot_name; /* pointer to BMOpDefine.slot_args */ + eBMOpSlotType slot_type; + eBMOpSlotSubType_Union slot_subtype; + + int len; + // int flag; /* UNUSED */ + // int index; /* index within slot array */ /* UNUSED */ + union { + int i; + float f; + void *p; + float vec[3]; + void **buf; + GHash *ghash; + struct { + /** Don't clobber (i) when assigning flags, see #eBMOpSlotSubType_Int. */ + int _i; + BMO_FlagSet *flags; + } enum_data; + } data; } BMOpSlot; /* mainly for use outside bmesh internal code */ -#define BMO_SLOT_AS_BOOL(slot) ((slot)->data.i) -#define BMO_SLOT_AS_INT(slot) ((slot)->data.i) -#define BMO_SLOT_AS_FLOAT(slot) ((slot)->data.f) -#define BMO_SLOT_AS_VECTOR(slot) ((slot)->data.vec) -#define BMO_SLOT_AS_MATRIX(slot ) ((float (*)[4])((slot)->data.p)) -#define BMO_SLOT_AS_BUFFER(slot ) ((slot)->data.buf) -#define BMO_SLOT_AS_GHASH(slot ) ((slot)->data.ghash) +#define BMO_SLOT_AS_BOOL(slot) ((slot)->data.i) +#define BMO_SLOT_AS_INT(slot) ((slot)->data.i) +#define BMO_SLOT_AS_FLOAT(slot) ((slot)->data.f) +#define BMO_SLOT_AS_VECTOR(slot) ((slot)->data.vec) +#define BMO_SLOT_AS_MATRIX(slot) ((float(*)[4])((slot)->data.p)) +#define BMO_SLOT_AS_BUFFER(slot) ((slot)->data.buf) +#define BMO_SLOT_AS_GHASH(slot) ((slot)->data.ghash) #define BMO_ASSERT_SLOT_IN_OP(slot, op) \ - BLI_assert(((slot >= (op)->slots_in) && (slot < &(op)->slots_in[BMO_OP_MAX_SLOTS])) || \ - ((slot >= (op)->slots_out) && (slot < &(op)->slots_out[BMO_OP_MAX_SLOTS]))) + BLI_assert(((slot >= (op)->slots_in) && (slot < &(op)->slots_in[BMO_OP_MAX_SLOTS])) || \ + ((slot >= (op)->slots_out) && (slot < &(op)->slots_out[BMO_OP_MAX_SLOTS]))) /* way more than probably needed, compiler complains if limit hit */ #define BMO_OP_MAX_SLOTS 20 /* BMOpDefine->type_flag */ typedef enum { - BMO_OPTYPE_FLAG_NOP = 0, - BMO_OPTYPE_FLAG_UNTAN_MULTIRES = (1 << 0), /* switch from multires tangent space to absolute coordinates */ - BMO_OPTYPE_FLAG_NORMALS_CALC = (1 << 1), - BMO_OPTYPE_FLAG_SELECT_FLUSH = (1 << 2), - BMO_OPTYPE_FLAG_SELECT_VALIDATE = (1 << 3), - BMO_OPTYPE_FLAG_INVALIDATE_CLNOR_ALL = (1 << 4), + BMO_OPTYPE_FLAG_NOP = 0, + BMO_OPTYPE_FLAG_UNTAN_MULTIRES = + (1 << 0), /* switch from multires tangent space to absolute coordinates */ + BMO_OPTYPE_FLAG_NORMALS_CALC = (1 << 1), + BMO_OPTYPE_FLAG_SELECT_FLUSH = (1 << 2), + BMO_OPTYPE_FLAG_SELECT_VALIDATE = (1 << 3), + BMO_OPTYPE_FLAG_INVALIDATE_CLNOR_ALL = (1 << 4), } BMOpTypeFlag; typedef struct BMOperator { - struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]; - struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]; - void (*exec)(BMesh *bm, struct BMOperator *op); - struct MemArena *arena; - int type; - BMOpTypeFlag type_flag; - int flag; /* runtime options */ + struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]; + struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]; + void (*exec)(BMesh *bm, struct BMOperator *op); + struct MemArena *arena; + int type; + BMOpTypeFlag type_flag; + int flag; /* runtime options */ } BMOperator; enum { - BMO_FLAG_RESPECT_HIDE = 1, + BMO_FLAG_RESPECT_HIDE = 1, }; -#define BMO_FLAG_DEFAULTS BMO_FLAG_RESPECT_HIDE +#define BMO_FLAG_DEFAULTS BMO_FLAG_RESPECT_HIDE -#define MAX_SLOTNAME 32 +#define MAX_SLOTNAME 32 typedef struct BMOSlotType { - char name[MAX_SLOTNAME]; - eBMOpSlotType type; - eBMOpSlotSubType_Union subtype; - BMO_FlagSet *enum_flags; + char name[MAX_SLOTNAME]; + eBMOpSlotType type; + eBMOpSlotSubType_Union subtype; + BMO_FlagSet *enum_flags; } BMOSlotType; typedef struct BMOpDefine { - const char *opname; - BMOSlotType slot_types_in[BMO_OP_MAX_SLOTS]; - BMOSlotType slot_types_out[BMO_OP_MAX_SLOTS]; - void (*exec)(BMesh *bm, BMOperator *op); - BMOpTypeFlag type_flag; + const char *opname; + BMOSlotType slot_types_in[BMO_OP_MAX_SLOTS]; + BMOSlotType slot_types_out[BMO_OP_MAX_SLOTS]; + void (*exec)(BMesh *bm, BMOperator *op); + BMOpTypeFlag type_flag; } BMOpDefine; /*------------- Operator API --------------*/ @@ -337,177 +389,205 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif /* copies the data of a slot from one operator to another. src and dst are the * source/destination slot codes, respectively. */ -#define BMO_slot_copy(op_src, slots_src, slot_name_src, \ - op_dst, slots_dst, slot_name_dst) \ - _bmo_slot_copy((op_src)->slots_src, slot_name_src, \ - (op_dst)->slots_dst, slot_name_dst, \ - (op_dst)->arena) +#define BMO_slot_copy(op_src, slots_src, slot_name_src, op_dst, slots_dst, slot_name_dst) \ + _bmo_slot_copy( \ + (op_src)->slots_src, slot_name_src, (op_dst)->slots_dst, slot_name_dst, (op_dst)->arena) -void _bmo_slot_copy( - BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, - BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, - struct MemArena *arena_dst); +void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], + const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], + const char *slot_name_dst, + struct MemArena *arena_dst); /* del "context" slot values, used for operator too */ enum { - DEL_VERTS = 1, - DEL_EDGES, - DEL_ONLYFACES, - DEL_EDGESFACES, - DEL_FACES, - /* A version of 'DEL_FACES' that keeps edges on face boundaries, - * allowing the surrounding edge-loop to be kept from removed face regions. */ - DEL_FACES_KEEP_BOUNDARY, - DEL_ONLYTAGGED, + DEL_VERTS = 1, + DEL_EDGES, + DEL_ONLYFACES, + DEL_EDGESFACES, + DEL_FACES, + /* A version of 'DEL_FACES' that keeps edges on face boundaries, + * allowing the surrounding edge-loop to be kept from removed face regions. */ + DEL_FACES_KEEP_BOUNDARY, + DEL_ONLYTAGGED, }; typedef enum { - BMO_SYMMETRIZE_NEGATIVE_X, - BMO_SYMMETRIZE_NEGATIVE_Y, - BMO_SYMMETRIZE_NEGATIVE_Z, + BMO_SYMMETRIZE_NEGATIVE_X, + BMO_SYMMETRIZE_NEGATIVE_Y, + BMO_SYMMETRIZE_NEGATIVE_Z, - BMO_SYMMETRIZE_POSITIVE_X, - BMO_SYMMETRIZE_POSITIVE_Y, - BMO_SYMMETRIZE_POSITIVE_Z, + BMO_SYMMETRIZE_POSITIVE_X, + BMO_SYMMETRIZE_POSITIVE_Y, + BMO_SYMMETRIZE_POSITIVE_Z, } BMO_SymmDirection; typedef enum { - BMO_DELIM_NORMAL = 1 << 0, - BMO_DELIM_MATERIAL = 1 << 1, - BMO_DELIM_SEAM = 1 << 2, - BMO_DELIM_SHARP = 1 << 3, - BMO_DELIM_UV = 1 << 4, + BMO_DELIM_NORMAL = 1 << 0, + BMO_DELIM_MATERIAL = 1 << 1, + BMO_DELIM_SEAM = 1 << 2, + BMO_DELIM_SHARP = 1 << 3, + BMO_DELIM_UV = 1 << 4, } BMO_Delimit; void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag); -void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f); +void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const float f); float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i); -int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i); -bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i); +int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i); +bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len); - /* don't pass in arrays that are supposed to map to elements this way. * * so, e.g. passing in list of floats per element in another slot is bad. * passing in, e.g. pointer to an editmesh for the conversion operator is fine * though. */ -void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p); +void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p); void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]); -void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]); +void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const float vec[3]); +void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]); /* only supports square mats */ /* size must be 3 or 4; this api is meant only for transformation matrices. * note that internally the matrix is stored in 4x4 form, and it's safe to * call whichever BMO_Get_MatXXX function you want. */ -void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size); -void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]); -void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]); +void BMO_slot_mat_set(BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const float *mat, + int size); +void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + float r_mat[4][4]); +void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + float r_mat[3][3]); void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag); -void BMO_mesh_selected_remap( - BMesh *bm, - BMOpSlot *slot_vert_map, - BMOpSlot *slot_edge_map, - BMOpSlot *slot_face_map, - const bool check_select); +void BMO_mesh_selected_remap(BMesh *bm, + BMOpSlot *slot_vert_map, + BMOpSlot *slot_edge_map, + BMOpSlot *slot_face_map, + const bool check_select); /* copies the values from another slot to the end of the output slot */ -#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \ - op_dst, slots_dst, slot_name_dst) \ - _bmo_slot_buffer_append((op_src)->slots_src, slot_name_src, \ - (op_dst)->slots_dst, slot_name_dst, \ - (op_dst)->arena) -void _bmo_slot_buffer_append( - BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, - BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, - struct MemArena *arena_dst); +#define BMO_slot_buffer_append( \ + op_src, slots_src, slot_name_src, op_dst, slots_dst, slot_name_dst) \ + _bmo_slot_buffer_append( \ + (op_src)->slots_src, slot_name_src, (op_dst)->slots_dst, slot_name_dst, (op_dst)->arena) +void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], + const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], + const char *slot_name_src, + struct MemArena *arena_dst); /* puts every element of type 'type' (which is a bitmask) with tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_enabled_flag( - BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +void BMO_slot_buffer_from_enabled_flag(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const short oflag); /* puts every element of type 'type' (which is a bitmask) without tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_disabled_flag( - BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +void BMO_slot_buffer_from_disabled_flag(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_flag_enable( - BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +void BMO_slot_buffer_flag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const short oflag); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_flag_disable( - BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +void BMO_slot_buffer_flag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_hflag_enable( - BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const bool do_flush); +void BMO_slot_buffer_hflag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const char hflag, + const bool do_flush); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_hflag_disable( - BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const bool do_flush); +void BMO_slot_buffer_hflag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const char hflag, + const bool do_flush); /* puts every element of type 'type' (which is a bitmask) with header * flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ -void BMO_slot_buffer_from_enabled_hflag( - BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag); +void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const char hflag); /* puts every element of type 'type' (which is a bitmask) without * header flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ -void BMO_slot_buffer_from_disabled_hflag( - BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag); - -void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len); - -void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele); +void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const char hflag); + +void BMO_slot_buffer_from_array(BMOperator *op, + BMOpSlot *slot, + BMHeader **ele_buffer, + int ele_buffer_len); + +void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele); void *BMO_slot_buffer_get_single(BMOpSlot *slot); - /* counts number of elements inside a slot array. */ int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void BMO_slot_map_insert( - BMOperator *op, BMOpSlot *slot, - const void *element, const void *data); +void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, const void *element, const void *data); /* flags all elements in a mapping. note that the mapping must only have * bmesh elements in it.*/ -void BMO_slot_map_to_flag( - BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - const char *slot_name, const char hflag, const short oflag); - -void *BMO_slot_buffer_alloc( - BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - const char *slot_name, const int len); - -void BMO_slot_buffer_from_all( - BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - const char *slot_name, const char htype); +void BMO_slot_map_to_flag(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char hflag, + const short oflag); + +void *BMO_slot_buffer_alloc(BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const int len); + +void BMO_slot_buffer_from_all(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype); /** * This part of the API is used to iterate over element buffer or @@ -547,37 +627,38 @@ void BMO_slot_buffer_from_all( /* contents of this structure are private, * don't directly access. */ typedef struct BMOIter { - BMOpSlot *slot; - int cur; //for arrays - GHashIterator giter; - void **val; - char restrictmask; /* bitwise '&' with BMHeader.htype */ + BMOpSlot *slot; + int cur; //for arrays + GHashIterator giter; + void **val; + char restrictmask; /* bitwise '&' with BMHeader.htype */ } BMOIter; void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void *BMO_iter_new( - BMOIter *iter, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char restrictmask); +void *BMO_iter_new(BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char restrictmask); void *BMO_iter_step(BMOIter *iter); void **BMO_iter_map_value_p(BMOIter *iter); -void *BMO_iter_map_value_ptr(BMOIter *iter); +void *BMO_iter_map_value_ptr(BMOIter *iter); float BMO_iter_map_value_float(BMOIter *iter); -int BMO_iter_map_value_int(BMOIter *iter); -bool BMO_iter_map_value_bool(BMOIter *iter); - -#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \ - for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); \ - ele; \ - BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter)) - -#define BMO_ITER_INDEX(ele, iter, slot_args, slot_name, restrict_flag, i_) \ - for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag), i_ = 0; \ - ele; \ - BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter), i_++) +int BMO_iter_map_value_int(BMOIter *iter); +bool BMO_iter_map_value_bool(BMOIter *iter); + +#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \ + for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); \ + ele; \ + BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter)) + +#define BMO_ITER_INDEX(ele, iter, slot_args, slot_name, restrict_flag, i_) \ + for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag), \ + i_ = 0; \ + ele; \ + BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter), i_++) extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES]; diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index 78e75cf3d30..2bda2d121c2 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -32,195 +32,209 @@ * ghash or a mapping slot to do it. */ /* flags 15 and 16 (1 << 14 and 1 << 15) are reserved for bmesh api use */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) -BLI_INLINE short _bmo_elem_flag_test(BMesh *bm, const BMFlagLayer *oflags, const short oflag) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE + short _bmo_elem_flag_test(BMesh *bm, const BMFlagLayer *oflags, const short oflag) { - BLI_assert(bm->use_toolflags); - return oflags[bm->toolflag_index].f & oflag; + BLI_assert(bm->use_toolflags); + return oflags[bm->toolflag_index].f & oflag; } -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) -BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, const BMFlagLayer *oflags, const short oflag) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE + bool _bmo_elem_flag_test_bool(BMesh *bm, const BMFlagLayer *oflags, const short oflag) { - BLI_assert(bm->use_toolflags); - return (oflags[bm->toolflag_index].f & oflag) != 0; + BLI_assert(bm->use_toolflags); + return (oflags[bm->toolflag_index].f & oflag) != 0; } ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_enable(BMesh *bm, BMFlagLayer *oflags, const short oflag) { - BLI_assert(bm->use_toolflags); - oflags[bm->toolflag_index].f |= oflag; + BLI_assert(bm->use_toolflags); + oflags[bm->toolflag_index].f |= oflag; } ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_disable(BMesh *bm, BMFlagLayer *oflags, const short oflag) { - BLI_assert(bm->use_toolflags); - oflags[bm->toolflag_index].f &= (short)~oflag; + BLI_assert(bm->use_toolflags); + oflags[bm->toolflag_index].f &= (short)~oflag; } ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_set(BMesh *bm, BMFlagLayer *oflags, const short oflag, int val) { - BLI_assert(bm->use_toolflags); - if (val) { oflags[bm->toolflag_index].f |= oflag; } - else { oflags[bm->toolflag_index].f &= (short)~oflag; } + BLI_assert(bm->use_toolflags); + if (val) { + oflags[bm->toolflag_index].f |= oflag; + } + else { + oflags[bm->toolflag_index].f &= (short)~oflag; + } } ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const short oflag) { - BLI_assert(bm->use_toolflags); - oflags[bm->toolflag_index].f ^= oflag; + BLI_assert(bm->use_toolflags); + oflags[bm->toolflag_index].f ^= oflag; } ATTR_NONNULL(1, 2) -BLI_INLINE void BMO_slot_map_int_insert( - BMOperator *op, BMOpSlot *slot, - void *element, const int val) +BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, + BMOpSlot *slot, + void *element, + const int val) { - union { void *ptr; int val; } t = {NULL}; - BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); - BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr)); + union { + void *ptr; + int val; + } t = {NULL}; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); + BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr)); } ATTR_NONNULL(1, 2) -BLI_INLINE void BMO_slot_map_bool_insert( - BMOperator *op, BMOpSlot *slot, - void *element, const bool val) +BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, + BMOpSlot *slot, + void *element, + const bool val) { - union { void *ptr; bool val; } t = {NULL}; - BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); - BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr)); + union { + void *ptr; + bool val; + } t = {NULL}; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); + BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr)); } ATTR_NONNULL(1, 2) -BLI_INLINE void BMO_slot_map_float_insert( - BMOperator *op, BMOpSlot *slot, - void *element, const float val) +BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, + BMOpSlot *slot, + void *element, + const float val) { - union { void *ptr; float val; } t = {NULL}; - BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); - BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr)); + union { + void *ptr; + float val; + } t = {NULL}; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); + BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr)); } - /* pointer versions of BMO_slot_map_float_get and BMO_slot_map_float_insert. * * do NOT use these for non-operator-api-allocated memory! instead * use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */ ATTR_NONNULL(1, 2) -BLI_INLINE void BMO_slot_map_ptr_insert( - BMOperator *op, BMOpSlot *slot, - const void *element, void *val) +BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, + BMOpSlot *slot, + const void *element, + void *val) { - BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); - BMO_slot_map_insert(op, slot, element, val); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); + BMO_slot_map_insert(op, slot, element, val); } ATTR_NONNULL(1, 2) -BLI_INLINE void BMO_slot_map_elem_insert( - BMOperator *op, BMOpSlot *slot, - const void *element, void *val) +BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, + BMOpSlot *slot, + const void *element, + void *val) { - BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); - BMO_slot_map_insert(op, slot, element, val); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); + BMO_slot_map_insert(op, slot, element, val); } - /* no values */ ATTR_NONNULL(1, 2) -BLI_INLINE void BMO_slot_map_empty_insert( - BMOperator *op, BMOpSlot *slot, - const void *element) +BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot, const void *element) { - BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY); - BMO_slot_map_insert(op, slot, element, NULL); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY); + BMO_slot_map_insert(op, slot, element, NULL); } -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE bool BMO_slot_map_contains(BMOpSlot *slot, const void *element) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE + bool BMO_slot_map_contains(BMOpSlot *slot, const void *element) { - BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); - return BLI_ghash_haskey(slot->data.ghash, element); + BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); + return BLI_ghash_haskey(slot->data.ghash, element); } -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE void **BMO_slot_map_data_get(BMOpSlot *slot, const void *element) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE + void **BMO_slot_map_data_get(BMOpSlot *slot, const void *element) { - return BLI_ghash_lookup_p(slot->data.ghash, element); + return BLI_ghash_lookup_p(slot->data.ghash, element); } -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE + float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) { - void **data; - BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); + void **data; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); - data = BMO_slot_map_data_get(slot, element); - if (data) { - return *(float *)data; - } - else { - return 0.0f; - } + data = BMO_slot_map_data_get(slot, element); + if (data) { + return *(float *)data; + } + else { + return 0.0f; + } } -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE + int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) { - void **data; - BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); + void **data; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); - data = BMO_slot_map_data_get(slot, element); - if (data) { - return *(int *)data; - } - else { - return 0; - } + data = BMO_slot_map_data_get(slot, element); + if (data) { + return *(int *)data; + } + else { + return 0; + } } -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE + bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) { - void **data; - BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); + void **data; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); - data = BMO_slot_map_data_get(slot, element); - if (data) { - return *(bool *)data; - } - else { - return false; - } + data = BMO_slot_map_data_get(slot, element); + if (data) { + return *(bool *)data; + } + else { + return false; + } } -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE + void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) { - void **val = BMO_slot_map_data_get(slot, element); - BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); - if (val) { - return *val; - } + void **val = BMO_slot_map_data_get(slot, element); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); + if (val) { + return *val; + } - return NULL; + return NULL; } -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE + void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element) { - void **val = (void **) BMO_slot_map_data_get(slot, element); - BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); - if (val) { - return *val; - } + void **val = (void **)BMO_slot_map_data_get(slot, element); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); + if (val) { + return *val; + } - return NULL; + return NULL; } #endif /* __BMESH_OPERATOR_API_INLINE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index fb6edbecaed..a7783084c01 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -39,36 +39,37 @@ static void bmo_flag_layer_alloc(BMesh *bm); static void bmo_flag_layer_free(BMesh *bm); static void bmo_flag_layer_clear(BMesh *bm); static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); -static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); +static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *identifier); static const char *bmo_error_messages[] = { - NULL, - N_("Self intersection error"), - N_("Could not dissolve vert"), - N_("Could not connect vertices"), - N_("Could not traverse mesh"), - N_("Could not dissolve faces"), - N_("Tessellation error"), - N_("Cannot deal with non-manifold geometry"), - N_("Invalid selection"), - N_("Internal mesh error"), + NULL, + N_("Self intersection error"), + N_("Could not dissolve vert"), + N_("Could not connect vertices"), + N_("Could not traverse mesh"), + N_("Could not dissolve faces"), + N_("Tessellation error"), + N_("Cannot deal with non-manifold geometry"), + N_("Invalid selection"), + N_("Internal mesh error"), }; BLI_STATIC_ASSERT(ARRAY_SIZE(bmo_error_messages) + 1 == BMERR_TOTAL, "message mismatch"); /* operator slot type information - size of one element of the type given. */ const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = { - 0, /* 0: BMO_OP_SLOT_SENTINEL */ - sizeof(int), /* 1: BMO_OP_SLOT_BOOL */ - sizeof(int), /* 2: BMO_OP_SLOT_INT */ - sizeof(float), /* 3: BMO_OP_SLOT_FLT */ - sizeof(void *), /* 4: BMO_OP_SLOT_PNT */ - sizeof(void *), /* 5: BMO_OP_SLOT_PNT */ - 0, /* 6: unused */ - 0, /* 7: unused */ - sizeof(float) * 3, /* 8: BMO_OP_SLOT_VEC */ - sizeof(void *), /* 9: BMO_OP_SLOT_ELEMENT_BUF */ - sizeof(void *), /* 10: BMO_OP_SLOT_MAPPING */ + 0, /* 0: BMO_OP_SLOT_SENTINEL */ + sizeof(int), /* 1: BMO_OP_SLOT_BOOL */ + sizeof(int), /* 2: BMO_OP_SLOT_INT */ + sizeof(float), /* 3: BMO_OP_SLOT_FLT */ + sizeof(void *), /* 4: BMO_OP_SLOT_PNT */ + sizeof(void *), /* 5: BMO_OP_SLOT_PNT */ + 0, /* 6: unused */ + 0, /* 7: unused */ + sizeof(float) * 3, /* 8: BMO_OP_SLOT_VEC */ + sizeof(void *), /* 9: BMO_OP_SLOT_ELEMENT_BUF */ + sizeof(void *), /* 10: BMO_OP_SLOT_MAPPING */ }; /* Dummy slot so there is something to return when slot name lookup fails */ @@ -76,12 +77,12 @@ const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = { void BMO_op_flag_enable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag) { - op->flag |= op_flag; + op->flag |= op_flag; } void BMO_op_flag_disable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag) { - op->flag &= ~op_flag; + op->flag &= ~op_flag; } /** @@ -91,17 +92,17 @@ void BMO_op_flag_disable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag) */ void BMO_push(BMesh *bm, BMOperator *UNUSED(op)) { - bm->toolflag_index++; + bm->toolflag_index++; - BLI_assert(bm->totflags > 0); + BLI_assert(bm->totflags > 0); - /* add flag layer, if appropriate */ - if (bm->toolflag_index > 0) { - bmo_flag_layer_alloc(bm); - } - else { - bmo_flag_layer_clear(bm); - } + /* add flag layer, if appropriate */ + if (bm->toolflag_index > 0) { + bmo_flag_layer_alloc(bm); + } + else { + bmo_flag_layer_clear(bm); + } } /** @@ -113,54 +114,55 @@ void BMO_push(BMesh *bm, BMOperator *UNUSED(op)) */ void BMO_pop(BMesh *bm) { - if (bm->toolflag_index > 0) { - bmo_flag_layer_free(bm); - } + if (bm->toolflag_index > 0) { + bmo_flag_layer_free(bm); + } - bm->toolflag_index--; + bm->toolflag_index--; } - /* use for both slot_types_in and slot_types_out */ static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args) { - BMOpSlot *slot; - uint i; - for (i = 0; slot_types[i].type; i++) { - slot = &slot_args[i]; - slot->slot_name = slot_types[i].name; - slot->slot_type = slot_types[i].type; - slot->slot_subtype = slot_types[i].subtype; - // slot->index = i; // UNUSED - - switch (slot->slot_type) { - case BMO_OP_SLOT_MAPPING: - slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash"); - break; - case BMO_OP_SLOT_INT: - if (ELEM(slot->slot_subtype.intg, BMO_OP_SLOT_SUBTYPE_INT_ENUM, BMO_OP_SLOT_SUBTYPE_INT_FLAG)) { - slot->data.enum_data.flags = slot_types[i].enum_flags; - } - default: - break; - } - } + BMOpSlot *slot; + uint i; + for (i = 0; slot_types[i].type; i++) { + slot = &slot_args[i]; + slot->slot_name = slot_types[i].name; + slot->slot_type = slot_types[i].type; + slot->slot_subtype = slot_types[i].subtype; + // slot->index = i; // UNUSED + + switch (slot->slot_type) { + case BMO_OP_SLOT_MAPPING: + slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash"); + break; + case BMO_OP_SLOT_INT: + if (ELEM(slot->slot_subtype.intg, + BMO_OP_SLOT_SUBTYPE_INT_ENUM, + BMO_OP_SLOT_SUBTYPE_INT_FLAG)) { + slot->data.enum_data.flags = slot_types[i].enum_flags; + } + default: + break; + } + } } static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args) { - BMOpSlot *slot; - uint i; - for (i = 0; slot_types[i].type; i++) { - slot = &slot_args[i]; - switch (slot->slot_type) { - case BMO_OP_SLOT_MAPPING: - BLI_ghash_free(slot->data.ghash, NULL, NULL); - break; - default: - break; - } - } + BMOpSlot *slot; + uint i; + for (i = 0; slot_types[i].type; i++) { + slot = &slot_args[i]; + switch (slot->slot_type) { + case BMO_OP_SLOT_MAPPING: + BLI_ghash_free(slot->data.ghash, NULL, NULL); + break; + default: + break; + } + } } /** @@ -170,33 +172,33 @@ static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args */ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) { - int opcode = BMO_opcode_from_opname(opname); + int opcode = BMO_opcode_from_opname(opname); #ifdef DEBUG - BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname); + BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname); #else - (void)bm; + (void)bm; #endif - if (opcode == -1) { - opcode = 0; /* error!, already printed, have a better way to handle this? */ - } + if (opcode == -1) { + opcode = 0; /* error!, already printed, have a better way to handle this? */ + } - memset(op, 0, sizeof(BMOperator)); - op->type = opcode; - op->type_flag = bmo_opdefines[opcode]->type_flag; - op->flag = flag; + memset(op, 0, sizeof(BMOperator)); + op->type = opcode; + op->type_flag = bmo_opdefines[opcode]->type_flag; + op->flag = flag; - /* initialize the operator slot types */ - bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_in, op->slots_in); - bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_out, op->slots_out); + /* initialize the operator slot types */ + bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_in, op->slots_in); + bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_out, op->slots_out); - /* callback */ - op->exec = bmo_opdefines[opcode]->exec; + /* callback */ + op->exec = bmo_opdefines[opcode]->exec; - /* memarena, used for operator's slot buffers */ - op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - BLI_memarena_use_calloc(op->arena); + /* memarena, used for operator's slot buffers */ + op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + BLI_memarena_use_calloc(op->arena); } /** @@ -210,21 +212,21 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) */ void BMO_op_exec(BMesh *bm, BMOperator *op) { - /* allocate tool flags on demand */ - BM_mesh_elem_toolflags_ensure(bm); + /* allocate tool flags on demand */ + BM_mesh_elem_toolflags_ensure(bm); - BMO_push(bm, op); + BMO_push(bm, op); - if (bm->toolflag_index == 1) { - bmesh_edit_begin(bm, op->type_flag); - } - op->exec(bm, op); + if (bm->toolflag_index == 1) { + bmesh_edit_begin(bm, op->type_flag); + } + op->exec(bm, op); - if (bm->toolflag_index == 1) { - bmesh_edit_end(bm, op->type_flag); - } + if (bm->toolflag_index == 1) { + bmesh_edit_end(bm, op->type_flag); + } - BMO_pop(bm); + BMO_pop(bm); } /** @@ -234,18 +236,18 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) */ void BMO_op_finish(BMesh *bm, BMOperator *op) { - bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_in, op->slots_in); - bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_out, op->slots_out); + bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_in, op->slots_in); + bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_out, op->slots_out); - BLI_memarena_free(op->arena); + BLI_memarena_free(op->arena); #ifdef DEBUG - BM_ELEM_INDEX_VALIDATE(bm, "post bmo", bmo_opdefines[op->type]->opname); + BM_ELEM_INDEX_VALIDATE(bm, "post bmo", bmo_opdefines[op->type]->opname); - /* avoid accidental re-use */ - memset(op, 0xff, sizeof(*op)); + /* avoid accidental re-use */ + memset(op, 0xff, sizeof(*op)); #else - (void)bm; + (void)bm; #endif } @@ -256,8 +258,8 @@ void BMO_op_finish(BMesh *bm, BMOperator *op) */ bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int slot_code = bmo_name_to_slotcode(slot_args, identifier); - return (slot_code >= 0); + int slot_code = bmo_name_to_slotcode(slot_args, identifier); + return (slot_code >= 0); } /** @@ -267,15 +269,15 @@ bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifie */ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int slot_code = bmo_name_to_slotcode_check(slot_args, identifier); + int slot_code = bmo_name_to_slotcode_check(slot_args, identifier); - if (UNLIKELY(slot_code < 0)) { - //return &BMOpEmptySlot; - BLI_assert(0); - return NULL; /* better crash */ - } + if (UNLIKELY(slot_code < 0)) { + //return &BMOpEmptySlot; + BLI_assert(0); + return NULL; /* better crash */ + } - return &slot_args[slot_code]; + return &slot_args[slot_code]; } /** @@ -284,84 +286,85 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif * define used. * Copies data from one slot to another. */ -void _bmo_slot_copy( - BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, - BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, - struct MemArena *arena_dst) -{ - BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); - BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); - - if (slot_src == slot_dst) { - return; - } - - BLI_assert(slot_src->slot_type == slot_dst->slot_type); - if (slot_src->slot_type != slot_dst->slot_type) { - return; - } - - if (slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { - /* do buffer copy */ - slot_dst->data.buf = NULL; - slot_dst->len = slot_src->len; - if (slot_dst->len) { - /* check dest has all flags enabled that the source has */ - const eBMOpSlotSubType_Elem src_elem_flag = (slot_src->slot_subtype.elem & BM_ALL_NOLOOP); - const eBMOpSlotSubType_Elem dst_elem_flag = (slot_dst->slot_subtype.elem & BM_ALL_NOLOOP); - - if ((src_elem_flag | dst_elem_flag) == dst_elem_flag) { - /* pass */ - } - else { - /* check types */ - const uint tot = slot_src->len; - uint i; - uint out = 0; - BMElem **ele_src = (BMElem **)slot_src->data.buf; - for (i = 0; i < tot; i++, ele_src++) { - if ((*ele_src)->head.htype & dst_elem_flag) { - out++; - } - } - if (out != tot) { - slot_dst->len = out; - } - } - - if (slot_dst->len) { - const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len; - slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size); - if (slot_src->len == slot_dst->len) { - memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size); - } - else { - /* only copy compatible elements */ - const uint tot = slot_src->len; - uint i; - BMElem **ele_src = (BMElem **)slot_src->data.buf; - BMElem **ele_dst = (BMElem **)slot_dst->data.buf; - for (i = 0; i < tot; i++, ele_src++) { - if ((*ele_src)->head.htype & dst_elem_flag) { - *ele_dst = *ele_src; - ele_dst++; - } - } - } - } - } - } - else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) { - GHashIterator gh_iter; - GHASH_ITER (gh_iter, slot_src->data.ghash) { - void *key = BLI_ghashIterator_getKey(&gh_iter); - void *val = BLI_ghashIterator_getValue(&gh_iter); - BLI_ghash_insert(slot_dst->data.ghash, key, val); - } - } - else { - slot_dst->data = slot_src->data; - } +void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], + const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], + const char *slot_name_dst, + struct MemArena *arena_dst) +{ + BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); + BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); + + if (slot_src == slot_dst) { + return; + } + + BLI_assert(slot_src->slot_type == slot_dst->slot_type); + if (slot_src->slot_type != slot_dst->slot_type) { + return; + } + + if (slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { + /* do buffer copy */ + slot_dst->data.buf = NULL; + slot_dst->len = slot_src->len; + if (slot_dst->len) { + /* check dest has all flags enabled that the source has */ + const eBMOpSlotSubType_Elem src_elem_flag = (slot_src->slot_subtype.elem & BM_ALL_NOLOOP); + const eBMOpSlotSubType_Elem dst_elem_flag = (slot_dst->slot_subtype.elem & BM_ALL_NOLOOP); + + if ((src_elem_flag | dst_elem_flag) == dst_elem_flag) { + /* pass */ + } + else { + /* check types */ + const uint tot = slot_src->len; + uint i; + uint out = 0; + BMElem **ele_src = (BMElem **)slot_src->data.buf; + for (i = 0; i < tot; i++, ele_src++) { + if ((*ele_src)->head.htype & dst_elem_flag) { + out++; + } + } + if (out != tot) { + slot_dst->len = out; + } + } + + if (slot_dst->len) { + const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len; + slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size); + if (slot_src->len == slot_dst->len) { + memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size); + } + else { + /* only copy compatible elements */ + const uint tot = slot_src->len; + uint i; + BMElem **ele_src = (BMElem **)slot_src->data.buf; + BMElem **ele_dst = (BMElem **)slot_dst->data.buf; + for (i = 0; i < tot; i++, ele_src++) { + if ((*ele_src)->head.htype & dst_elem_flag) { + *ele_dst = *ele_src; + ele_dst++; + } + } + } + } + } + } + else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) { + GHashIterator gh_iter; + GHASH_ITER (gh_iter, slot_src->data.ghash) { + void *key = BLI_ghashIterator_getKey(&gh_iter); + void *val = BLI_ghashIterator_getValue(&gh_iter); + BLI_ghash_insert(slot_dst->data.ghash, key, val); + } + } + else { + slot_dst->data = slot_src->data; + } } /* @@ -372,185 +375,194 @@ void _bmo_slot_copy( void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); - if (!(slot->slot_type == BMO_OP_SLOT_FLT)) { - return; - } + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); + if (!(slot->slot_type == BMO_OP_SLOT_FLT)) { + return; + } - slot->data.f = f; + slot->data.f = f; } void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); - if (!(slot->slot_type == BMO_OP_SLOT_INT)) { - return; - } + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); + if (!(slot->slot_type == BMO_OP_SLOT_INT)) { + return; + } - slot->data.i = i; + slot->data.i = i; } void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); - if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) { - return; - } + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); + if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) { + return; + } - slot->data.i = i; + slot->data.i = i; } /* only supports square mats */ -void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size) -{ - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); - if (!(slot->slot_type == BMO_OP_SLOT_MAT)) { - return; - } - - slot->len = 4; - slot->data.p = BLI_memarena_alloc(op->arena, sizeof(float) * 4 * 4); - - if (size == 4) { - copy_m4_m4(slot->data.p, (float (*)[4])mat); - } - else if (size == 3) { - copy_m4_m3(slot->data.p, (float (*)[3])mat); - } - else { - fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size); - - zero_m4(slot->data.p); - } -} - -void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]) -{ - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); - if (!(slot->slot_type == BMO_OP_SLOT_MAT)) { - return; - } - - if (slot->data.p) { - copy_m4_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); - } - else { - unit_m4(r_mat); - } -} - -void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]) -{ - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); - if (!(slot->slot_type == BMO_OP_SLOT_MAT)) { - return; - } - - if (slot->data.p) { - copy_m3_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); - } - else { - unit_m3(r_mat); - } +void BMO_slot_mat_set(BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const float *mat, + int size) +{ + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); + if (!(slot->slot_type == BMO_OP_SLOT_MAT)) { + return; + } + + slot->len = 4; + slot->data.p = BLI_memarena_alloc(op->arena, sizeof(float) * 4 * 4); + + if (size == 4) { + copy_m4_m4(slot->data.p, (float(*)[4])mat); + } + else if (size == 3) { + copy_m4_m3(slot->data.p, (float(*)[3])mat); + } + else { + fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size); + + zero_m4(slot->data.p); + } +} + +void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + float r_mat[4][4]) +{ + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); + if (!(slot->slot_type == BMO_OP_SLOT_MAT)) { + return; + } + + if (slot->data.p) { + copy_m4_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); + } + else { + unit_m4(r_mat); + } +} + +void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + float r_mat[3][3]) +{ + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); + if (!(slot->slot_type == BMO_OP_SLOT_MAT)) { + return; + } + + if (slot->data.p) { + copy_m3_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); + } + else { + unit_m3(r_mat); + } } void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); - if (!(slot->slot_type == BMO_OP_SLOT_PTR)) { - return; - } + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); + if (!(slot->slot_type == BMO_OP_SLOT_PTR)) { + return; + } - slot->data.p = p; + slot->data.p = p; } -void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]) +void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const float vec[3]) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); - if (!(slot->slot_type == BMO_OP_SLOT_VEC)) { - return; - } + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); + if (!(slot->slot_type == BMO_OP_SLOT_VEC)) { + return; + } - copy_v3_v3(slot->data.vec, vec); + copy_v3_v3(slot->data.vec, vec); } - float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); - if (!(slot->slot_type == BMO_OP_SLOT_FLT)) { - return 0.0f; - } + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); + if (!(slot->slot_type == BMO_OP_SLOT_FLT)) { + return 0.0f; + } - return slot->data.f; + return slot->data.f; } int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); - if (!(slot->slot_type == BMO_OP_SLOT_INT)) { - return 0; - } + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); + if (!(slot->slot_type == BMO_OP_SLOT_INT)) { + return 0; + } - return slot->data.i; + return slot->data.i; } bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); - if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) { - return 0; - } + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); + if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) { + return 0; + } - return slot->data.i; + return slot->data.i; } /* if you want a copy of the elem buffer */ void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - void **ret; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + void **ret; - /* could add support for mapping type */ - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + /* could add support for mapping type */ + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - ret = MEM_mallocN(sizeof(void *) * slot->len, __func__); - memcpy(ret, slot->data.buf, sizeof(void *) * slot->len); - *len = slot->len; - return ret; + ret = MEM_mallocN(sizeof(void *) * slot->len, __func__); + memcpy(ret, slot->data.buf, sizeof(void *) * slot->len); + *len = slot->len; + return ret; } void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); - if (!(slot->slot_type == BMO_OP_SLOT_PTR)) { - return NULL; - } + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); + if (!(slot->slot_type == BMO_OP_SLOT_PTR)) { + return NULL; + } - return slot->data.p; + return slot->data.p; } void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); - if (!(slot->slot_type == BMO_OP_SLOT_VEC)) { - return; - } + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); + if (!(slot->slot_type == BMO_OP_SLOT_VEC)) { + return; + } - copy_v3_v3(r_vec, slot->data.vec); + copy_v3_v3(r_vec, slot->data.vec); } /* @@ -560,234 +572,242 @@ void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam * specific flag enabled (or disabled if test_for_enabled is false). */ -static int bmo_mesh_flag_count( - BMesh *bm, const char htype, const short oflag, - const bool test_for_enabled) -{ - int count_vert = 0, count_edge = 0, count_face = 0; - - if (htype & BM_VERT) { - BMIter iter; - BMVert *ele; - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - if (BMO_vert_flag_test_bool(bm, ele, oflag) == test_for_enabled) { - count_vert++; - } - } - } - if (htype & BM_EDGE) { - BMIter iter; - BMEdge *ele; - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - if (BMO_edge_flag_test_bool(bm, ele, oflag) == test_for_enabled) { - count_edge++; - } - } - } - if (htype & BM_FACE) { - BMIter iter; - BMFace *ele; - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - if (BMO_face_flag_test_bool(bm, ele, oflag) == test_for_enabled) { - count_face++; - } - } - } - - return (count_vert + count_edge + count_face); +static int bmo_mesh_flag_count(BMesh *bm, + const char htype, + const short oflag, + const bool test_for_enabled) +{ + int count_vert = 0, count_edge = 0, count_face = 0; + + if (htype & BM_VERT) { + BMIter iter; + BMVert *ele; + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + if (BMO_vert_flag_test_bool(bm, ele, oflag) == test_for_enabled) { + count_vert++; + } + } + } + if (htype & BM_EDGE) { + BMIter iter; + BMEdge *ele; + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + if (BMO_edge_flag_test_bool(bm, ele, oflag) == test_for_enabled) { + count_edge++; + } + } + } + if (htype & BM_FACE) { + BMIter iter; + BMFace *ele; + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + if (BMO_face_flag_test_bool(bm, ele, oflag) == test_for_enabled) { + count_face++; + } + } + } + + return (count_vert + count_edge + count_face); } - int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag) { - return bmo_mesh_flag_count(bm, htype, oflag, true); + return bmo_mesh_flag_count(bm, htype, oflag, true); } int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag) { - return bmo_mesh_flag_count(bm, htype, oflag, false); -} - -void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char htype, const short oflag) -{ - if (htype & BM_VERT) { - BMIter iter; - BMVert *ele; - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - BMO_vert_flag_disable(bm, ele, oflag); - } - } - if (htype & BM_EDGE) { - BMIter iter; - BMEdge *ele; - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - BMO_edge_flag_disable(bm, ele, oflag); - } - } - if (htype & BM_FACE) { - BMIter iter; - BMFace *ele; - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - BMO_face_flag_disable(bm, ele, oflag); - } - } -} - -void BMO_mesh_selected_remap( - BMesh *bm, - BMOpSlot *slot_vert_map, - BMOpSlot *slot_edge_map, - BMOpSlot *slot_face_map, - const bool check_select) -{ - if (bm->selected.first) { - BMEditSelection *ese, *ese_next; - BMOpSlot *slot_elem_map; - - for (ese = bm->selected.first; ese; ese = ese_next) { - ese_next = ese->next; - - switch (ese->htype) { - case BM_VERT: slot_elem_map = slot_vert_map; break; - case BM_EDGE: slot_elem_map = slot_edge_map; break; - default: slot_elem_map = slot_face_map; break; - } - - ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele); - - if (UNLIKELY((ese->ele == NULL) || - (check_select && (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false)))) - { - BLI_remlink(&bm->selected, ese); - MEM_freeN(ese); - } - } - } - - if (bm->act_face) { - BMFace *f = BMO_slot_map_elem_get(slot_face_map, bm->act_face); - if (f) { - bm->act_face = f; - } - } + return bmo_mesh_flag_count(bm, htype, oflag, false); +} + +void BMO_mesh_flag_disable_all(BMesh *bm, + BMOperator *UNUSED(op), + const char htype, + const short oflag) +{ + if (htype & BM_VERT) { + BMIter iter; + BMVert *ele; + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + BMO_vert_flag_disable(bm, ele, oflag); + } + } + if (htype & BM_EDGE) { + BMIter iter; + BMEdge *ele; + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + BMO_edge_flag_disable(bm, ele, oflag); + } + } + if (htype & BM_FACE) { + BMIter iter; + BMFace *ele; + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + BMO_face_flag_disable(bm, ele, oflag); + } + } +} + +void BMO_mesh_selected_remap(BMesh *bm, + BMOpSlot *slot_vert_map, + BMOpSlot *slot_edge_map, + BMOpSlot *slot_face_map, + const bool check_select) +{ + if (bm->selected.first) { + BMEditSelection *ese, *ese_next; + BMOpSlot *slot_elem_map; + + for (ese = bm->selected.first; ese; ese = ese_next) { + ese_next = ese->next; + + switch (ese->htype) { + case BM_VERT: + slot_elem_map = slot_vert_map; + break; + case BM_EDGE: + slot_elem_map = slot_edge_map; + break; + default: + slot_elem_map = slot_face_map; + break; + } + + ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele); + + if (UNLIKELY((ese->ele == NULL) || + (check_select && (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false)))) { + BLI_remlink(&bm->selected, ese); + MEM_freeN(ese); + } + } + } + + if (bm->act_face) { + BMFace *f = BMO_slot_map_elem_get(slot_face_map, bm->act_face); + if (f) { + bm->act_face = f; + } + } } - int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - /* check if its actually a buffer */ - if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) { - return 0; - } + /* check if its actually a buffer */ + if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) { + return 0; + } - return slot->len; + return slot->len; } int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); - return BLI_ghash_len(slot->data.ghash); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); + return BLI_ghash_len(slot->data.ghash); } /* inserts a key/value mapping into a mapping slot. note that it copies the * value, it doesn't store a reference to it. */ -void BMO_slot_map_insert( - BMOperator *op, BMOpSlot *slot, - const void *element, const void *data) +void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, const void *element, const void *data) { - (void) op; /* Ignored in release builds. */ + (void)op; /* Ignored in release builds. */ - BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); - BMO_ASSERT_SLOT_IN_OP(slot, op); + BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); + BMO_ASSERT_SLOT_IN_OP(slot, op); - BLI_ghash_insert(slot->data.ghash, (void *)element, (void *)data); + BLI_ghash_insert(slot->data.ghash, (void *)element, (void *)data); } #if 0 void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) { - BMOpSlot *slot = &op->slots[slot_code]; - void *tmp; - ssize_t allocsize; + BMOpSlot *slot = &op->slots[slot_code]; + void *tmp; + ssize_t allocsize; - BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF); - /* check if its actually a buffer */ - if (slot->slottype != BMO_OP_SLOT_ELEMENT_BUF) - return NULL; + /* check if its actually a buffer */ + if (slot->slottype != BMO_OP_SLOT_ELEMENT_BUF) + return NULL; - if (slot->flag & BMOS_DYNAMIC_ARRAY) { - if (slot->len >= slot->size) { - slot->size = (slot->size + 1 + totadd) * 2; + if (slot->flag & BMOS_DYNAMIC_ARRAY) { + if (slot->len >= slot->size) { + slot->size = (slot->size + 1 + totadd) * 2; - allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->size; + allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->size; - tmp = slot->data.buf; - slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array"); - memcpy(slot->data.buf, tmp, allocsize); - MEM_freeN(tmp); - } + tmp = slot->data.buf; + slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array"); + memcpy(slot->data.buf, tmp, allocsize); + MEM_freeN(tmp); + } - slot->len += totadd; - } - else { - slot->flag |= BMOS_DYNAMIC_ARRAY; - slot->len += totadd; - slot->size = slot->len + 2; + slot->len += totadd; + } + else { + slot->flag |= BMOS_DYNAMIC_ARRAY; + slot->len += totadd; + slot->size = slot->len + 2; - allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->len; + allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->len; - tmp = slot->data.buf; - slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array"); - memcpy(slot->data.buf, tmp, allocsize); - } + tmp = slot->data.buf; + slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array"); + memcpy(slot->data.buf, tmp, allocsize); + } - return slot->data.buf; + return slot->data.buf; } #endif -void BMO_slot_map_to_flag( - BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag) +void BMO_slot_map_to_flag(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const short oflag) { - GHashIterator gh_iter; - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BMElemF *ele_f; - - BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); + GHashIterator gh_iter; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMElemF *ele_f; + BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); - GHASH_ITER (gh_iter, slot->data.ghash) { - ele_f = BLI_ghashIterator_getKey(&gh_iter); - if (ele_f->head.htype & htype) { - BMO_elem_flag_enable(bm, ele_f, oflag); - } - } + GHASH_ITER (gh_iter, slot->data.ghash) { + ele_f = BLI_ghashIterator_getKey(&gh_iter); + if (ele_f->head.htype & htype) { + BMO_elem_flag_enable(bm, ele_f, oflag); + } + } } -void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int len) +void *BMO_slot_buffer_alloc(BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const int len) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - /* check if its actually a buffer */ - if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) { - return NULL; - } + /* check if its actually a buffer */ + if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) { + return NULL; + } - slot->len = len; - if (len) { - slot->data.buf = BLI_memarena_alloc(op->arena, BMO_OPSLOT_TYPEINFO[slot->slot_type] * len); - } - else { - slot->data.buf = NULL; - } + slot->len = len; + if (len) { + slot->data.buf = BLI_memarena_alloc(op->arena, BMO_OPSLOT_TYPEINFO[slot->slot_type] * len); + } + else { + slot->data.buf = NULL; + } - return slot->data.buf; + return slot->data.buf; } /** @@ -795,49 +815,57 @@ void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS] * * Copies all elements of a certain type into an operator slot. */ -void BMO_slot_buffer_from_all( - BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - const char *slot_name, const char htype) -{ - BMOpSlot *output = BMO_slot_get(slot_args, slot_name); - int totelement = 0, i = 0; - - BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); - - if (htype & BM_VERT) { totelement += bm->totvert; } - if (htype & BM_EDGE) { totelement += bm->totedge; } - if (htype & BM_FACE) { totelement += bm->totface; } - - if (totelement) { - BMIter iter; - BMHeader *ele; - - BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); - - /* TODO - collapse these loops into one */ - - if (htype & BM_VERT) { - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - output->data.buf[i] = ele; - i++; - } - } - - if (htype & BM_EDGE) { - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - output->data.buf[i] = ele; - i++; - } - } - - if (htype & BM_FACE) { - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - output->data.buf[i] = ele; - i++; - } - } - } +void BMO_slot_buffer_from_all(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype) +{ + BMOpSlot *output = BMO_slot_get(slot_args, slot_name); + int totelement = 0, i = 0; + + BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); + + if (htype & BM_VERT) { + totelement += bm->totvert; + } + if (htype & BM_EDGE) { + totelement += bm->totedge; + } + if (htype & BM_FACE) { + totelement += bm->totface; + } + + if (totelement) { + BMIter iter; + BMHeader *ele; + + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); + + /* TODO - collapse these loops into one */ + + if (htype & BM_VERT) { + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + output->data.buf[i] = ele; + i++; + } + } + + if (htype & BM_EDGE) { + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + output->data.buf[i] = ele; + i++; + } + } + + if (htype & BM_FACE) { + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + output->data.buf[i] = ele; + i++; + } + } + } } /** @@ -846,159 +874,166 @@ void BMO_slot_buffer_from_all( * Copies elements of a certain type, which have a certain header flag * enabled/disabled into a slot for an operator. */ -static void bmo_slot_buffer_from_hflag( - BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, - const bool test_for_enabled) -{ - BMOpSlot *output = BMO_slot_get(slot_args, slot_name); - int totelement = 0, i = 0; - const bool respecthide = ((op->flag & BMO_FLAG_RESPECT_HIDE) != 0) && ((hflag & BM_ELEM_HIDDEN) == 0); - - BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); - BLI_assert((output->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0); - - if (test_for_enabled) { - totelement = BM_mesh_elem_hflag_count_enabled(bm, htype, hflag, respecthide); - } - else { - totelement = BM_mesh_elem_hflag_count_disabled(bm, htype, hflag, respecthide); - } - - if (totelement) { - BMIter iter; - BMElem *ele; - - BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); - - /* TODO - collapse these loops into one */ - - if (htype & BM_VERT) { - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && - BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) - { - output->data.buf[i] = ele; - i++; - } - } - } - - if (htype & BM_EDGE) { - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && - BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) - { - output->data.buf[i] = ele; - i++; - } - } - } - - if (htype & BM_FACE) { - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && - BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) - { - output->data.buf[i] = ele; - i++; - } - } - } - } - else { - output->len = 0; - } -} - -void BMO_slot_buffer_from_enabled_hflag( - BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag) -{ - bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, true); -} - -void BMO_slot_buffer_from_disabled_hflag( - BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag) -{ - bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false); +static void bmo_slot_buffer_from_hflag(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const char hflag, + const bool test_for_enabled) +{ + BMOpSlot *output = BMO_slot_get(slot_args, slot_name); + int totelement = 0, i = 0; + const bool respecthide = ((op->flag & BMO_FLAG_RESPECT_HIDE) != 0) && + ((hflag & BM_ELEM_HIDDEN) == 0); + + BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); + BLI_assert((output->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0); + + if (test_for_enabled) { + totelement = BM_mesh_elem_hflag_count_enabled(bm, htype, hflag, respecthide); + } + else { + totelement = BM_mesh_elem_hflag_count_disabled(bm, htype, hflag, respecthide); + } + + if (totelement) { + BMIter iter; + BMElem *ele; + + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); + + /* TODO - collapse these loops into one */ + + if (htype & BM_VERT) { + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && + BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { + output->data.buf[i] = ele; + i++; + } + } + } + + if (htype & BM_EDGE) { + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && + BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { + output->data.buf[i] = ele; + i++; + } + } + } + + if (htype & BM_FACE) { + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && + BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { + output->data.buf[i] = ele; + i++; + } + } + } + } + else { + output->len = 0; + } +} + +void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const char hflag) +{ + bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, true); +} + +void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const char hflag) +{ + bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false); } void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele) { - BMO_ASSERT_SLOT_IN_OP(slot, op); - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE); - BLI_assert(slot->len == 0 || slot->len == 1); + BMO_ASSERT_SLOT_IN_OP(slot, op); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE); + BLI_assert(slot->len == 0 || slot->len == 1); - BLI_assert(slot->slot_subtype.elem & ele->htype); + BLI_assert(slot->slot_subtype.elem & ele->htype); - slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); /* XXX, why 'x4' ? */ - slot->len = 1; - *slot->data.buf = ele; + slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); /* XXX, why 'x4' ? */ + slot->len = 1; + *slot->data.buf = ele; } -void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len) +void BMO_slot_buffer_from_array(BMOperator *op, + BMOpSlot *slot, + BMHeader **ele_buffer, + int ele_buffer_len) { - BMO_ASSERT_SLOT_IN_OP(slot, op); - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - BLI_assert(slot->len == 0 || slot->len == ele_buffer_len); + BMO_ASSERT_SLOT_IN_OP(slot, op); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot->len == 0 || slot->len == ele_buffer_len); - if (slot->data.buf == NULL) { - slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(*slot->data.buf) * ele_buffer_len); - } + if (slot->data.buf == NULL) { + slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(*slot->data.buf) * ele_buffer_len); + } - slot->len = ele_buffer_len; - memcpy(slot->data.buf, ele_buffer, ele_buffer_len * sizeof(*slot->data.buf)); + slot->len = ele_buffer_len; + memcpy(slot->data.buf, ele_buffer, ele_buffer_len * sizeof(*slot->data.buf)); } - void *BMO_slot_buffer_get_single(BMOpSlot *slot) { - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE); - BLI_assert(slot->len == 0 || slot->len == 1); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE); + BLI_assert(slot->len == 0 || slot->len == 1); - return slot->len ? (BMHeader *)slot->data.buf[0] : NULL; + return slot->len ? (BMHeader *)slot->data.buf[0] : NULL; } /** * Copies the values from another slot to the end of the output slot. */ -void _bmo_slot_buffer_append( - BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, - BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, - struct MemArena *arena_dst) -{ - BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); - BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); - - BLI_assert(slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF && - slot_src->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - - if (slot_dst->len == 0) { - /* output slot is empty, copy rather than append */ - _bmo_slot_copy(slot_args_src, slot_name_src, - slot_args_dst, slot_name_dst, - arena_dst); - } - else if (slot_src->len != 0) { - int elem_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type]; - int alloc_size = elem_size * (slot_dst->len + slot_src->len); - /* allocate new buffer */ - void *buf = BLI_memarena_alloc(arena_dst, alloc_size); - - /* copy slot data */ - memcpy(buf, slot_dst->data.buf, elem_size * slot_dst->len); - memcpy(((char *)buf) + elem_size * slot_dst->len, slot_src->data.buf, elem_size * slot_src->len); - - slot_dst->data.buf = buf; - slot_dst->len += slot_src->len; - } +void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], + const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], + const char *slot_name_src, + struct MemArena *arena_dst) +{ + BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); + BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); + + BLI_assert(slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF && + slot_src->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + + if (slot_dst->len == 0) { + /* output slot is empty, copy rather than append */ + _bmo_slot_copy(slot_args_src, slot_name_src, slot_args_dst, slot_name_dst, arena_dst); + } + else if (slot_src->len != 0) { + int elem_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type]; + int alloc_size = elem_size * (slot_dst->len + slot_src->len); + /* allocate new buffer */ + void *buf = BLI_memarena_alloc(arena_dst, alloc_size); + + /* copy slot data */ + memcpy(buf, slot_dst->data.buf, elem_size * slot_dst->len); + memcpy( + ((char *)buf) + elem_size * slot_dst->len, slot_src->data.buf, elem_size * slot_src->len); + + slot_dst->data.buf = buf; + slot_dst->len += slot_src->len; + } } /** @@ -1007,85 +1042,91 @@ void _bmo_slot_buffer_append( * Copies elements of a certain type, which have a certain flag set * into an output slot for an operator. */ -static void bmo_slot_buffer_from_flag( - BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag, - const bool test_for_enabled) -{ - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - int totelement, i = 0; - - BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args); - - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); - BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0); - - if (test_for_enabled) { - totelement = BMO_mesh_enabled_flag_count(bm, htype, oflag); - } - else { - totelement = BMO_mesh_disabled_flag_count(bm, htype, oflag); - } - - if (totelement) { - BMIter iter; - BMHeader *ele; - BMHeader **ele_array; - - BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); - - ele_array = (BMHeader **)slot->data.buf; - - /* TODO - collapse these loops into one */ - - if (htype & BM_VERT) { - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - if (BMO_vert_flag_test_bool(bm, (BMVert *)ele, oflag) == test_for_enabled) { - ele_array[i] = ele; - i++; - } - } - } - - if (htype & BM_EDGE) { - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - if (BMO_edge_flag_test_bool(bm, (BMEdge *)ele, oflag) == test_for_enabled) { - ele_array[i] = ele; - i++; - } - } - } - - if (htype & BM_FACE) { - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - if (BMO_face_flag_test_bool(bm, (BMFace *)ele, oflag) == test_for_enabled) { - ele_array[i] = ele; - i++; - } - } - } - } - else { - slot->len = 0; - } -} - -void BMO_slot_buffer_from_enabled_flag( - BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag) -{ - bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, true); -} - -void BMO_slot_buffer_from_disabled_flag( - BMesh *bm, BMOperator *op, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag) -{ - bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false); +static void bmo_slot_buffer_from_flag(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const short oflag, + const bool test_for_enabled) +{ + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + int totelement, i = 0; + + BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args); + + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); + BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0); + + if (test_for_enabled) { + totelement = BMO_mesh_enabled_flag_count(bm, htype, oflag); + } + else { + totelement = BMO_mesh_disabled_flag_count(bm, htype, oflag); + } + + if (totelement) { + BMIter iter; + BMHeader *ele; + BMHeader **ele_array; + + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); + + ele_array = (BMHeader **)slot->data.buf; + + /* TODO - collapse these loops into one */ + + if (htype & BM_VERT) { + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + if (BMO_vert_flag_test_bool(bm, (BMVert *)ele, oflag) == test_for_enabled) { + ele_array[i] = ele; + i++; + } + } + } + + if (htype & BM_EDGE) { + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + if (BMO_edge_flag_test_bool(bm, (BMEdge *)ele, oflag) == test_for_enabled) { + ele_array[i] = ele; + i++; + } + } + } + + if (htype & BM_FACE) { + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + if (BMO_face_flag_test_bool(bm, (BMFace *)ele, oflag) == test_for_enabled) { + ele_array[i] = ele; + i++; + } + } + } + } + else { + slot->len = 0; + } +} + +void BMO_slot_buffer_from_enabled_flag(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const short oflag) +{ + bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, true); +} + +void BMO_slot_buffer_from_disabled_flag(BMesh *bm, + BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const short oflag) +{ + bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false); } /** @@ -1094,36 +1135,38 @@ void BMO_slot_buffer_from_disabled_flag( * Header Flags elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_enable( - BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const bool do_flush) +void BMO_slot_buffer_hflag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const char hflag, + const bool do_flush) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BMElem **data = (BMElem **)slot->data.buf; - int i; - const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); - const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMElem **data = (BMElem **)slot->data.buf; + int i; + const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); + const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); - BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); + BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0); - for (i = 0; i < slot->len; i++, data++) { - if (!(htype & (*data)->head.htype)) { - continue; - } + for (i = 0; i < slot->len; i++, data++) { + if (!(htype & (*data)->head.htype)) { + continue; + } - if (do_flush_select) { - BM_elem_select_set(bm, *data, true); - } + if (do_flush_select) { + BM_elem_select_set(bm, *data, true); + } - if (do_flush_hide) { - BM_elem_hide_set(bm, *data, false); - } + if (do_flush_hide) { + BM_elem_hide_set(bm, *data, false); + } - BM_elem_flag_enable(*data, hflag); - } + BM_elem_flag_enable(*data, hflag); + } } /** @@ -1132,35 +1175,37 @@ void BMO_slot_buffer_hflag_enable( * Removes flags from elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_disable( - BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const bool do_flush) +void BMO_slot_buffer_hflag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const char hflag, + const bool do_flush) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BMElem **data = (BMElem **)slot->data.buf; - int i; - const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); - const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMElem **data = (BMElem **)slot->data.buf; + int i; + const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); + const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); - for (i = 0; i < slot->len; i++, data++) { - if (!(htype & (*data)->head.htype)) { - continue; - } + for (i = 0; i < slot->len; i++, data++) { + if (!(htype & (*data)->head.htype)) { + continue; + } - if (do_flush_select) { - BM_elem_select_set(bm, *data, false); - } + if (do_flush_select) { + BM_elem_select_set(bm, *data, false); + } - if (do_flush_hide) { - BM_elem_hide_set(bm, *data, false); - } + if (do_flush_hide) { + BM_elem_hide_set(bm, *data, false); + } - BM_elem_flag_disable(*data, hflag); - } + BM_elem_flag_disable(*data, hflag); + } } /** @@ -1168,25 +1213,26 @@ void BMO_slot_buffer_hflag_disable( * * Flags elements in a slots buffer */ -void BMO_slot_buffer_flag_enable( - BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag) +void BMO_slot_buffer_flag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const short oflag) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BMHeader **data = slot->data.p; - int i; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMHeader **data = slot->data.p; + int i; - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); - for (i = 0; i < slot->len; i++) { - if (!(htype & data[i]->htype)) { - continue; - } + for (i = 0; i < slot->len; i++) { + if (!(htype & data[i]->htype)) { + continue; + } - BMO_elem_flag_enable(bm, (BMElemF *)data[i], oflag); - } + BMO_elem_flag_enable(bm, (BMElemF *)data[i], oflag); + } } /** @@ -1194,28 +1240,28 @@ void BMO_slot_buffer_flag_enable( * * Removes flags from elements in a slots buffer */ -void BMO_slot_buffer_flag_disable( - BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag) +void BMO_slot_buffer_flag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char htype, + const short oflag) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - BMHeader **data = (BMHeader **)slot->data.buf; - int i; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMHeader **data = (BMHeader **)slot->data.buf; + int i; - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); - for (i = 0; i < slot->len; i++) { - if (!(htype & data[i]->htype)) { - continue; - } + for (i = 0; i < slot->len; i++) { + if (!(htype & data[i]->htype)) { + continue; + } - BMO_elem_flag_disable(bm, (BMElemF *)data[i], oflag); - } + BMO_elem_flag_disable(bm, (BMElemF *)data[i], oflag); + } } - /** * \brief ALLOC/FREE FLAG LAYER * @@ -1231,172 +1277,175 @@ void BMO_slot_buffer_flag_disable( */ static void bmo_flag_layer_alloc(BMesh *bm) { - /* set the index values since we are looping over all data anyway, - * may save time later on */ - - BLI_mempool *voldpool = bm->vtoolflagpool; /* old flag pool */ - BLI_mempool *eoldpool = bm->etoolflagpool; /* old flag pool */ - BLI_mempool *foldpool = bm->ftoolflagpool; /* old flag pool */ - - /* store memcpy size for reuse */ - const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer)); - - bm->totflags++; - - bm->vtoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, bm->totvert, 512, BLI_MEMPOOL_NOP); - bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, bm->totedge, 512, BLI_MEMPOOL_NOP); - bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, bm->totface, 512, BLI_MEMPOOL_NOP); - - /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */ - BMIter iter; - int i; - - BMVert_OFlag *v_oflag; - BLI_mempool *newpool = bm->vtoolflagpool; - BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) { - void *oldflags = v_oflag->oflags; - v_oflag->oflags = BLI_mempool_calloc(newpool); - memcpy(v_oflag->oflags, oldflags, old_totflags_size); - BM_elem_index_set(&v_oflag->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag); - } - - BMEdge_OFlag *e_oflag; - newpool = bm->etoolflagpool; - BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) { - void *oldflags = e_oflag->oflags; - e_oflag->oflags = BLI_mempool_calloc(newpool); - memcpy(e_oflag->oflags, oldflags, old_totflags_size); - BM_elem_index_set(&e_oflag->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag); - } - - BMFace_OFlag *f_oflag; - newpool = bm->ftoolflagpool; - BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) { - void *oldflags = f_oflag->oflags; - f_oflag->oflags = BLI_mempool_calloc(newpool); - memcpy(f_oflag->oflags, oldflags, old_totflags_size); - BM_elem_index_set(&f_oflag->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag); - } - - BLI_mempool_destroy(voldpool); - BLI_mempool_destroy(eoldpool); - BLI_mempool_destroy(foldpool); - - bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); + /* set the index values since we are looping over all data anyway, + * may save time later on */ + + BLI_mempool *voldpool = bm->vtoolflagpool; /* old flag pool */ + BLI_mempool *eoldpool = bm->etoolflagpool; /* old flag pool */ + BLI_mempool *foldpool = bm->ftoolflagpool; /* old flag pool */ + + /* store memcpy size for reuse */ + const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer)); + + bm->totflags++; + + bm->vtoolflagpool = BLI_mempool_create( + sizeof(BMFlagLayer) * bm->totflags, bm->totvert, 512, BLI_MEMPOOL_NOP); + bm->etoolflagpool = BLI_mempool_create( + sizeof(BMFlagLayer) * bm->totflags, bm->totedge, 512, BLI_MEMPOOL_NOP); + bm->ftoolflagpool = BLI_mempool_create( + sizeof(BMFlagLayer) * bm->totflags, bm->totface, 512, BLI_MEMPOOL_NOP); + + /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */ + BMIter iter; + int i; + + BMVert_OFlag *v_oflag; + BLI_mempool *newpool = bm->vtoolflagpool; + BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) { + void *oldflags = v_oflag->oflags; + v_oflag->oflags = BLI_mempool_calloc(newpool); + memcpy(v_oflag->oflags, oldflags, old_totflags_size); + BM_elem_index_set(&v_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag); + } + + BMEdge_OFlag *e_oflag; + newpool = bm->etoolflagpool; + BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) { + void *oldflags = e_oflag->oflags; + e_oflag->oflags = BLI_mempool_calloc(newpool); + memcpy(e_oflag->oflags, oldflags, old_totflags_size); + BM_elem_index_set(&e_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag); + } + + BMFace_OFlag *f_oflag; + newpool = bm->ftoolflagpool; + BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) { + void *oldflags = f_oflag->oflags; + f_oflag->oflags = BLI_mempool_calloc(newpool); + memcpy(f_oflag->oflags, oldflags, old_totflags_size); + BM_elem_index_set(&f_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag); + } + + BLI_mempool_destroy(voldpool); + BLI_mempool_destroy(eoldpool); + BLI_mempool_destroy(foldpool); + + bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); } static void bmo_flag_layer_free(BMesh *bm) { - /* set the index values since we are looping over all data anyway, - * may save time later on */ - - BLI_mempool *voldpool = bm->vtoolflagpool; - BLI_mempool *eoldpool = bm->etoolflagpool; - BLI_mempool *foldpool = bm->ftoolflagpool; - - /* store memcpy size for reuse */ - const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer)); - - /* de-increment the totflags first.. */ - bm->totflags--; - - bm->vtoolflagpool = BLI_mempool_create(new_totflags_size, bm->totvert, 512, BLI_MEMPOOL_NOP); - bm->etoolflagpool = BLI_mempool_create(new_totflags_size, bm->totedge, 512, BLI_MEMPOOL_NOP); - bm->ftoolflagpool = BLI_mempool_create(new_totflags_size, bm->totface, 512, BLI_MEMPOOL_NOP); - - /* now go through and memcpy all the flag */ - BMIter iter; - int i; - - BMVert_OFlag *v_oflag; - BLI_mempool *newpool = bm->vtoolflagpool; - BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) { - void *oldflags = v_oflag->oflags; - v_oflag->oflags = BLI_mempool_alloc(newpool); - memcpy(v_oflag->oflags, oldflags, new_totflags_size); - BM_elem_index_set(&v_oflag->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag); - } - - BMEdge_OFlag *e_oflag; - newpool = bm->etoolflagpool; - BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) { - void *oldflags = e_oflag->oflags; - e_oflag->oflags = BLI_mempool_alloc(newpool); - memcpy(e_oflag->oflags, oldflags, new_totflags_size); - BM_elem_index_set(&e_oflag->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag); - } - - BMFace_OFlag *f_oflag; - newpool = bm->ftoolflagpool; - BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) { - void *oldflags = f_oflag->oflags; - f_oflag->oflags = BLI_mempool_alloc(newpool); - memcpy(f_oflag->oflags, oldflags, new_totflags_size); - BM_elem_index_set(&f_oflag->base, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag); - } - - BLI_mempool_destroy(voldpool); - BLI_mempool_destroy(eoldpool); - BLI_mempool_destroy(foldpool); - - bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); + /* set the index values since we are looping over all data anyway, + * may save time later on */ + + BLI_mempool *voldpool = bm->vtoolflagpool; + BLI_mempool *eoldpool = bm->etoolflagpool; + BLI_mempool *foldpool = bm->ftoolflagpool; + + /* store memcpy size for reuse */ + const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer)); + + /* de-increment the totflags first.. */ + bm->totflags--; + + bm->vtoolflagpool = BLI_mempool_create(new_totflags_size, bm->totvert, 512, BLI_MEMPOOL_NOP); + bm->etoolflagpool = BLI_mempool_create(new_totflags_size, bm->totedge, 512, BLI_MEMPOOL_NOP); + bm->ftoolflagpool = BLI_mempool_create(new_totflags_size, bm->totface, 512, BLI_MEMPOOL_NOP); + + /* now go through and memcpy all the flag */ + BMIter iter; + int i; + + BMVert_OFlag *v_oflag; + BLI_mempool *newpool = bm->vtoolflagpool; + BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) { + void *oldflags = v_oflag->oflags; + v_oflag->oflags = BLI_mempool_alloc(newpool); + memcpy(v_oflag->oflags, oldflags, new_totflags_size); + BM_elem_index_set(&v_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag); + } + + BMEdge_OFlag *e_oflag; + newpool = bm->etoolflagpool; + BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) { + void *oldflags = e_oflag->oflags; + e_oflag->oflags = BLI_mempool_alloc(newpool); + memcpy(e_oflag->oflags, oldflags, new_totflags_size); + BM_elem_index_set(&e_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag); + } + + BMFace_OFlag *f_oflag; + newpool = bm->ftoolflagpool; + BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) { + void *oldflags = f_oflag->oflags; + f_oflag->oflags = BLI_mempool_alloc(newpool); + memcpy(f_oflag->oflags, oldflags, new_totflags_size); + BM_elem_index_set(&f_oflag->base, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag); + } + + BLI_mempool_destroy(voldpool); + BLI_mempool_destroy(eoldpool); + BLI_mempool_destroy(foldpool); + + bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); } static void bmo_flag_layer_clear(BMesh *bm) { - /* set the index values since we are looping over all data anyway, - * may save time later on */ - const BMFlagLayer zero_flag = {0}; - - const int totflags_offset = bm->totflags - 1; - - /* now go through and memcpy all the flag */ - { - BMIter iter; - BMVert_OFlag *ele; - int i; - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { - ele->oflags[totflags_offset] = zero_flag; - BM_elem_index_set(&ele->base, i); /* set_inline */ - } - } - { - BMIter iter; - BMEdge_OFlag *ele; - int i; - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { - ele->oflags[totflags_offset] = zero_flag; - BM_elem_index_set(&ele->base, i); /* set_inline */ - } - } - { - BMIter iter; - BMFace_OFlag *ele; - int i; - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { - ele->oflags[totflags_offset] = zero_flag; - BM_elem_index_set(&ele->base, i); /* set_inline */ - } - } - - bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); + /* set the index values since we are looping over all data anyway, + * may save time later on */ + const BMFlagLayer zero_flag = {0}; + + const int totflags_offset = bm->totflags - 1; + + /* now go through and memcpy all the flag */ + { + BMIter iter; + BMVert_OFlag *ele; + int i; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { + ele->oflags[totflags_offset] = zero_flag; + BM_elem_index_set(&ele->base, i); /* set_inline */ + } + } + { + BMIter iter; + BMEdge_OFlag *ele; + int i; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { + ele->oflags[totflags_offset] = zero_flag; + BM_elem_index_set(&ele->base, i); /* set_inline */ + } + } + { + BMIter iter; + BMFace_OFlag *ele; + int i; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { + ele->oflags[totflags_offset] = zero_flag; + BM_elem_index_set(&ele->base, i); /* set_inline */ + } + } + + bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); } void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) { - return NULL; - } + if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) { + return NULL; + } - return slot->data.buf ? *slot->data.buf : NULL; + return slot->data.buf ? *slot->data.buf : NULL; } /** @@ -1405,78 +1454,77 @@ void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char * \param restrictmask: restricts the iteration to certain element types * (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating * over an element buffer (not a mapping). */ -void *BMO_iter_new( - BMOIter *iter, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char restrictmask) +void *BMO_iter_new(BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, + const char restrictmask) { - BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); - memset(iter, 0, sizeof(BMOIter)); + memset(iter, 0, sizeof(BMOIter)); - iter->slot = slot; - iter->cur = 0; - iter->restrictmask = restrictmask; + iter->slot = slot; + iter->cur = 0; + iter->restrictmask = restrictmask; - if (iter->slot->slot_type == BMO_OP_SLOT_MAPPING) { - BLI_ghashIterator_init(&iter->giter, slot->data.ghash); - } - else if (iter->slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { - BLI_assert(restrictmask & slot->slot_subtype.elem); - } - else { - BLI_assert(0); - } + if (iter->slot->slot_type == BMO_OP_SLOT_MAPPING) { + BLI_ghashIterator_init(&iter->giter, slot->data.ghash); + } + else if (iter->slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { + BLI_assert(restrictmask & slot->slot_subtype.elem); + } + else { + BLI_assert(0); + } - return BMO_iter_step(iter); + return BMO_iter_step(iter); } void *BMO_iter_step(BMOIter *iter) { - BMOpSlot *slot = iter->slot; - if (slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { - BMHeader *ele; + BMOpSlot *slot = iter->slot; + if (slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { + BMHeader *ele; - if (iter->cur >= slot->len) { - return NULL; - } + if (iter->cur >= slot->len) { + return NULL; + } - ele = slot->data.buf[iter->cur++]; - while (!(iter->restrictmask & ele->htype)) { - if (iter->cur >= slot->len) { - return NULL; - } + ele = slot->data.buf[iter->cur++]; + while (!(iter->restrictmask & ele->htype)) { + if (iter->cur >= slot->len) { + return NULL; + } - ele = slot->data.buf[iter->cur++]; - BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype)); - } + ele = slot->data.buf[iter->cur++]; + BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype)); + } - BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype)); + BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype)); - return ele; - } - else if (slot->slot_type == BMO_OP_SLOT_MAPPING) { - void *ret; + return ele; + } + else if (slot->slot_type == BMO_OP_SLOT_MAPPING) { + void *ret; + if (BLI_ghashIterator_done(&iter->giter) == false) { + ret = BLI_ghashIterator_getKey(&iter->giter); + iter->val = BLI_ghashIterator_getValue_p(&iter->giter); - if (BLI_ghashIterator_done(&iter->giter) == false) { - ret = BLI_ghashIterator_getKey(&iter->giter); - iter->val = BLI_ghashIterator_getValue_p(&iter->giter); + BLI_ghashIterator_step(&iter->giter); + } + else { + ret = NULL; + iter->val = NULL; + } - BLI_ghashIterator_step(&iter->giter); - } - else { - ret = NULL; - iter->val = NULL; - } + return ret; + } + else { + BLI_assert(0); + } - return ret; - } - else { - BLI_assert(0); - } - - return NULL; + return NULL; } /* used for iterating over mappings */ @@ -1487,149 +1535,154 @@ void *BMO_iter_step(BMOIter *iter) */ void **BMO_iter_map_value_p(BMOIter *iter) { - return iter->val; + return iter->val; } void *BMO_iter_map_value_ptr(BMOIter *iter) { - BLI_assert(ELEM(iter->slot->slot_subtype.map, - BMO_OP_SLOT_SUBTYPE_MAP_ELEM, BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL)); - return iter->val ? *iter->val : NULL; + BLI_assert(ELEM(iter->slot->slot_subtype.map, + BMO_OP_SLOT_SUBTYPE_MAP_ELEM, + BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL)); + return iter->val ? *iter->val : NULL; } - float BMO_iter_map_value_float(BMOIter *iter) { - BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); - return **((float **)iter->val); + BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); + return **((float **)iter->val); } int BMO_iter_map_value_int(BMOIter *iter) { - BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); - return **((int **)iter->val); + BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); + return **((int **)iter->val); } bool BMO_iter_map_value_bool(BMOIter *iter) { - BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); - return **((bool **)iter->val); + BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); + return **((bool **)iter->val); } /* error system */ typedef struct BMOpError { - struct BMOpError *next, *prev; - int errorcode; - BMOperator *op; - const char *msg; + struct BMOpError *next, *prev; + int errorcode; + BMOperator *op; + const char *msg; } BMOpError; void BMO_error_clear(BMesh *bm) { - while (BMO_error_pop(bm, NULL, NULL)) { - /* pass */ - } + while (BMO_error_pop(bm, NULL, NULL)) { + /* pass */ + } } void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg) { - BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error"); + BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error"); - err->errorcode = errcode; - if (!msg) { - msg = bmo_error_messages[errcode]; - } - err->msg = msg; - err->op = owner; + err->errorcode = errcode; + if (!msg) { + msg = bmo_error_messages[errcode]; + } + err->msg = msg; + err->op = owner; - BLI_addhead(&bm->errorstack, err); + BLI_addhead(&bm->errorstack, err); } bool BMO_error_occurred(BMesh *bm) { - return (BLI_listbase_is_empty(&bm->errorstack) == false); + return (BLI_listbase_is_empty(&bm->errorstack) == false); } /* returns error code or 0 if no error */ int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op) { - BMOpError *err = bm->errorstack.first; - if (!err) { - return 0; - } + BMOpError *err = bm->errorstack.first; + if (!err) { + return 0; + } - if (msg) { - *msg = err->msg; - } - if (op) { - *op = err->op; - } + if (msg) { + *msg = err->msg; + } + if (op) { + *op = err->op; + } - return err->errorcode; + return err->errorcode; } int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op) { - int errorcode = BMO_error_get(bm, msg, op); + int errorcode = BMO_error_get(bm, msg, op); - if (errorcode) { - BMOpError *err = bm->errorstack.first; + if (errorcode) { + BMOpError *err = bm->errorstack.first; - BLI_remlink(&bm->errorstack, bm->errorstack.first); - MEM_freeN(err); - } + BLI_remlink(&bm->errorstack, bm->errorstack.first); + MEM_freeN(err); + } - return errorcode; + return errorcode; } - #define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0) static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int i = 0; + int i = 0; - while (slot_args->slot_name) { - if (STREQLEN(identifier, slot_args->slot_name, MAX_SLOTNAME)) { - return i; - } - slot_args++; - i++; - } + while (slot_args->slot_name) { + if (STREQLEN(identifier, slot_args->slot_name, MAX_SLOTNAME)) { + return i; + } + slot_args++; + i++; + } - return -1; + return -1; } static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int i = bmo_name_to_slotcode(slot_args, identifier); - if (i < 0) { - fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, identifier); - } + int i = bmo_name_to_slotcode(slot_args, identifier); + if (i < 0) { + fprintf(stderr, + "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", + __func__, + identifier); + } - return i; + return i; } int BMO_opcode_from_opname(const char *opname) { - const uint tot = bmo_opdefines_total; - uint i; - for (i = 0; i < tot; i++) { - if (STREQ(bmo_opdefines[i]->opname, opname)) { - return i; - } - } - return -1; + const uint tot = bmo_opdefines_total; + uint i; + for (i = 0; i < tot; i++) { + if (STREQ(bmo_opdefines[i]->opname, opname)) { + return i; + } + } + return -1; } static int BMO_opcode_from_opname_check(const char *opname) { - int i = BMO_opcode_from_opname(opname); - if (i == -1) { - fprintf(stderr, "%s: could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname); - } - return i; + int i = BMO_opcode_from_opname(opname); + if (i == -1) { + fprintf(stderr, + "%s: could not find bmesh slot for name %s! (bmesh internal error)\n", + __func__, + opname); + } + return i; } /** @@ -1688,283 +1741,294 @@ static int BMO_opcode_from_opname_check(const char *opname) bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist) { -// BMOpDefine *def; - char *opname, *ofmt, *fmt; - char slot_name[64] = {0}; - int i, type; - bool noslot, state; - - - /* basic useful info to help find where bmop formatting strings fail */ - const char *err_reason = "Unknown"; - int lineno = -1; - -#define GOTO_ERROR(reason) \ - { \ - err_reason = reason; \ - lineno = __LINE__; \ - goto error; \ - } (void)0 - - /* we muck around in here, so dup it */ - fmt = ofmt = BLI_strdup(_fmt); - - /* find operator name */ - i = strcspn(fmt, " "); - - opname = fmt; - noslot = (opname[i] == '\0'); - opname[i] = '\0'; - - fmt += i + (noslot ? 0 : 1); - - i = BMO_opcode_from_opname_check(opname); - - if (i == -1) { - MEM_freeN(ofmt); - BLI_assert(0); - return false; - } - - BMO_op_init(bm, op, flag, opname); -// def = bmo_opdefines[i]; - - i = 0; - state = true; /* false: not inside slot_code name, true: inside slot_code name */ - - while (*fmt) { - if (state) { - /* jump past leading whitespace */ - i = strspn(fmt, " "); - fmt += i; - - /* ignore trailing whitespace */ - if (!fmt[i]) { - break; - } - - /* find end of slot name, only "slot=%f", can be used */ - i = strcspn(fmt, "="); - if (!fmt[i]) { - GOTO_ERROR("could not match end of slot name"); - } - - fmt[i] = 0; - - if (bmo_name_to_slotcode_check(op->slots_in, fmt) < 0) { - GOTO_ERROR("name to slot code check failed"); - } - - BLI_strncpy(slot_name, fmt, sizeof(slot_name)); - - state = false; - fmt += i; - } - else { - switch (*fmt) { - case ' ': - case '=': - case '%': - break; - case 'm': - { - int size; - const char c = NEXT_CHAR(fmt); - fmt++; - - if (c == '3') { size = 3; } - else if (c == '4') { size = 4; } - else { GOTO_ERROR("matrix size was not 3 or 4"); } - - BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size); - state = true; - break; - } - case 'v': - { - BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *)); - state = true; - break; - } - case 'e': - { - BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name); - - if (NEXT_CHAR(fmt) == 'b') { - BMHeader **ele_buffer = va_arg(vlist, void *); - int ele_buffer_len = va_arg(vlist, int); - - BMO_slot_buffer_from_array(op, slot, ele_buffer, ele_buffer_len); - fmt++; - } - else { - /* single vert/edge/face */ - BMHeader *ele = va_arg(vlist, void *); - - BMO_slot_buffer_from_single(op, slot, ele); - } - - state = true; - break; - } - case 's': - case 'S': - { - BMOperator *op_other = va_arg(vlist, void *); - const char *slot_name_other = va_arg(vlist, char *); - - if (*fmt == 's') { - BLI_assert(bmo_name_to_slotcode_check(op_other->slots_in, slot_name_other) != -1); - BMO_slot_copy(op_other, slots_in, slot_name_other, - op, slots_in, slot_name); - } - else { - BLI_assert(bmo_name_to_slotcode_check(op_other->slots_out, slot_name_other) != -1); - BMO_slot_copy(op_other, slots_out, slot_name_other, - op, slots_in, slot_name); - } - state = true; - break; - } - case 'i': - BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int)); - state = true; - break; - case 'b': - BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int)); - state = true; - break; - case 'p': - BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *)); - state = true; - break; - case 'f': - case 'F': - case 'h': - case 'H': - case 'a': - type = *fmt; - - if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') { - BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double)); - } - else { - char htype = 0; - - while (1) { - char htype_set; - const char c = NEXT_CHAR(fmt); - if (c == 'f') { htype_set = BM_FACE; } - else if (c == 'e') { htype_set = BM_EDGE; } - else if (c == 'v') { htype_set = BM_VERT; } - else { - break; - } - - if (UNLIKELY(htype & htype_set)) { - GOTO_ERROR("htype duplicated"); - } - - htype |= htype_set; - fmt++; - } - - if (type == 'h') { - BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); - } - else if (type == 'H') { - BMO_slot_buffer_from_disabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); - } - else if (type == 'a') { - if ((op->flag & BMO_FLAG_RESPECT_HIDE) == 0) { - BMO_slot_buffer_from_all(bm, op, op->slots_in, slot_name, htype); - } - else { - BMO_slot_buffer_from_disabled_hflag(bm, op, op->slots_in, slot_name, htype, BM_ELEM_HIDDEN); - } - } - else if (type == 'f') { - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); - } - else if (type == 'F') { - BMO_slot_buffer_from_disabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); - } - } - - state = true; - break; - default: - fprintf(stderr, - "%s: unrecognized bmop format char: '%c', %d in '%s'\n", - __func__, *fmt, (int)(fmt - ofmt), ofmt); - break; - } - } - fmt++; - } - - MEM_freeN(ofmt); - return true; + // BMOpDefine *def; + char *opname, *ofmt, *fmt; + char slot_name[64] = {0}; + int i, type; + bool noslot, state; + + /* basic useful info to help find where bmop formatting strings fail */ + const char *err_reason = "Unknown"; + int lineno = -1; + +#define GOTO_ERROR(reason) \ + { \ + err_reason = reason; \ + lineno = __LINE__; \ + goto error; \ + } \ + (void)0 + + /* we muck around in here, so dup it */ + fmt = ofmt = BLI_strdup(_fmt); + + /* find operator name */ + i = strcspn(fmt, " "); + + opname = fmt; + noslot = (opname[i] == '\0'); + opname[i] = '\0'; + + fmt += i + (noslot ? 0 : 1); + + i = BMO_opcode_from_opname_check(opname); + + if (i == -1) { + MEM_freeN(ofmt); + BLI_assert(0); + return false; + } + + BMO_op_init(bm, op, flag, opname); + // def = bmo_opdefines[i]; + + i = 0; + state = true; /* false: not inside slot_code name, true: inside slot_code name */ + + while (*fmt) { + if (state) { + /* jump past leading whitespace */ + i = strspn(fmt, " "); + fmt += i; + + /* ignore trailing whitespace */ + if (!fmt[i]) { + break; + } + + /* find end of slot name, only "slot=%f", can be used */ + i = strcspn(fmt, "="); + if (!fmt[i]) { + GOTO_ERROR("could not match end of slot name"); + } + + fmt[i] = 0; + + if (bmo_name_to_slotcode_check(op->slots_in, fmt) < 0) { + GOTO_ERROR("name to slot code check failed"); + } + + BLI_strncpy(slot_name, fmt, sizeof(slot_name)); + + state = false; + fmt += i; + } + else { + switch (*fmt) { + case ' ': + case '=': + case '%': + break; + case 'm': { + int size; + const char c = NEXT_CHAR(fmt); + fmt++; + + if (c == '3') { + size = 3; + } + else if (c == '4') { + size = 4; + } + else { + GOTO_ERROR("matrix size was not 3 or 4"); + } + + BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size); + state = true; + break; + } + case 'v': { + BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *)); + state = true; + break; + } + case 'e': { + BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name); + + if (NEXT_CHAR(fmt) == 'b') { + BMHeader **ele_buffer = va_arg(vlist, void *); + int ele_buffer_len = va_arg(vlist, int); + + BMO_slot_buffer_from_array(op, slot, ele_buffer, ele_buffer_len); + fmt++; + } + else { + /* single vert/edge/face */ + BMHeader *ele = va_arg(vlist, void *); + + BMO_slot_buffer_from_single(op, slot, ele); + } + + state = true; + break; + } + case 's': + case 'S': { + BMOperator *op_other = va_arg(vlist, void *); + const char *slot_name_other = va_arg(vlist, char *); + + if (*fmt == 's') { + BLI_assert(bmo_name_to_slotcode_check(op_other->slots_in, slot_name_other) != -1); + BMO_slot_copy(op_other, slots_in, slot_name_other, op, slots_in, slot_name); + } + else { + BLI_assert(bmo_name_to_slotcode_check(op_other->slots_out, slot_name_other) != -1); + BMO_slot_copy(op_other, slots_out, slot_name_other, op, slots_in, slot_name); + } + state = true; + break; + } + case 'i': + BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int)); + state = true; + break; + case 'b': + BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int)); + state = true; + break; + case 'p': + BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *)); + state = true; + break; + case 'f': + case 'F': + case 'h': + case 'H': + case 'a': + type = *fmt; + + if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') { + BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double)); + } + else { + char htype = 0; + + while (1) { + char htype_set; + const char c = NEXT_CHAR(fmt); + if (c == 'f') { + htype_set = BM_FACE; + } + else if (c == 'e') { + htype_set = BM_EDGE; + } + else if (c == 'v') { + htype_set = BM_VERT; + } + else { + break; + } + + if (UNLIKELY(htype & htype_set)) { + GOTO_ERROR("htype duplicated"); + } + + htype |= htype_set; + fmt++; + } + + if (type == 'h') { + BMO_slot_buffer_from_enabled_hflag( + bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); + } + else if (type == 'H') { + BMO_slot_buffer_from_disabled_hflag( + bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); + } + else if (type == 'a') { + if ((op->flag & BMO_FLAG_RESPECT_HIDE) == 0) { + BMO_slot_buffer_from_all(bm, op, op->slots_in, slot_name, htype); + } + else { + BMO_slot_buffer_from_disabled_hflag( + bm, op, op->slots_in, slot_name, htype, BM_ELEM_HIDDEN); + } + } + else if (type == 'f') { + BMO_slot_buffer_from_enabled_flag( + bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); + } + else if (type == 'F') { + BMO_slot_buffer_from_disabled_flag( + bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); + } + } + + state = true; + break; + default: + fprintf(stderr, + "%s: unrecognized bmop format char: '%c', %d in '%s'\n", + __func__, + *fmt, + (int)(fmt - ofmt), + ofmt); + break; + } + } + fmt++; + } + + MEM_freeN(ofmt); + return true; error: - /* non urgent todo - explain exactly what is failing */ - fprintf(stderr, "%s: error parsing formatting string\n", __func__); - - fprintf(stderr, "string: '%s', position %d\n", _fmt, (int)(fmt - ofmt)); - fprintf(stderr, " "); - { - int pos = (int)(fmt - ofmt); - for (i = 0; i < pos; i++) { - fprintf(stderr, " "); - } - fprintf(stderr, "^\n"); - } + /* non urgent todo - explain exactly what is failing */ + fprintf(stderr, "%s: error parsing formatting string\n", __func__); - fprintf(stderr, "source code: %s:%d\n", __FILE__, lineno); + fprintf(stderr, "string: '%s', position %d\n", _fmt, (int)(fmt - ofmt)); + fprintf(stderr, " "); + { + int pos = (int)(fmt - ofmt); + for (i = 0; i < pos; i++) { + fprintf(stderr, " "); + } + fprintf(stderr, "^\n"); + } - fprintf(stderr, "reason: %s\n", err_reason); + fprintf(stderr, "source code: %s:%d\n", __FILE__, lineno); + fprintf(stderr, "reason: %s\n", err_reason); - MEM_freeN(ofmt); + MEM_freeN(ofmt); - BMO_op_finish(bm, op); - return false; + BMO_op_finish(bm, op); + return false; #undef GOTO_ERROR - } - bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...) { - va_list list; + va_list list; - va_start(list, fmt); - if (!BMO_op_vinitf(bm, op, flag, fmt, list)) { - printf("%s: failed\n", __func__); - va_end(list); - return false; - } - va_end(list); + va_start(list, fmt); + if (!BMO_op_vinitf(bm, op, flag, fmt, list)) { + printf("%s: failed\n", __func__); + va_end(list); + return false; + } + va_end(list); - return true; + return true; } bool BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...) { - va_list list; - BMOperator op; + va_list list; + BMOperator op; - va_start(list, fmt); - if (!BMO_op_vinitf(bm, &op, flag, fmt, list)) { - printf("%s: failed, format is:\n \"%s\"\n", __func__, fmt); - va_end(list); - return false; - } + va_start(list, fmt); + if (!BMO_op_vinitf(bm, &op, flag, fmt, list)) { + printf("%s: failed, format is:\n \"%s\"\n", __func__, fmt); + va_end(list); + return false; + } - BMO_op_exec(bm, &op); - BMO_op_finish(bm, &op); + BMO_op_exec(bm, &op); + BMO_op_finish(bm, &op); - va_end(list); - return true; + va_end(list); + return true; } diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 6c0a6854d8e..0279e4dd23e 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -27,132 +27,143 @@ /*quad innervert values*/ enum { - SUBD_CORNER_INNERVERT, - SUBD_CORNER_PATH, - SUBD_CORNER_FAN, - SUBD_CORNER_STRAIGHT_CUT, + SUBD_CORNER_INNERVERT, + SUBD_CORNER_PATH, + SUBD_CORNER_FAN, + SUBD_CORNER_STRAIGHT_CUT, }; /* aligned with PROP_SMOOTH and friends */ enum { - SUBD_FALLOFF_SMOOTH = 0, - SUBD_FALLOFF_SPHERE, - SUBD_FALLOFF_ROOT, - SUBD_FALLOFF_SHARP, - SUBD_FALLOFF_LIN, - SUBD_FALLOFF_INVSQUARE = 7, /* matching PROP_INVSQUARE */ + SUBD_FALLOFF_SMOOTH = 0, + SUBD_FALLOFF_SPHERE, + SUBD_FALLOFF_ROOT, + SUBD_FALLOFF_SHARP, + SUBD_FALLOFF_LIN, + SUBD_FALLOFF_INVSQUARE = 7, /* matching PROP_INVSQUARE */ }; enum { - SUBDIV_SELECT_NONE, - SUBDIV_SELECT_ORIG, - SUBDIV_SELECT_INNER, - SUBDIV_SELECT_LOOPCUT, + SUBDIV_SELECT_NONE, + SUBDIV_SELECT_ORIG, + SUBDIV_SELECT_INNER, + SUBDIV_SELECT_LOOPCUT, }; /* subdivide_edgering */ enum { - /* just subdiv */ - SUBD_RING_INTERP_LINEAR, + /* just subdiv */ + SUBD_RING_INTERP_LINEAR, - /* single bezier spline - curve follows bezier rotation */ - SUBD_RING_INTERP_PATH, + /* single bezier spline - curve follows bezier rotation */ + SUBD_RING_INTERP_PATH, - /* beziers based on adjacent faces (fallback to tangent) */ - SUBD_RING_INTERP_SURF, + /* beziers based on adjacent faces (fallback to tangent) */ + SUBD_RING_INTERP_SURF, }; /* similar face selection slot values */ enum { - SIMFACE_MATERIAL = 201, - SIMFACE_AREA, - SIMFACE_SIDES, - SIMFACE_PERIMETER, - SIMFACE_NORMAL, - SIMFACE_COPLANAR, - SIMFACE_SMOOTH, - SIMFACE_FACEMAP, - SIMFACE_FREESTYLE, + SIMFACE_MATERIAL = 201, + SIMFACE_AREA, + SIMFACE_SIDES, + SIMFACE_PERIMETER, + SIMFACE_NORMAL, + SIMFACE_COPLANAR, + SIMFACE_SMOOTH, + SIMFACE_FACEMAP, + SIMFACE_FREESTYLE, }; /* similar edge selection slot values */ enum { - SIMEDGE_LENGTH = 101, - SIMEDGE_DIR, - SIMEDGE_FACE, - SIMEDGE_FACE_ANGLE, - SIMEDGE_CREASE, - SIMEDGE_BEVEL, - SIMEDGE_SEAM, - SIMEDGE_SHARP, - SIMEDGE_FREESTYLE, + SIMEDGE_LENGTH = 101, + SIMEDGE_DIR, + SIMEDGE_FACE, + SIMEDGE_FACE_ANGLE, + SIMEDGE_CREASE, + SIMEDGE_BEVEL, + SIMEDGE_SEAM, + SIMEDGE_SHARP, + SIMEDGE_FREESTYLE, }; /* similar vertex selection slot values */ enum { - SIMVERT_NORMAL = 0, - SIMVERT_FACE, - SIMVERT_VGROUP, - SIMVERT_EDGE, + SIMVERT_NORMAL = 0, + SIMVERT_FACE, + SIMVERT_VGROUP, + SIMVERT_EDGE, }; /* Poke face center calculation */ enum { - BMOP_POKE_MEDIAN_WEIGHTED = 0, - BMOP_POKE_MEDIAN, - BMOP_POKE_BOUNDS, + BMOP_POKE_MEDIAN_WEIGHTED = 0, + BMOP_POKE_MEDIAN, + BMOP_POKE_BOUNDS, }; /* Bevel offset_type slot values */ enum { - BEVEL_AMT_OFFSET, - BEVEL_AMT_WIDTH, - BEVEL_AMT_DEPTH, - BEVEL_AMT_PERCENT, + BEVEL_AMT_OFFSET, + BEVEL_AMT_WIDTH, + BEVEL_AMT_DEPTH, + BEVEL_AMT_PERCENT, }; /* Bevel face_strength_mode values: should match face_str mode enum in DNA_modifer_types.h */ enum { - BEVEL_FACE_STRENGTH_NONE, - BEVEL_FACE_STRENGTH_NEW, - BEVEL_FACE_STRENGTH_AFFECTED, - BEVEL_FACE_STRENGTH_ALL, + BEVEL_FACE_STRENGTH_NONE, + BEVEL_FACE_STRENGTH_NEW, + BEVEL_FACE_STRENGTH_AFFECTED, + BEVEL_FACE_STRENGTH_ALL, }; /* Bevel miter slot values */ enum { - BEVEL_MITER_SHARP, - BEVEL_MITER_PATCH, - BEVEL_MITER_ARC, + BEVEL_MITER_SHARP, + BEVEL_MITER_PATCH, + BEVEL_MITER_ARC, }; extern const BMOpDefine *bmo_opdefines[]; -extern const int bmo_opdefines_total; +extern const int bmo_opdefines_total; /*------specific operator helper functions-------*/ -void BM_mesh_esubdivide( - BMesh *bm, const char edge_hflag, - const float smooth, const short smooth_falloff, const bool use_smooth_even, - const float fractal, const float along_normal, - const int numcuts, - const int seltype, const int cornertype, - const short use_single_edge, const short use_grid_fill, - const short use_only_quads, - const int seed); - -void BM_mesh_calc_uvs_grid( - BMesh *bm, const uint x_segments, const uint y_segments, - const short oflag, const int cd_loop_uv_offset); -void BM_mesh_calc_uvs_sphere( - BMesh *bm, - const short oflag, const int cd_loop_uv_offset); -void BM_mesh_calc_uvs_circle( - BMesh *bm, float mat[4][4], const float radius, - const short oflag, const int cd_loop_uv_offset); -void BM_mesh_calc_uvs_cone( - BMesh *bm, float mat[4][4], - const float radius_top, const float radius_bottom, const int segments, const bool cap_ends, - const short oflag, const int cd_loop_uv_offset); +void BM_mesh_esubdivide(BMesh *bm, + const char edge_hflag, + const float smooth, + const short smooth_falloff, + const bool use_smooth_even, + const float fractal, + const float along_normal, + const int numcuts, + const int seltype, + const int cornertype, + const short use_single_edge, + const short use_grid_fill, + const short use_only_quads, + const int seed); + +void BM_mesh_calc_uvs_grid(BMesh *bm, + const uint x_segments, + const uint y_segments, + const short oflag, + const int cd_loop_uv_offset); +void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag, const int cd_loop_uv_offset); +void BM_mesh_calc_uvs_circle(BMesh *bm, + float mat[4][4], + const float radius, + const short oflag, + const int cd_loop_uv_offset); +void BM_mesh_calc_uvs_cone(BMesh *bm, + float mat[4][4], + const float radius_top, + const float radius_bottom, + const int segments, + const bool cap_ends, + const short oflag, + const int cd_loop_uv_offset); void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag); #include "intern/bmesh_operator_api_inline.h" diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 4cc3cf3e4c1..2a734c242ba 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -50,24 +50,24 @@ */ static float bm_face_calc_poly_normal(const BMFace *f, float n[3]) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter = l_first; - const float *v_prev = l_first->prev->v->co; - const float *v_curr = l_first->v->co; + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter = l_first; + const float *v_prev = l_first->prev->v->co; + const float *v_curr = l_first->v->co; - zero_v3(n); + zero_v3(n); - /* Newell's Method */ - do { - add_newell_cross_v3_v3v3(n, v_prev, v_curr); + /* Newell's Method */ + do { + add_newell_cross_v3_v3v3(n, v_prev, v_curr); - l_iter = l_iter->next; - v_prev = v_curr; - v_curr = l_iter->v->co; + l_iter = l_iter->next; + v_prev = v_curr; + v_curr = l_iter->v->co; - } while (l_iter != l_first); + } while (l_iter != l_first); - return normalize_v3(n); + return normalize_v3(n); } /** @@ -76,46 +76,46 @@ static float bm_face_calc_poly_normal(const BMFace *f, float n[3]) * Same as #bm_face_calc_poly_normal * but takes an array of vertex locations. */ -static float bm_face_calc_poly_normal_vertex_cos( - const BMFace *f, float r_no[3], - float const (*vertexCos)[3]) +static float bm_face_calc_poly_normal_vertex_cos(const BMFace *f, + float r_no[3], + float const (*vertexCos)[3]) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter = l_first; - const float *v_prev = vertexCos[BM_elem_index_get(l_first->prev->v)]; - const float *v_curr = vertexCos[BM_elem_index_get(l_first->v)]; + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter = l_first; + const float *v_prev = vertexCos[BM_elem_index_get(l_first->prev->v)]; + const float *v_curr = vertexCos[BM_elem_index_get(l_first->v)]; - zero_v3(r_no); + zero_v3(r_no); - /* Newell's Method */ - do { - add_newell_cross_v3_v3v3(r_no, v_prev, v_curr); + /* Newell's Method */ + do { + add_newell_cross_v3_v3v3(r_no, v_prev, v_curr); - l_iter = l_iter->next; - v_prev = v_curr; - v_curr = vertexCos[BM_elem_index_get(l_iter->v)]; - } while (l_iter != l_first); + l_iter = l_iter->next; + v_prev = v_curr; + v_curr = vertexCos[BM_elem_index_get(l_iter->v)]; + } while (l_iter != l_first); - return normalize_v3(r_no); + return normalize_v3(r_no); } /** * \brief COMPUTE POLY CENTER (BMFace) */ -static void bm_face_calc_poly_center_median_vertex_cos( - const BMFace *f, float r_cent[3], - float const (*vertexCos)[3]) +static void bm_face_calc_poly_center_median_vertex_cos(const BMFace *f, + float r_cent[3], + float const (*vertexCos)[3]) { - const BMLoop *l_first, *l_iter; + const BMLoop *l_first, *l_iter; - zero_v3(r_cent); + zero_v3(r_cent); - /* Newell's Method */ - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - add_v3_v3(r_cent, vertexCos[BM_elem_index_get(l_iter->v)]); - } while ((l_iter = l_iter->next) != l_first); - mul_v3_fl(r_cent, 1.0f / f->len); + /* Newell's Method */ + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + add_v3_v3(r_cent, vertexCos[BM_elem_index_get(l_iter->v)]); + } while ((l_iter = l_iter->next) != l_first); + mul_v3_fl(r_cent, 1.0f / f->len); } /** @@ -126,54 +126,55 @@ static void bm_face_calc_poly_center_median_vertex_cos( * \param r_loops: Store face loop pointers, (f->len) * \param r_index: Store triangle triples, indices into \a r_loops, `((f->len - 2) * 3)` */ -void BM_face_calc_tessellation( - const BMFace *f, const bool use_fixed_quad, - BMLoop **r_loops, uint (*r_index)[3]) +void BM_face_calc_tessellation(const BMFace *f, + const bool use_fixed_quad, + BMLoop **r_loops, + uint (*r_index)[3]) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter; - - if (f->len == 3) { - *r_loops++ = (l_iter = l_first); - *r_loops++ = (l_iter = l_iter->next); - *r_loops++ = ( l_iter->next); - - r_index[0][0] = 0; - r_index[0][1] = 1; - r_index[0][2] = 2; - } - else if (f->len == 4 && use_fixed_quad) { - *r_loops++ = (l_iter = l_first); - *r_loops++ = (l_iter = l_iter->next); - *r_loops++ = (l_iter = l_iter->next); - *r_loops++ = ( l_iter->next); - - r_index[0][0] = 0; - r_index[0][1] = 1; - r_index[0][2] = 2; - - r_index[1][0] = 0; - r_index[1][1] = 2; - r_index[1][2] = 3; - } - else { - float axis_mat[3][3]; - float (*projverts)[2] = BLI_array_alloca(projverts, f->len); - int j; - - axis_dominant_v3_to_m3(axis_mat, f->no); - - j = 0; - l_iter = l_first; - do { - mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); - r_loops[j] = l_iter; - j++; - } while ((l_iter = l_iter->next) != l_first); - - /* complete the loop */ - BLI_polyfill_calc(projverts, f->len, -1, r_index); - } + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter; + + if (f->len == 3) { + *r_loops++ = (l_iter = l_first); + *r_loops++ = (l_iter = l_iter->next); + *r_loops++ = (l_iter->next); + + r_index[0][0] = 0; + r_index[0][1] = 1; + r_index[0][2] = 2; + } + else if (f->len == 4 && use_fixed_quad) { + *r_loops++ = (l_iter = l_first); + *r_loops++ = (l_iter = l_iter->next); + *r_loops++ = (l_iter = l_iter->next); + *r_loops++ = (l_iter->next); + + r_index[0][0] = 0; + r_index[0][1] = 1; + r_index[0][2] = 2; + + r_index[1][0] = 0; + r_index[1][1] = 2; + r_index[1][2] = 3; + } + else { + float axis_mat[3][3]; + float(*projverts)[2] = BLI_array_alloca(projverts, f->len); + int j; + + axis_dominant_v3_to_m3(axis_mat, f->no); + + j = 0; + l_iter = l_first; + do { + mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); + r_loops[j] = l_iter; + j++; + } while ((l_iter = l_iter->next) != l_first); + + /* complete the loop */ + BLI_polyfill_calc(projverts, f->len, -1, r_index); + } } /** @@ -181,39 +182,40 @@ void BM_face_calc_tessellation( */ void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]) { - const BMLoop *l_tri[3]; - - if (f->len == 3) { - const BMLoop *l = BM_FACE_FIRST_LOOP(f); - ARRAY_SET_ITEMS(l_tri, l, l->next, l->prev); - } - else { - /* tessellation here seems overkill when in many cases this will be the center, - * but without this we can't be sure the point is inside a concave face. */ - const int tottri = f->len - 2; - BMLoop **loops = BLI_array_alloca(loops, f->len); - uint (*index)[3] = BLI_array_alloca(index, tottri); - int j; - int j_best = 0; /* use as fallback when unset */ - float area_best = -1.0f; - - BM_face_calc_tessellation(f, false, loops, index); - - for (j = 0; j < tottri; j++) { - const float *p1 = loops[index[j][0]]->v->co; - const float *p2 = loops[index[j][1]]->v->co; - const float *p3 = loops[index[j][2]]->v->co; - const float area = area_squared_tri_v3(p1, p2, p3); - if (area > area_best) { - j_best = j; - area_best = area; - } - } - - ARRAY_SET_ITEMS(l_tri, loops[index[j_best][0]], loops[index[j_best][1]], loops[index[j_best][2]]); - } - - mid_v3_v3v3v3(r_co, l_tri[0]->v->co, l_tri[1]->v->co, l_tri[2]->v->co); + const BMLoop *l_tri[3]; + + if (f->len == 3) { + const BMLoop *l = BM_FACE_FIRST_LOOP(f); + ARRAY_SET_ITEMS(l_tri, l, l->next, l->prev); + } + else { + /* tessellation here seems overkill when in many cases this will be the center, + * but without this we can't be sure the point is inside a concave face. */ + const int tottri = f->len - 2; + BMLoop **loops = BLI_array_alloca(loops, f->len); + uint(*index)[3] = BLI_array_alloca(index, tottri); + int j; + int j_best = 0; /* use as fallback when unset */ + float area_best = -1.0f; + + BM_face_calc_tessellation(f, false, loops, index); + + for (j = 0; j < tottri; j++) { + const float *p1 = loops[index[j][0]]->v->co; + const float *p2 = loops[index[j][1]]->v->co; + const float *p3 = loops[index[j][2]]->v->co; + const float area = area_squared_tri_v3(p1, p2, p3); + if (area > area_best) { + j_best = j; + area_best = area; + } + } + + ARRAY_SET_ITEMS( + l_tri, loops[index[j_best][0]], loops[index[j_best][1]], loops[index[j_best][2]]); + } + + mid_v3_v3v3v3(r_co, l_tri[0]->v->co, l_tri[1]->v->co, l_tri[2]->v->co); } /** @@ -221,16 +223,16 @@ void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]) */ float BM_face_calc_area(const BMFace *f) { - /* inline 'area_poly_v3' logic, avoid creating a temp array */ - const BMLoop *l_iter, *l_first; - float n[3]; - - zero_v3(n); - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - add_newell_cross_v3_v3v3(n, l_iter->v->co, l_iter->next->v->co); - } while ((l_iter = l_iter->next) != l_first); - return len_v3(n) * 0.5f; + /* inline 'area_poly_v3' logic, avoid creating a temp array */ + const BMLoop *l_iter, *l_first; + float n[3]; + + zero_v3(n); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + add_newell_cross_v3_v3v3(n, l_iter->v->co, l_iter->next->v->co); + } while ((l_iter = l_iter->next) != l_first); + return len_v3(n) * 0.5f; } /** @@ -238,21 +240,21 @@ float BM_face_calc_area(const BMFace *f) */ float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) { - /* inline 'area_poly_v3' logic, avoid creating a temp array */ - const BMLoop *l_iter, *l_first; - float co[3]; - float n[3]; - - zero_v3(n); - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - mul_v3_m3v3(co, mat3, l_iter->v->co); - do { - float co_next[3]; - mul_v3_m3v3(co_next, mat3, l_iter->next->v->co); - add_newell_cross_v3_v3v3(n, co, co_next); - copy_v3_v3(co, co_next); - } while ((l_iter = l_iter->next) != l_first); - return len_v3(n) * 0.5f; + /* inline 'area_poly_v3' logic, avoid creating a temp array */ + const BMLoop *l_iter, *l_first; + float co[3]; + float n[3]; + + zero_v3(n); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + mul_v3_m3v3(co, mat3, l_iter->v->co); + do { + float co_next[3]; + mul_v3_m3v3(co_next, mat3, l_iter->next->v->co); + add_newell_cross_v3_v3v3(n, co, co_next); + copy_v3_v3(co, co_next); + } while ((l_iter = l_iter->next) != l_first); + return len_v3(n) * 0.5f; } /** @@ -260,18 +262,18 @@ float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) */ float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) { - /* inline 'area_poly_v2' logic, avoid creating a temp array */ - const BMLoop *l_iter, *l_first; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - /* The Trapezium Area Rule */ - float cross = 0.0f; - do { - const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); - const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset); - cross += (luv_next->uv[0] - luv->uv[0]) * (luv_next->uv[1] + luv->uv[1]); - } while ((l_iter = l_iter->next) != l_first); - return fabsf(cross * 0.5f); + /* inline 'area_poly_v2' logic, avoid creating a temp array */ + const BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + /* The Trapezium Area Rule */ + float cross = 0.0f; + do { + const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); + const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset); + cross += (luv_next->uv[0] - luv->uv[0]) * (luv_next->uv[1] + luv->uv[1]); + } while ((l_iter = l_iter->next) != l_first); + return fabsf(cross * 0.5f); } /** @@ -279,15 +281,15 @@ float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) */ float BM_face_calc_perimeter(const BMFace *f) { - const BMLoop *l_iter, *l_first; - float perimeter = 0.0f; + const BMLoop *l_iter, *l_first; + float perimeter = 0.0f; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - perimeter += len_v3v3(l_iter->v->co, l_iter->next->v->co); - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + perimeter += len_v3v3(l_iter->v->co, l_iter->next->v->co); + } while ((l_iter = l_iter->next) != l_first); - return perimeter; + return perimeter; } /** @@ -295,20 +297,20 @@ float BM_face_calc_perimeter(const BMFace *f) */ float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3]) { - const BMLoop *l_iter, *l_first; - float co[3]; - float perimeter = 0.0f; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - mul_v3_m3v3(co, mat3, l_iter->v->co); - do { - float co_next[3]; - mul_v3_m3v3(co_next, mat3, l_iter->next->v->co); - perimeter += len_v3v3(co, co_next); - copy_v3_v3(co, co_next); - } while ((l_iter = l_iter->next) != l_first); - - return perimeter; + const BMLoop *l_iter, *l_first; + float co[3]; + float perimeter = 0.0f; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + mul_v3_m3v3(co, mat3, l_iter->v->co); + do { + float co_next[3]; + mul_v3_m3v3(co_next, mat3, l_iter->next->v->co); + perimeter += len_v3v3(co, co_next); + copy_v3_v3(co, co_next); + } while ((l_iter = l_iter->next) != l_first); + + return perimeter; } /** @@ -318,42 +320,39 @@ float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3]) */ static int bm_vert_tri_find_unique_edge(BMVert *verts[3]) { - /* find the most 'unique' loop, (greatest difference to others) */ + /* find the most 'unique' loop, (greatest difference to others) */ #if 1 - /* optimized version that avoids sqrt */ - float difs[3]; - for (int i_prev = 1, i_curr = 2, i_next = 0; - i_next < 3; - i_prev = i_curr, i_curr = i_next++) - { - const float *co = verts[i_curr]->co; - const float *co_other[2] = {verts[i_prev]->co, verts[i_next]->co}; - float proj_dir[3]; - mid_v3_v3v3(proj_dir, co_other[0], co_other[1]); - sub_v3_v3(proj_dir, co); - - float proj_pair[2][3]; - project_v3_v3v3(proj_pair[0], co_other[0], proj_dir); - project_v3_v3v3(proj_pair[1], co_other[1], proj_dir); - difs[i_next] = len_squared_v3v3(proj_pair[0], proj_pair[1]); - } + /* optimized version that avoids sqrt */ + float difs[3]; + for (int i_prev = 1, i_curr = 2, i_next = 0; i_next < 3; i_prev = i_curr, i_curr = i_next++) { + const float *co = verts[i_curr]->co; + const float *co_other[2] = {verts[i_prev]->co, verts[i_next]->co}; + float proj_dir[3]; + mid_v3_v3v3(proj_dir, co_other[0], co_other[1]); + sub_v3_v3(proj_dir, co); + + float proj_pair[2][3]; + project_v3_v3v3(proj_pair[0], co_other[0], proj_dir); + project_v3_v3v3(proj_pair[1], co_other[1], proj_dir); + difs[i_next] = len_squared_v3v3(proj_pair[0], proj_pair[1]); + } #else - const float lens[3] = { - len_v3v3(verts[0]->co, verts[1]->co), - len_v3v3(verts[1]->co, verts[2]->co), - len_v3v3(verts[2]->co, verts[0]->co), - }; - const float difs[3] = { - fabsf(lens[1] - lens[2]), - fabsf(lens[2] - lens[0]), - fabsf(lens[0] - lens[1]), - }; + const float lens[3] = { + len_v3v3(verts[0]->co, verts[1]->co), + len_v3v3(verts[1]->co, verts[2]->co), + len_v3v3(verts[2]->co, verts[0]->co), + }; + const float difs[3] = { + fabsf(lens[1] - lens[2]), + fabsf(lens[2] - lens[0]), + fabsf(lens[0] - lens[1]), + }; #endif - int order[3] = {0, 1, 2}; - axis_sort_v3(difs, order); + int order[3] = {0, 1, 2}; + axis_sort_v3(difs, order); - return order[0]; + return order[0]; } /** @@ -366,11 +365,11 @@ static int bm_vert_tri_find_unique_edge(BMVert *verts[3]) */ void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3]) { - const int index = bm_vert_tri_find_unique_edge(verts); + const int index = bm_vert_tri_find_unique_edge(verts); - sub_v3_v3v3(r_tangent, verts[index]->co, verts[(index + 1) % 3]->co); + sub_v3_v3v3(r_tangent, verts[index]->co, verts[(index + 1) % 3]->co); - normalize_v3(r_tangent); + normalize_v3(r_tangent); } /** @@ -383,29 +382,28 @@ void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3]) */ void BM_vert_tri_calc_tangent_edge_pair(BMVert *verts[3], float r_tangent[3]) { - const int index = bm_vert_tri_find_unique_edge(verts); + const int index = bm_vert_tri_find_unique_edge(verts); - const float *v_a = verts[index]->co; - const float *v_b = verts[(index + 1) % 3]->co; - const float *v_other = verts[(index + 2) % 3]->co; + const float *v_a = verts[index]->co; + const float *v_b = verts[(index + 1) % 3]->co; + const float *v_other = verts[(index + 2) % 3]->co; - mid_v3_v3v3(r_tangent, v_a, v_b); - sub_v3_v3v3(r_tangent, v_other, r_tangent); + mid_v3_v3v3(r_tangent, v_a, v_b); + sub_v3_v3v3(r_tangent, v_other, r_tangent); - normalize_v3(r_tangent); + normalize_v3(r_tangent); } /** * Compute the tangent of the face, using the longest edge. */ -void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3]) +void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3]) { - const BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f); + const BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f); - sub_v3_v3v3(r_tangent, l_long->v->co, l_long->next->v->co); - - normalize_v3(r_tangent); + sub_v3_v3v3(r_tangent, l_long->v->co, l_long->next->v->co); + normalize_v3(r_tangent); } /** @@ -413,64 +411,64 @@ void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3]) * * \param r_tangent: Calculated unit length tangent (return value). */ -void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3]) +void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3]) { - if (f->len == 3) { - BMVert *verts[3]; - - BM_face_as_array_vert_tri((BMFace *)f, verts); - - BM_vert_tri_calc_tangent_edge_pair(verts, r_tangent); - } - else if (f->len == 4) { - /* Use longest edge pair */ - BMVert *verts[4]; - float vec[3], vec_a[3], vec_b[3]; - - BM_face_as_array_vert_quad((BMFace *)f, verts); - - sub_v3_v3v3(vec_a, verts[3]->co, verts[2]->co); - sub_v3_v3v3(vec_b, verts[0]->co, verts[1]->co); - add_v3_v3v3(r_tangent, vec_a, vec_b); - - sub_v3_v3v3(vec_a, verts[0]->co, verts[3]->co); - sub_v3_v3v3(vec_b, verts[1]->co, verts[2]->co); - add_v3_v3v3(vec, vec_a, vec_b); - /* use the longest edge length */ - if (len_squared_v3(r_tangent) < len_squared_v3(vec)) { - copy_v3_v3(r_tangent, vec); - } - } - else { - /* For ngons use two longest disconnected edges */ - BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f); - BMLoop *l_long_other = NULL; - - float len_max_sq = 0.0f; - float vec_a[3], vec_b[3]; - - BMLoop *l_iter = l_long->prev->prev; - BMLoop *l_last = l_long->next; - - do { - const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co); - if (len_sq >= len_max_sq) { - l_long_other = l_iter; - len_max_sq = len_sq; - } - } while ((l_iter = l_iter->prev) != l_last); - - sub_v3_v3v3(vec_a, l_long->next->v->co, l_long->v->co); - sub_v3_v3v3(vec_b, l_long_other->v->co, l_long_other->next->v->co); - add_v3_v3v3(r_tangent, vec_a, vec_b); - - /* Edges may not be opposite side of the ngon, - * this could cause problems for ngons with multiple-aligned edges of the same length. - * Fallback to longest edge. */ - if (UNLIKELY(normalize_v3(r_tangent) == 0.0f)) { - normalize_v3_v3(r_tangent, vec_a); - } - } + if (f->len == 3) { + BMVert *verts[3]; + + BM_face_as_array_vert_tri((BMFace *)f, verts); + + BM_vert_tri_calc_tangent_edge_pair(verts, r_tangent); + } + else if (f->len == 4) { + /* Use longest edge pair */ + BMVert *verts[4]; + float vec[3], vec_a[3], vec_b[3]; + + BM_face_as_array_vert_quad((BMFace *)f, verts); + + sub_v3_v3v3(vec_a, verts[3]->co, verts[2]->co); + sub_v3_v3v3(vec_b, verts[0]->co, verts[1]->co); + add_v3_v3v3(r_tangent, vec_a, vec_b); + + sub_v3_v3v3(vec_a, verts[0]->co, verts[3]->co); + sub_v3_v3v3(vec_b, verts[1]->co, verts[2]->co); + add_v3_v3v3(vec, vec_a, vec_b); + /* use the longest edge length */ + if (len_squared_v3(r_tangent) < len_squared_v3(vec)) { + copy_v3_v3(r_tangent, vec); + } + } + else { + /* For ngons use two longest disconnected edges */ + BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f); + BMLoop *l_long_other = NULL; + + float len_max_sq = 0.0f; + float vec_a[3], vec_b[3]; + + BMLoop *l_iter = l_long->prev->prev; + BMLoop *l_last = l_long->next; + + do { + const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co); + if (len_sq >= len_max_sq) { + l_long_other = l_iter; + len_max_sq = len_sq; + } + } while ((l_iter = l_iter->prev) != l_last); + + sub_v3_v3v3(vec_a, l_long->next->v->co, l_long->v->co); + sub_v3_v3v3(vec_b, l_long_other->v->co, l_long_other->next->v->co); + add_v3_v3v3(r_tangent, vec_a, vec_b); + + /* Edges may not be opposite side of the ngon, + * this could cause problems for ngons with multiple-aligned edges of the same length. + * Fallback to longest edge. */ + if (UNLIKELY(normalize_v3(r_tangent) == 0.0f)) { + normalize_v3_v3(r_tangent, vec_a); + } + } } /** @@ -478,35 +476,36 @@ void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3]) * * \param r_tangent: Calculated unit length tangent (return value). */ -void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3]) +void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3]) { - BMLoop *l_iter, *l_first; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - - /* incase of degenerate faces */ - zero_v3(r_tangent); - - /* warning: O(n^2) loop here, take care! */ - float dist_max_sq = 0.0f; - do { - BMLoop *l_iter_other = l_iter->next; - BMLoop *l_iter_last = l_iter->prev; - do { - BLI_assert(!ELEM(l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co)); - float co_other[3], vec[3]; - closest_to_line_segment_v3(co_other, l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co); - sub_v3_v3v3(vec, l_iter->v->co, co_other); - - const float dist_sq = len_squared_v3(vec); - if (dist_sq > dist_max_sq) { - dist_max_sq = dist_sq; - copy_v3_v3(r_tangent, vec); - } - } while ((l_iter_other = l_iter_other->next) != l_iter_last); - } while ((l_iter = l_iter->next) != l_first); - - normalize_v3(r_tangent); + BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + + /* incase of degenerate faces */ + zero_v3(r_tangent); + + /* warning: O(n^2) loop here, take care! */ + float dist_max_sq = 0.0f; + do { + BMLoop *l_iter_other = l_iter->next; + BMLoop *l_iter_last = l_iter->prev; + do { + BLI_assert(!ELEM(l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co)); + float co_other[3], vec[3]; + closest_to_line_segment_v3( + co_other, l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co); + sub_v3_v3v3(vec, l_iter->v->co, co_other); + + const float dist_sq = len_squared_v3(vec); + if (dist_sq > dist_max_sq) { + dist_max_sq = dist_sq; + copy_v3_v3(r_tangent, vec); + } + } while ((l_iter_other = l_iter_other->next) != l_iter_last); + } while ((l_iter = l_iter->next) != l_first); + + normalize_v3(r_tangent); } /** @@ -514,32 +513,32 @@ void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3]) * * \note The logic is almost identical to #BM_face_calc_tangent_edge_diagonal */ -void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3]) +void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3]) { - BMLoop *l_iter, *l_first; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - - /* incase of degenerate faces */ - zero_v3(r_tangent); - - /* warning: O(n^2) loop here, take care! */ - float dist_max_sq = 0.0f; - do { - BMLoop *l_iter_other = l_iter->next; - do { - float vec[3]; - sub_v3_v3v3(vec, l_iter->v->co, l_iter_other->v->co); - - const float dist_sq = len_squared_v3(vec); - if (dist_sq > dist_max_sq) { - dist_max_sq = dist_sq; - copy_v3_v3(r_tangent, vec); - } - } while ((l_iter_other = l_iter_other->next) != l_iter); - } while ((l_iter = l_iter->next) != l_first); - - normalize_v3(r_tangent); + BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + + /* incase of degenerate faces */ + zero_v3(r_tangent); + + /* warning: O(n^2) loop here, take care! */ + float dist_max_sq = 0.0f; + do { + BMLoop *l_iter_other = l_iter->next; + do { + float vec[3]; + sub_v3_v3v3(vec, l_iter->v->co, l_iter_other->v->co); + + const float dist_sq = len_squared_v3(vec); + if (dist_sq > dist_max_sq) { + dist_max_sq = dist_sq; + copy_v3_v3(r_tangent, vec); + } + } while ((l_iter_other = l_iter_other->next) != l_iter); + } while ((l_iter = l_iter->next) != l_first); + + normalize_v3(r_tangent); } /** @@ -549,20 +548,20 @@ void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3]) */ void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3]) { - if (f->len == 3) { - /* most 'unique' edge of a triangle */ - BMVert *verts[3]; - BM_face_as_array_vert_tri((BMFace *)f, verts); - BM_vert_tri_calc_tangent_edge(verts, r_tangent); - } - else if (f->len == 4) { - /* longest edge pair of a quad */ - BM_face_calc_tangent_edge_pair((BMFace *)f, r_tangent); - } - else { - /* longest edge of an ngon */ - BM_face_calc_tangent_edge((BMFace *)f, r_tangent); - } + if (f->len == 3) { + /* most 'unique' edge of a triangle */ + BMVert *verts[3]; + BM_face_as_array_vert_tri((BMFace *)f, verts); + BM_vert_tri_calc_tangent_edge(verts, r_tangent); + } + else if (f->len == 4) { + /* longest edge pair of a quad */ + BM_face_calc_tangent_edge_pair((BMFace *)f, r_tangent); + } + else { + /* longest edge of an ngon */ + BM_face_calc_tangent_edge((BMFace *)f, r_tangent); + } } /** @@ -570,11 +569,11 @@ void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3]) */ void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3]) { - const BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - minmax_v3v3_v3(min, max, l_iter->v->co); - } while ((l_iter = l_iter->next) != l_first); + const BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + minmax_v3v3_v3(min, max, l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); } /** @@ -582,17 +581,17 @@ void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3]) */ void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3]) { - const BMLoop *l_iter, *l_first; - float min[3], max[3]; + const BMLoop *l_iter, *l_first; + float min[3], max[3]; - INIT_MINMAX(min, max); + INIT_MINMAX(min, max); - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - minmax_v3v3_v3(min, max, l_iter->v->co); - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + minmax_v3v3_v3(min, max, l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); - mid_v3_v3v3(r_cent, min, max); + mid_v3_v3v3(r_cent, min, max); } /** @@ -600,15 +599,15 @@ void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3]) */ void BM_face_calc_center_median(const BMFace *f, float r_cent[3]) { - const BMLoop *l_iter, *l_first; + const BMLoop *l_iter, *l_first; - zero_v3(r_cent); + zero_v3(r_cent); - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - add_v3_v3(r_cent, l_iter->v->co); - } while ((l_iter = l_iter->next) != l_first); - mul_v3_fl(r_cent, 1.0f / (float) f->len); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + add_v3_v3(r_cent, l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); + mul_v3_fl(r_cent, 1.0f / (float)f->len); } /** @@ -617,27 +616,26 @@ void BM_face_calc_center_median(const BMFace *f, float r_cent[3]) */ void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3]) { - const BMLoop *l_iter; - const BMLoop *l_first; - float totw = 0.0f; - float w_prev; - - zero_v3(r_cent); - - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - w_prev = BM_edge_calc_length(l_iter->prev->e); - do { - const float w_curr = BM_edge_calc_length(l_iter->e); - const float w = (w_curr + w_prev); - madd_v3_v3fl(r_cent, l_iter->v->co, w); - totw += w; - w_prev = w_curr; - } while ((l_iter = l_iter->next) != l_first); - - if (totw != 0.0f) { - mul_v3_fl(r_cent, 1.0f / (float) totw); - } + const BMLoop *l_iter; + const BMLoop *l_first; + float totw = 0.0f; + float w_prev; + + zero_v3(r_cent); + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + w_prev = BM_edge_calc_length(l_iter->prev->e); + do { + const float w_curr = BM_edge_calc_length(l_iter->e); + const float w = (w_curr + w_prev); + madd_v3_v3fl(r_cent, l_iter->v->co, w); + totw += w; + w_prev = w_curr; + } while ((l_iter = l_iter->next) != l_first); + + if (totw != 0.0f) { + mul_v3_fl(r_cent, 1.0f / (float)totw); + } } /** @@ -648,17 +646,17 @@ void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3]) */ void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nverts) { - float mat[3][3]; - float co[3]; - uint i; + float mat[3][3]; + float co[3]; + uint i; - co[2] = 0.0f; + co[2] = 0.0f; - axis_dominant_v3_to_m3(mat, normal); - for (i = 0; i < nverts; i++) { - mul_v2_m3v3(co, mat, verts[i]); - copy_v3_v3(verts[i], co); - } + axis_dominant_v3_to_m3(mat, normal); + for (i = 0; i < nverts; i++) { + mul_v2_m3v3(co, mat, verts[i]); + copy_v3_v3(verts[i], co); + } } /** @@ -666,119 +664,119 @@ void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nver */ void BM_edge_normals_update(BMEdge *e) { - BMIter iter; - BMFace *f; + BMIter iter; + BMFace *f; - BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { - BM_face_normal_update(f); - } + BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { + BM_face_normal_update(f); + } - BM_vert_normal_update(e->v1); - BM_vert_normal_update(e->v2); + BM_vert_normal_update(e->v1); + BM_vert_normal_update(e->v2); } static void bm_loop_normal_accum(const BMLoop *l, float no[3]) { - float vec1[3], vec2[3], fac; + float vec1[3], vec2[3], fac; - /* Same calculation used in BM_mesh_normals_update */ - sub_v3_v3v3(vec1, l->v->co, l->prev->v->co); - sub_v3_v3v3(vec2, l->next->v->co, l->v->co); - normalize_v3(vec1); - normalize_v3(vec2); + /* Same calculation used in BM_mesh_normals_update */ + sub_v3_v3v3(vec1, l->v->co, l->prev->v->co); + sub_v3_v3v3(vec2, l->next->v->co, l->v->co); + normalize_v3(vec1); + normalize_v3(vec2); - fac = saacos(-dot_v3v3(vec1, vec2)); + fac = saacos(-dot_v3v3(vec1, vec2)); - madd_v3_v3fl(no, l->f->no, fac); + madd_v3_v3fl(no, l->f->no, fac); } bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3]) { - int len = 0; - - zero_v3(r_no); - - if (v->e) { - const BMEdge *e = v->e; - do { - if (e->l) { - const BMLoop *l = e->l; - do { - if (l->v == v) { - if (BM_elem_flag_test(l->f, hflag)) { - bm_loop_normal_accum(l, r_no); - len++; - } - } - } while ((l = l->radial_next) != e->l); - } - } while ((e = bmesh_disk_edge_next(e, v)) != v->e); - } - - if (len) { - normalize_v3(r_no); - return true; - } - else { - return false; - } + int len = 0; + + zero_v3(r_no); + + if (v->e) { + const BMEdge *e = v->e; + do { + if (e->l) { + const BMLoop *l = e->l; + do { + if (l->v == v) { + if (BM_elem_flag_test(l->f, hflag)) { + bm_loop_normal_accum(l, r_no); + len++; + } + } + } while ((l = l->radial_next) != e->l); + } + } while ((e = bmesh_disk_edge_next(e, v)) != v->e); + } + + if (len) { + normalize_v3(r_no); + return true; + } + else { + return false; + } } bool BM_vert_calc_normal(const BMVert *v, float r_no[3]) { - int len = 0; - - zero_v3(r_no); - - if (v->e) { - const BMEdge *e = v->e; - do { - if (e->l) { - const BMLoop *l = e->l; - do { - if (l->v == v) { - bm_loop_normal_accum(l, r_no); - len++; - } - } while ((l = l->radial_next) != e->l); - } - } while ((e = bmesh_disk_edge_next(e, v)) != v->e); - } - - if (len) { - normalize_v3(r_no); - return true; - } - else { - return false; - } + int len = 0; + + zero_v3(r_no); + + if (v->e) { + const BMEdge *e = v->e; + do { + if (e->l) { + const BMLoop *l = e->l; + do { + if (l->v == v) { + bm_loop_normal_accum(l, r_no); + len++; + } + } while ((l = l->radial_next) != e->l); + } + } while ((e = bmesh_disk_edge_next(e, v)) != v->e); + } + + if (len) { + normalize_v3(r_no); + return true; + } + else { + return false; + } } void BM_vert_normal_update_all(BMVert *v) { - int len = 0; - - zero_v3(v->no); - - if (v->e) { - const BMEdge *e = v->e; - do { - if (e->l) { - const BMLoop *l = e->l; - do { - if (l->v == v) { - BM_face_normal_update(l->f); - bm_loop_normal_accum(l, v->no); - len++; - } - } while ((l = l->radial_next) != e->l); - } - } while ((e = bmesh_disk_edge_next(e, v)) != v->e); - } - - if (len) { - normalize_v3(v->no); - } + int len = 0; + + zero_v3(v->no); + + if (v->e) { + const BMEdge *e = v->e; + do { + if (e->l) { + const BMLoop *l = e->l; + do { + if (l->v == v) { + BM_face_normal_update(l->f); + bm_loop_normal_accum(l, v->no); + len++; + } + } while ((l = l->radial_next) != e->l); + } + } while ((e = bmesh_disk_edge_next(e, v)) != v->e); + } + + if (len) { + normalize_v3(v->no); + } } /** @@ -786,7 +784,7 @@ void BM_vert_normal_update_all(BMVert *v) */ void BM_vert_normal_update(BMVert *v) { - BM_vert_calc_normal(v, v->no); + BM_vert_calc_normal(v, v->no); } /** @@ -801,73 +799,68 @@ void BM_vert_normal_update(BMVert *v) float BM_face_calc_normal(const BMFace *f, float r_no[3]) { - BMLoop *l; - - /* common cases first */ - switch (f->len) { - case 4: - { - const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co; - const float *co2 = (l = l->next)->v->co; - const float *co3 = (l = l->next)->v->co; - const float *co4 = (l->next)->v->co; - - return normal_quad_v3(r_no, co1, co2, co3, co4); - } - case 3: - { - const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co; - const float *co2 = (l = l->next)->v->co; - const float *co3 = (l->next)->v->co; - - return normal_tri_v3(r_no, co1, co2, co3); - } - default: - { - return bm_face_calc_poly_normal(f, r_no); - } - } + BMLoop *l; + + /* common cases first */ + switch (f->len) { + case 4: { + const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co; + const float *co2 = (l = l->next)->v->co; + const float *co3 = (l = l->next)->v->co; + const float *co4 = (l->next)->v->co; + + return normal_quad_v3(r_no, co1, co2, co3, co4); + } + case 3: { + const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co; + const float *co2 = (l = l->next)->v->co; + const float *co3 = (l->next)->v->co; + + return normal_tri_v3(r_no, co1, co2, co3); + } + default: { + return bm_face_calc_poly_normal(f, r_no); + } + } } void BM_face_normal_update(BMFace *f) { - BM_face_calc_normal(f, f->no); + BM_face_calc_normal(f, f->no); } /* exact same as 'BM_face_calc_normal' but accepts vertex coords */ -float BM_face_calc_normal_vcos( - const BMesh *bm, const BMFace *f, float r_no[3], - float const (*vertexCos)[3]) +float BM_face_calc_normal_vcos(const BMesh *bm, + const BMFace *f, + float r_no[3], + float const (*vertexCos)[3]) { - BMLoop *l; - - /* must have valid index data */ - BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); - (void)bm; - - /* common cases first */ - switch (f->len) { - case 4: - { - const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)]; - const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)]; - const float *co3 = vertexCos[BM_elem_index_get((l = l->next)->v)]; - const float *co4 = vertexCos[BM_elem_index_get((l->next)->v)]; - - return normal_quad_v3(r_no, co1, co2, co3, co4); - } - case 3: - { - const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)]; - const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)]; - const float *co3 = vertexCos[BM_elem_index_get((l->next)->v)]; - - return normal_tri_v3(r_no, co1, co2, co3); - } - default: - { - return bm_face_calc_poly_normal_vertex_cos(f, r_no, vertexCos); - } - } + BMLoop *l; + + /* must have valid index data */ + BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); + (void)bm; + + /* common cases first */ + switch (f->len) { + case 4: { + const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)]; + const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)]; + const float *co3 = vertexCos[BM_elem_index_get((l = l->next)->v)]; + const float *co4 = vertexCos[BM_elem_index_get((l->next)->v)]; + + return normal_quad_v3(r_no, co1, co2, co3, co4); + } + case 3: { + const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)]; + const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)]; + const float *co3 = vertexCos[BM_elem_index_get((l->next)->v)]; + + return normal_tri_v3(r_no, co1, co2, co3); + } + default: { + return bm_face_calc_poly_normal_vertex_cos(f, r_no, vertexCos); + } + } } /** @@ -875,34 +868,35 @@ float BM_face_calc_normal_vcos( */ float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3]) { - const float *v_prev, *v_curr; + const float *v_prev, *v_curr; - /* Newell's Method */ - const BMLoop *l_iter = l_first; - const BMLoop *l_term = l_last->next; + /* Newell's Method */ + const BMLoop *l_iter = l_first; + const BMLoop *l_term = l_last->next; - zero_v3(r_no); + zero_v3(r_no); - v_prev = l_last->v->co; - do { - v_curr = l_iter->v->co; - add_newell_cross_v3_v3v3(r_no, v_prev, v_curr); - v_prev = v_curr; - } while ((l_iter = l_iter->next) != l_term); + v_prev = l_last->v->co; + do { + v_curr = l_iter->v->co; + add_newell_cross_v3_v3v3(r_no, v_prev, v_curr); + v_prev = v_curr; + } while ((l_iter = l_iter->next) != l_term); - return normalize_v3(r_no); + return normalize_v3(r_no); } /* exact same as 'BM_face_calc_normal' but accepts vertex coords */ -void BM_face_calc_center_median_vcos( - const BMesh *bm, const BMFace *f, float r_cent[3], - float const (*vertexCos)[3]) +void BM_face_calc_center_median_vcos(const BMesh *bm, + const BMFace *f, + float r_cent[3], + float const (*vertexCos)[3]) { - /* must have valid index data */ - BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); - (void)bm; + /* must have valid index data */ + BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); + (void)bm; - bm_face_calc_poly_center_median_vertex_cos(f, r_cent, vertexCos); + bm_face_calc_poly_center_median_vertex_cos(f, r_cent, vertexCos); } /** @@ -911,18 +905,19 @@ void BM_face_calc_center_median_vcos( * Reverses the winding of a face. * \note This updates the calculated normal. */ -void BM_face_normal_flip_ex( - BMesh *bm, BMFace *f, - const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip) +void BM_face_normal_flip_ex(BMesh *bm, + BMFace *f, + const int cd_loop_mdisp_offset, + const bool use_loop_mdisp_flip) { - bmesh_kernel_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip); - negate_v3(f->no); + bmesh_kernel_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip); + negate_v3(f->no); } void BM_face_normal_flip(BMesh *bm, BMFace *f) { - const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); - BM_face_normal_flip_ex(bm, f, cd_loop_mdisp_offset, true); + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + BM_face_normal_flip_ex(bm, f, cd_loop_mdisp_offset, true); } /** @@ -937,24 +932,24 @@ void BM_face_normal_flip(BMesh *bm, BMFace *f) */ bool BM_face_point_inside_test(const BMFace *f, const float co[3]) { - float axis_mat[3][3]; - float (*projverts)[2] = BLI_array_alloca(projverts, f->len); + float axis_mat[3][3]; + float(*projverts)[2] = BLI_array_alloca(projverts, f->len); - float co_2d[2]; - BMLoop *l_iter; - int i; + float co_2d[2]; + BMLoop *l_iter; + int i; - BLI_assert(BM_face_is_normal_valid(f)); + BLI_assert(BM_face_is_normal_valid(f)); - axis_dominant_v3_to_m3(axis_mat, f->no); + axis_dominant_v3_to_m3(axis_mat, f->no); - mul_v2_m3v3(co_2d, axis_mat, co); + mul_v2_m3v3(co_2d, axis_mat, co); - for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) { - mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co); - } + for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) { + mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co); + } - return isect_point_poly_v2(co_2d, projverts, f->len, false); + return isect_point_poly_v2(co_2d, projverts, f->len, false); } /** @@ -980,236 +975,226 @@ bool BM_face_point_inside_test(const BMFace *f, const float co[3]) * * \note use_tag tags new flags and edges. */ -void BM_face_triangulate( - BMesh *bm, BMFace *f, - BMFace **r_faces_new, - int *r_faces_new_tot, - BMEdge **r_edges_new, - int *r_edges_new_tot, - LinkNode **r_faces_double, - const int quad_method, - const int ngon_method, - const bool use_tag, - /* use for ngons only! */ - MemArena *pf_arena, - - /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */ - struct Heap *pf_heap) +void BM_face_triangulate(BMesh *bm, + BMFace *f, + BMFace **r_faces_new, + int *r_faces_new_tot, + BMEdge **r_edges_new, + int *r_edges_new_tot, + LinkNode **r_faces_double, + const int quad_method, + const int ngon_method, + const bool use_tag, + /* use for ngons only! */ + MemArena *pf_arena, + + /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */ + struct Heap *pf_heap) { - const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); - const bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY); - BMLoop *l_first, *l_new; - BMFace *f_new; - int nf_i = 0; - int ne_i = 0; - - BLI_assert(BM_face_is_normal_valid(f)); - - /* ensure both are valid or NULL */ - BLI_assert((r_faces_new == NULL) == (r_faces_new_tot == NULL)); - - BLI_assert(f->len > 3); - - { - BMLoop **loops = BLI_array_alloca(loops, f->len); - uint (*tris)[3] = BLI_array_alloca(tris, f->len); - const int totfilltri = f->len - 2; - const int last_tri = f->len - 3; - int i; - /* for mdisps */ - float f_center[3]; - - if (f->len == 4) { - /* even though we're not using BLI_polyfill, fill in 'tris' and 'loops' - * so we can share code to handle face creation afterwards. */ - BMLoop *l_v1, *l_v2; - - l_first = BM_FACE_FIRST_LOOP(f); - - switch (quad_method) { - case MOD_TRIANGULATE_QUAD_FIXED: - { - l_v1 = l_first; - l_v2 = l_first->next->next; - break; - } - case MOD_TRIANGULATE_QUAD_ALTERNATE: - { - l_v1 = l_first->next; - l_v2 = l_first->prev; - break; - } - case MOD_TRIANGULATE_QUAD_SHORTEDGE: - case MOD_TRIANGULATE_QUAD_BEAUTY: - default: - { - BMLoop *l_v3, *l_v4; - bool split_24; - - l_v1 = l_first->next; - l_v2 = l_first->next->next; - l_v3 = l_first->prev; - l_v4 = l_first; - - if (quad_method == MOD_TRIANGULATE_QUAD_SHORTEDGE) { - float d1, d2; - d1 = len_squared_v3v3(l_v4->v->co, l_v2->v->co); - d2 = len_squared_v3v3(l_v1->v->co, l_v3->v->co); - split_24 = ((d2 - d1) > 0.0f); - } - else { - /* first check if the quad is concave on either diagonal */ - const int flip_flag = is_quad_flip_v3(l_v1->v->co, l_v2->v->co, l_v3->v->co, l_v4->v->co); - if (UNLIKELY(flip_flag & (1 << 0))) { - split_24 = true; - } - else if (UNLIKELY(flip_flag & (1 << 1))) { - split_24 = false; - } - else { - split_24 = (BM_verts_calc_rotate_beauty(l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) > 0.0f); - } - } - - /* named confusingly, l_v1 is in fact the second vertex */ - if (split_24) { - l_v1 = l_v4; - //l_v2 = l_v2; - } - else { - //l_v1 = l_v1; - l_v2 = l_v3; - } - break; - } - } - - loops[0] = l_v1; - loops[1] = l_v1->next; - loops[2] = l_v2; - loops[3] = l_v2->next; - - ARRAY_SET_ITEMS(tris[0], 0, 1, 2); - ARRAY_SET_ITEMS(tris[1], 0, 2, 3); - } - else { - BMLoop *l_iter; - float axis_mat[3][3]; - float (*projverts)[2] = BLI_array_alloca(projverts, f->len); - - axis_dominant_v3_to_m3_negate(axis_mat, f->no); - - for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) { - loops[i] = l_iter; - mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co); - } - - BLI_polyfill_calc_arena(projverts, f->len, 1, tris, - pf_arena); - - if (use_beauty) { - BLI_polyfill_beautify( - projverts, f->len, tris, - pf_arena, pf_heap); - } - - BLI_memarena_clear(pf_arena); - } - - if (cd_loop_mdisp_offset != -1) { - BM_face_calc_center_median(f, f_center); - } - - /* loop over calculated triangles and create new geometry */ - for (i = 0; i < totfilltri; i++) { - BMLoop *l_tri[3] = { - loops[tris[i][0]], - loops[tris[i][1]], - loops[tris[i][2]]}; - - BMVert *v_tri[3] = { - l_tri[0]->v, - l_tri[1]->v, - l_tri[2]->v}; - - f_new = BM_face_create_verts(bm, v_tri, 3, f, BM_CREATE_NOP, true); - l_new = BM_FACE_FIRST_LOOP(f_new); - - BLI_assert(v_tri[0] == l_new->v); - - /* check for duplicate */ - if (l_new->radial_next != l_new) { - BMLoop *l_iter = l_new->radial_next; - do { - if (UNLIKELY((l_iter->f->len == 3) && (l_new->prev->v == l_iter->prev->v))) { - /* Check the last tri because we swap last f_new with f at the end... */ - BLI_linklist_prepend(r_faces_double, (i != last_tri) ? f_new : f); - break; - } - } while ((l_iter = l_iter->radial_next) != l_new); - } - - /* copy CD data */ - BM_elem_attrs_copy(bm, bm, l_tri[0], l_new); - BM_elem_attrs_copy(bm, bm, l_tri[1], l_new->next); - BM_elem_attrs_copy(bm, bm, l_tri[2], l_new->prev); - - /* add all but the last face which is swapped and removed (below) */ - if (i != last_tri) { - if (use_tag) { - BM_elem_flag_enable(f_new, BM_ELEM_TAG); - } - if (r_faces_new) { - r_faces_new[nf_i++] = f_new; - } - } - - if (use_tag || r_edges_new) { - /* new faces loops */ - BMLoop *l_iter; - - l_iter = l_first = l_new; - do { - BMEdge *e = l_iter->e; - /* confusing! if its not a boundary now, we know it will be later - * since this will be an edge of one of the new faces which we're in the middle of creating */ - bool is_new_edge = (l_iter == l_iter->radial_next); - - if (is_new_edge) { - if (use_tag) { - BM_elem_flag_enable(e, BM_ELEM_TAG); - } - if (r_edges_new) { - r_edges_new[ne_i++] = e; - } - } - /* note, never disable tag's */ - } while ((l_iter = l_iter->next) != l_first); - } - - if (cd_loop_mdisp_offset != -1) { - float f_new_center[3]; - BM_face_calc_center_median(f_new, f_new_center); - BM_face_interp_multires_ex(bm, f_new, f, f_new_center, f_center, cd_loop_mdisp_offset); - } - } - - { - /* we can't delete the real face, because some of the callers expect it to remain valid. - * so swap data and delete the last created tri */ - bmesh_face_swap_data(f, f_new); - BM_face_kill(bm, f_new); - } - } - bm->elem_index_dirty |= BM_FACE; - - if (r_faces_new_tot) { - *r_faces_new_tot = nf_i; - } - - if (r_edges_new_tot) { - *r_edges_new_tot = ne_i; - } + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + const bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY); + BMLoop *l_first, *l_new; + BMFace *f_new; + int nf_i = 0; + int ne_i = 0; + + BLI_assert(BM_face_is_normal_valid(f)); + + /* ensure both are valid or NULL */ + BLI_assert((r_faces_new == NULL) == (r_faces_new_tot == NULL)); + + BLI_assert(f->len > 3); + + { + BMLoop **loops = BLI_array_alloca(loops, f->len); + uint(*tris)[3] = BLI_array_alloca(tris, f->len); + const int totfilltri = f->len - 2; + const int last_tri = f->len - 3; + int i; + /* for mdisps */ + float f_center[3]; + + if (f->len == 4) { + /* even though we're not using BLI_polyfill, fill in 'tris' and 'loops' + * so we can share code to handle face creation afterwards. */ + BMLoop *l_v1, *l_v2; + + l_first = BM_FACE_FIRST_LOOP(f); + + switch (quad_method) { + case MOD_TRIANGULATE_QUAD_FIXED: { + l_v1 = l_first; + l_v2 = l_first->next->next; + break; + } + case MOD_TRIANGULATE_QUAD_ALTERNATE: { + l_v1 = l_first->next; + l_v2 = l_first->prev; + break; + } + case MOD_TRIANGULATE_QUAD_SHORTEDGE: + case MOD_TRIANGULATE_QUAD_BEAUTY: + default: { + BMLoop *l_v3, *l_v4; + bool split_24; + + l_v1 = l_first->next; + l_v2 = l_first->next->next; + l_v3 = l_first->prev; + l_v4 = l_first; + + if (quad_method == MOD_TRIANGULATE_QUAD_SHORTEDGE) { + float d1, d2; + d1 = len_squared_v3v3(l_v4->v->co, l_v2->v->co); + d2 = len_squared_v3v3(l_v1->v->co, l_v3->v->co); + split_24 = ((d2 - d1) > 0.0f); + } + else { + /* first check if the quad is concave on either diagonal */ + const int flip_flag = is_quad_flip_v3( + l_v1->v->co, l_v2->v->co, l_v3->v->co, l_v4->v->co); + if (UNLIKELY(flip_flag & (1 << 0))) { + split_24 = true; + } + else if (UNLIKELY(flip_flag & (1 << 1))) { + split_24 = false; + } + else { + split_24 = (BM_verts_calc_rotate_beauty(l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) > + 0.0f); + } + } + + /* named confusingly, l_v1 is in fact the second vertex */ + if (split_24) { + l_v1 = l_v4; + //l_v2 = l_v2; + } + else { + //l_v1 = l_v1; + l_v2 = l_v3; + } + break; + } + } + + loops[0] = l_v1; + loops[1] = l_v1->next; + loops[2] = l_v2; + loops[3] = l_v2->next; + + ARRAY_SET_ITEMS(tris[0], 0, 1, 2); + ARRAY_SET_ITEMS(tris[1], 0, 2, 3); + } + else { + BMLoop *l_iter; + float axis_mat[3][3]; + float(*projverts)[2] = BLI_array_alloca(projverts, f->len); + + axis_dominant_v3_to_m3_negate(axis_mat, f->no); + + for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) { + loops[i] = l_iter; + mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co); + } + + BLI_polyfill_calc_arena(projverts, f->len, 1, tris, pf_arena); + + if (use_beauty) { + BLI_polyfill_beautify(projverts, f->len, tris, pf_arena, pf_heap); + } + + BLI_memarena_clear(pf_arena); + } + + if (cd_loop_mdisp_offset != -1) { + BM_face_calc_center_median(f, f_center); + } + + /* loop over calculated triangles and create new geometry */ + for (i = 0; i < totfilltri; i++) { + BMLoop *l_tri[3] = {loops[tris[i][0]], loops[tris[i][1]], loops[tris[i][2]]}; + + BMVert *v_tri[3] = {l_tri[0]->v, l_tri[1]->v, l_tri[2]->v}; + + f_new = BM_face_create_verts(bm, v_tri, 3, f, BM_CREATE_NOP, true); + l_new = BM_FACE_FIRST_LOOP(f_new); + + BLI_assert(v_tri[0] == l_new->v); + + /* check for duplicate */ + if (l_new->radial_next != l_new) { + BMLoop *l_iter = l_new->radial_next; + do { + if (UNLIKELY((l_iter->f->len == 3) && (l_new->prev->v == l_iter->prev->v))) { + /* Check the last tri because we swap last f_new with f at the end... */ + BLI_linklist_prepend(r_faces_double, (i != last_tri) ? f_new : f); + break; + } + } while ((l_iter = l_iter->radial_next) != l_new); + } + + /* copy CD data */ + BM_elem_attrs_copy(bm, bm, l_tri[0], l_new); + BM_elem_attrs_copy(bm, bm, l_tri[1], l_new->next); + BM_elem_attrs_copy(bm, bm, l_tri[2], l_new->prev); + + /* add all but the last face which is swapped and removed (below) */ + if (i != last_tri) { + if (use_tag) { + BM_elem_flag_enable(f_new, BM_ELEM_TAG); + } + if (r_faces_new) { + r_faces_new[nf_i++] = f_new; + } + } + + if (use_tag || r_edges_new) { + /* new faces loops */ + BMLoop *l_iter; + + l_iter = l_first = l_new; + do { + BMEdge *e = l_iter->e; + /* confusing! if its not a boundary now, we know it will be later + * since this will be an edge of one of the new faces which we're in the middle of creating */ + bool is_new_edge = (l_iter == l_iter->radial_next); + + if (is_new_edge) { + if (use_tag) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + } + if (r_edges_new) { + r_edges_new[ne_i++] = e; + } + } + /* note, never disable tag's */ + } while ((l_iter = l_iter->next) != l_first); + } + + if (cd_loop_mdisp_offset != -1) { + float f_new_center[3]; + BM_face_calc_center_median(f_new, f_new_center); + BM_face_interp_multires_ex(bm, f_new, f, f_new_center, f_center, cd_loop_mdisp_offset); + } + } + + { + /* we can't delete the real face, because some of the callers expect it to remain valid. + * so swap data and delete the last created tri */ + bmesh_face_swap_data(f, f_new); + BM_face_kill(bm, f_new); + } + } + bm->elem_index_dirty |= BM_FACE; + + if (r_faces_new_tot) { + *r_faces_new_tot = nf_i; + } + + if (r_edges_new_tot) { + *r_edges_new_tot = ne_i; + } } /** @@ -1222,101 +1207,97 @@ void BM_face_triangulate( */ void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) { - float out[2] = {-FLT_MAX, -FLT_MAX}; - float center[2] = {0.0f, 0.0f}; - float axis_mat[3][3]; - float (*projverts)[2] = BLI_array_alloca(projverts, f->len); - const float *(*edgeverts)[2] = BLI_array_alloca(edgeverts, len); - BMLoop *l; - int i, i_prev, j; - - BLI_assert(BM_face_is_normal_valid(f)); - - axis_dominant_v3_to_m3(axis_mat, f->no); - - for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) { - mul_v2_m3v3(projverts[i], axis_mat, l->v->co); - add_v2_v2(center, projverts[i]); - } - - /* first test for completely convex face */ - if (is_poly_convex_v2(projverts, f->len)) { - return; - } - - mul_v2_fl(center, 1.0f / f->len); - - for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) { - BM_elem_index_set(l, i); /* set_dirty */ - - /* center the projection for maximum accuracy */ - sub_v2_v2(projverts[i], center); - - out[0] = max_ff(out[0], projverts[i][0]); - out[1] = max_ff(out[1], projverts[i][1]); - } - bm->elem_index_dirty |= BM_LOOP; - - /* ensure we are well outside the face bounds (value is arbitrary) */ - add_v2_fl(out, 1.0f); - - for (i = 0; i < len; i++) { - edgeverts[i][0] = projverts[BM_elem_index_get(loops[i][0])]; - edgeverts[i][1] = projverts[BM_elem_index_get(loops[i][1])]; - } - - /* do convexity test */ - for (i = 0; i < len; i++) { - float mid[2]; - mid_v2_v2v2(mid, edgeverts[i][0], edgeverts[i][1]); - - int isect = 0; - int j_prev; - for (j = 0, j_prev = f->len - 1; j < f->len; j_prev = j++) { - const float *f_edge[2] = {projverts[j_prev], projverts[j]}; - if (isect_seg_seg_v2(UNPACK2(f_edge), mid, out) == ISECT_LINE_LINE_CROSS) { - isect++; - } - } - - if (isect % 2 == 0) { - loops[i][0] = NULL; - } - } + float out[2] = {-FLT_MAX, -FLT_MAX}; + float center[2] = {0.0f, 0.0f}; + float axis_mat[3][3]; + float(*projverts)[2] = BLI_array_alloca(projverts, f->len); + const float *(*edgeverts)[2] = BLI_array_alloca(edgeverts, len); + BMLoop *l; + int i, i_prev, j; + + BLI_assert(BM_face_is_normal_valid(f)); + + axis_dominant_v3_to_m3(axis_mat, f->no); + + for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) { + mul_v2_m3v3(projverts[i], axis_mat, l->v->co); + add_v2_v2(center, projverts[i]); + } + + /* first test for completely convex face */ + if (is_poly_convex_v2(projverts, f->len)) { + return; + } + + mul_v2_fl(center, 1.0f / f->len); + + for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) { + BM_elem_index_set(l, i); /* set_dirty */ + + /* center the projection for maximum accuracy */ + sub_v2_v2(projverts[i], center); + + out[0] = max_ff(out[0], projverts[i][0]); + out[1] = max_ff(out[1], projverts[i][1]); + } + bm->elem_index_dirty |= BM_LOOP; + + /* ensure we are well outside the face bounds (value is arbitrary) */ + add_v2_fl(out, 1.0f); + + for (i = 0; i < len; i++) { + edgeverts[i][0] = projverts[BM_elem_index_get(loops[i][0])]; + edgeverts[i][1] = projverts[BM_elem_index_get(loops[i][1])]; + } + + /* do convexity test */ + for (i = 0; i < len; i++) { + float mid[2]; + mid_v2_v2v2(mid, edgeverts[i][0], edgeverts[i][1]); + + int isect = 0; + int j_prev; + for (j = 0, j_prev = f->len - 1; j < f->len; j_prev = j++) { + const float *f_edge[2] = {projverts[j_prev], projverts[j]}; + if (isect_seg_seg_v2(UNPACK2(f_edge), mid, out) == ISECT_LINE_LINE_CROSS) { + isect++; + } + } + + if (isect % 2 == 0) { + loops[i][0] = NULL; + } + } #define EDGE_SHARE_VERT(e1, e2) \ - ((ELEM((e1)[0], (e2)[0], (e2)[1])) || \ - (ELEM((e1)[1], (e2)[0], (e2)[1]))) - - /* do line crossing tests */ - for (i = 0, i_prev = f->len - 1; i < f->len; i_prev = i++) { - const float *f_edge[2] = {projverts[i_prev], projverts[i]}; - for (j = 0; j < len; j++) { - if ((loops[j][0] != NULL) && - !EDGE_SHARE_VERT(f_edge, edgeverts[j])) - { - if (isect_seg_seg_v2(UNPACK2(f_edge), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) { - loops[j][0] = NULL; - } - } - } - } - - /* self intersect tests */ - for (i = 0; i < len; i++) { - if (loops[i][0]) { - for (j = i + 1; j < len; j++) { - if ((loops[j][0] != NULL) && - !EDGE_SHARE_VERT(edgeverts[i], edgeverts[j])) - { - if (isect_seg_seg_v2(UNPACK2(edgeverts[i]), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) { - loops[i][0] = NULL; - break; - } - } - } - } - } + ((ELEM((e1)[0], (e2)[0], (e2)[1])) || (ELEM((e1)[1], (e2)[0], (e2)[1]))) + + /* do line crossing tests */ + for (i = 0, i_prev = f->len - 1; i < f->len; i_prev = i++) { + const float *f_edge[2] = {projverts[i_prev], projverts[i]}; + for (j = 0; j < len; j++) { + if ((loops[j][0] != NULL) && !EDGE_SHARE_VERT(f_edge, edgeverts[j])) { + if (isect_seg_seg_v2(UNPACK2(f_edge), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) { + loops[j][0] = NULL; + } + } + } + } + + /* self intersect tests */ + for (i = 0; i < len; i++) { + if (loops[i][0]) { + for (j = i + 1; j < len; j++) { + if ((loops[j][0] != NULL) && !EDGE_SHARE_VERT(edgeverts[i], edgeverts[j])) { + if (isect_seg_seg_v2(UNPACK2(edgeverts[i]), UNPACK2(edgeverts[j])) == + ISECT_LINE_LINE_CROSS) { + loops[i][0] = NULL; + break; + } + } + } + } + } #undef EDGE_SHARE_VERT } @@ -1327,14 +1308,15 @@ void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int l */ void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len) { - int i; - - for (i = 0; i < len; i++) { - BMLoop *l_a_dummy, *l_b_dummy; - if (f != BM_vert_pair_share_face_by_angle(loops[i][0]->v, loops[i][1]->v, &l_a_dummy, &l_b_dummy, false)) { - loops[i][0] = NULL; - } - } + int i; + + for (i = 0; i < len; i++) { + BMLoop *l_a_dummy, *l_b_dummy; + if (f != BM_vert_pair_share_face_by_angle( + loops[i][0]->v, loops[i][1]->v, &l_a_dummy, &l_b_dummy, false)) { + loops[i][0] = NULL; + } + } } /** @@ -1345,13 +1327,15 @@ void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len) */ void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]) { - BMLoop *l = BM_FACE_FIRST_LOOP(f); + BMLoop *l = BM_FACE_FIRST_LOOP(f); - BLI_assert(f->len == 3); + BLI_assert(f->len == 3); - r_verts[0] = l->v; l = l->next; - r_verts[1] = l->v; l = l->next; - r_verts[2] = l->v; + r_verts[0] = l->v; + l = l->next; + r_verts[1] = l->v; + l = l->next; + r_verts[2] = l->v; } /** @@ -1360,17 +1344,19 @@ void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]) */ void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) { - BMLoop *l = BM_FACE_FIRST_LOOP(f); + BMLoop *l = BM_FACE_FIRST_LOOP(f); - BLI_assert(f->len == 4); + BLI_assert(f->len == 4); - r_verts[0] = l->v; l = l->next; - r_verts[1] = l->v; l = l->next; - r_verts[2] = l->v; l = l->next; - r_verts[3] = l->v; + r_verts[0] = l->v; + l = l->next; + r_verts[1] = l->v; + l = l->next; + r_verts[2] = l->v; + l = l->next; + r_verts[3] = l->v; } - /** * Small utility functions for fast access * @@ -1379,13 +1365,15 @@ void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) */ void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3]) { - BMLoop *l = BM_FACE_FIRST_LOOP(f); + BMLoop *l = BM_FACE_FIRST_LOOP(f); - BLI_assert(f->len == 3); + BLI_assert(f->len == 3); - r_loops[0] = l; l = l->next; - r_loops[1] = l; l = l->next; - r_loops[2] = l; + r_loops[0] = l; + l = l->next; + r_loops[1] = l; + l = l->next; + r_loops[2] = l; } /** @@ -1394,17 +1382,19 @@ void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3]) */ void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4]) { - BMLoop *l = BM_FACE_FIRST_LOOP(f); + BMLoop *l = BM_FACE_FIRST_LOOP(f); - BLI_assert(f->len == 4); + BLI_assert(f->len == 4); - r_loops[0] = l; l = l->next; - r_loops[1] = l; l = l->next; - r_loops[2] = l; l = l->next; - r_loops[3] = l; + r_loops[0] = l; + l = l->next; + r_loops[1] = l; + l = l->next; + r_loops[2] = l; + l = l->next; + r_loops[3] = l; } - /** * \brief BM_mesh_calc_tessellation get the looptris and its number from a certain bmesh * \param looptris: @@ -1413,287 +1403,280 @@ void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4]) */ void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot) { - /* use this to avoid locking pthread for _every_ polygon - * and calling the fill function */ + /* use this to avoid locking pthread for _every_ polygon + * and calling the fill function */ #define USE_TESSFACE_SPEEDUP - /* this assumes all faces can be scan-filled, which isn't always true, - * worst case we over alloc a little which is acceptable */ + /* this assumes all faces can be scan-filled, which isn't always true, + * worst case we over alloc a little which is acceptable */ #ifndef NDEBUG - const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); + const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); #endif - BMIter iter; - BMFace *efa; - int i = 0; + BMIter iter; + BMFace *efa; + int i = 0; - MemArena *arena = NULL; + MemArena *arena = NULL; - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - /* don't consider two-edged faces */ - if (UNLIKELY(efa->len < 3)) { - /* do nothing */ - } + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + /* don't consider two-edged faces */ + if (UNLIKELY(efa->len < 3)) { + /* do nothing */ + } #ifdef USE_TESSFACE_SPEEDUP - /* no need to ensure the loop order, we know its ok */ - - else if (efa->len == 3) { -#if 0 - int j; - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) { - looptris[i][j] = l; - } - i += 1; -#else - /* more cryptic but faster */ - BMLoop *l; - BMLoop **l_ptr = looptris[i++]; - l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa); - l_ptr[1] = l = l->next; - l_ptr[2] = l->next; -#endif - } - else if (efa->len == 4) { -#if 0 - BMLoop *ltmp[4]; - int j; - BLI_array_grow_items(looptris, 2); - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) { - ltmp[j] = l; - } - - looptris[i][0] = ltmp[0]; - looptris[i][1] = ltmp[1]; - looptris[i][2] = ltmp[2]; - i += 1; - - looptris[i][0] = ltmp[0]; - looptris[i][1] = ltmp[2]; - looptris[i][2] = ltmp[3]; - i += 1; -#else - /* more cryptic but faster */ - BMLoop *l; - BMLoop **l_ptr_a = looptris[i++]; - BMLoop **l_ptr_b = looptris[i++]; - (l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa)); - (l_ptr_a[1] = l = l->next); - (l_ptr_a[2] = l_ptr_b[1] = l = l->next); - ( l_ptr_b[2] = l->next); -#endif - - if (UNLIKELY(is_quad_flip_v3_first_third_fast( - l_ptr_a[0]->v->co, - l_ptr_a[1]->v->co, - l_ptr_a[2]->v->co, - l_ptr_b[2]->v->co))) - { - /* flip out of degenerate 0-2 state. */ - l_ptr_a[2] = l_ptr_b[2]; - l_ptr_b[0] = l_ptr_a[1]; - } - } + /* no need to ensure the loop order, we know its ok */ + + else if (efa->len == 3) { +# if 0 + int j; + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) { + looptris[i][j] = l; + } + i += 1; +# else + /* more cryptic but faster */ + BMLoop *l; + BMLoop **l_ptr = looptris[i++]; + l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa); + l_ptr[1] = l = l->next; + l_ptr[2] = l->next; +# endif + } + else if (efa->len == 4) { +# if 0 + BMLoop *ltmp[4]; + int j; + BLI_array_grow_items(looptris, 2); + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) { + ltmp[j] = l; + } + + looptris[i][0] = ltmp[0]; + looptris[i][1] = ltmp[1]; + looptris[i][2] = ltmp[2]; + i += 1; + + looptris[i][0] = ltmp[0]; + looptris[i][1] = ltmp[2]; + looptris[i][2] = ltmp[3]; + i += 1; +# else + /* more cryptic but faster */ + BMLoop *l; + BMLoop **l_ptr_a = looptris[i++]; + BMLoop **l_ptr_b = looptris[i++]; + (l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa)); + (l_ptr_a[1] = l = l->next); + (l_ptr_a[2] = l_ptr_b[1] = l = l->next); + (l_ptr_b[2] = l->next); +# endif + + if (UNLIKELY(is_quad_flip_v3_first_third_fast( + l_ptr_a[0]->v->co, l_ptr_a[1]->v->co, l_ptr_a[2]->v->co, l_ptr_b[2]->v->co))) { + /* flip out of degenerate 0-2 state. */ + l_ptr_a[2] = l_ptr_b[2]; + l_ptr_b[0] = l_ptr_a[1]; + } + } #endif /* USE_TESSFACE_SPEEDUP */ - else { - int j; + else { + int j; - BMLoop *l_iter; - BMLoop *l_first; - BMLoop **l_arr; + BMLoop *l_iter; + BMLoop *l_first; + BMLoop **l_arr; - float axis_mat[3][3]; - float (*projverts)[2]; - uint (*tris)[3]; + float axis_mat[3][3]; + float(*projverts)[2]; + uint(*tris)[3]; - const int totfilltri = efa->len - 2; + const int totfilltri = efa->len - 2; - if (UNLIKELY(arena == NULL)) { - arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - } + if (UNLIKELY(arena == NULL)) { + arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + } - tris = BLI_memarena_alloc(arena, sizeof(*tris) * totfilltri); - l_arr = BLI_memarena_alloc(arena, sizeof(*l_arr) * efa->len); - projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * efa->len); + tris = BLI_memarena_alloc(arena, sizeof(*tris) * totfilltri); + l_arr = BLI_memarena_alloc(arena, sizeof(*l_arr) * efa->len); + projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * efa->len); - axis_dominant_v3_to_m3_negate(axis_mat, efa->no); + axis_dominant_v3_to_m3_negate(axis_mat, efa->no); - j = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - l_arr[j] = l_iter; - mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); - j++; - } while ((l_iter = l_iter->next) != l_first); + j = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + l_arr[j] = l_iter; + mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); + j++; + } while ((l_iter = l_iter->next) != l_first); - BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, arena); + BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, arena); - for (j = 0; j < totfilltri; j++) { - BMLoop **l_ptr = looptris[i++]; - uint *tri = tris[j]; + for (j = 0; j < totfilltri; j++) { + BMLoop **l_ptr = looptris[i++]; + uint *tri = tris[j]; - l_ptr[0] = l_arr[tri[0]]; - l_ptr[1] = l_arr[tri[1]]; - l_ptr[2] = l_arr[tri[2]]; - } + l_ptr[0] = l_arr[tri[0]]; + l_ptr[1] = l_arr[tri[1]]; + l_ptr[2] = l_arr[tri[2]]; + } - BLI_memarena_clear(arena); - } - } + BLI_memarena_clear(arena); + } + } - if (arena) { - BLI_memarena_free(arena); - arena = NULL; - } + if (arena) { + BLI_memarena_free(arena); + arena = NULL; + } - *r_looptris_tot = i; + *r_looptris_tot = i; - BLI_assert(i <= looptris_tot); + BLI_assert(i <= looptris_tot); #undef USE_TESSFACE_SPEEDUP - } - /** * A version of #BM_mesh_calc_tessellation that avoids degenerate triangles. */ void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot) { - /* this assumes all faces can be scan-filled, which isn't always true, - * worst case we over alloc a little which is acceptable */ + /* this assumes all faces can be scan-filled, which isn't always true, + * worst case we over alloc a little which is acceptable */ #ifndef NDEBUG - const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); + const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); #endif - BMIter iter; - BMFace *efa; - int i = 0; - - MemArena *pf_arena = NULL; - - /* use_beauty */ - Heap *pf_heap = NULL; - - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - /* don't consider two-edged faces */ - if (UNLIKELY(efa->len < 3)) { - /* do nothing */ - } - else if (efa->len == 3) { - BMLoop *l; - BMLoop **l_ptr = looptris[i++]; - l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa); - l_ptr[1] = l = l->next; - l_ptr[2] = l->next; - } - else if (efa->len == 4) { - BMLoop *l_v1 = BM_FACE_FIRST_LOOP(efa); - BMLoop *l_v2 = l_v1->next; - BMLoop *l_v3 = l_v2->next; - BMLoop *l_v4 = l_v1->prev; - - /* #BM_verts_calc_rotate_beauty performs excessive checks we don't need! - * It's meant for rotating edges, it also calculates a new normal. - * - * Use #BLI_polyfill_beautify_quad_rotate_calc since we have the normal. - */ + BMIter iter; + BMFace *efa; + int i = 0; + + MemArena *pf_arena = NULL; + + /* use_beauty */ + Heap *pf_heap = NULL; + + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + /* don't consider two-edged faces */ + if (UNLIKELY(efa->len < 3)) { + /* do nothing */ + } + else if (efa->len == 3) { + BMLoop *l; + BMLoop **l_ptr = looptris[i++]; + l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa); + l_ptr[1] = l = l->next; + l_ptr[2] = l->next; + } + else if (efa->len == 4) { + BMLoop *l_v1 = BM_FACE_FIRST_LOOP(efa); + BMLoop *l_v2 = l_v1->next; + BMLoop *l_v3 = l_v2->next; + BMLoop *l_v4 = l_v1->prev; + + /* #BM_verts_calc_rotate_beauty performs excessive checks we don't need! + * It's meant for rotating edges, it also calculates a new normal. + * + * Use #BLI_polyfill_beautify_quad_rotate_calc since we have the normal. + */ #if 0 - const bool split_13 = (BM_verts_calc_rotate_beauty( - l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) < 0.0f); + const bool split_13 = (BM_verts_calc_rotate_beauty( + l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) < 0.0f); #else - float axis_mat[3][3], v_quad[4][2]; - axis_dominant_v3_to_m3(axis_mat, efa->no); - mul_v2_m3v3(v_quad[0], axis_mat, l_v1->v->co); - mul_v2_m3v3(v_quad[1], axis_mat, l_v2->v->co); - mul_v2_m3v3(v_quad[2], axis_mat, l_v3->v->co); - mul_v2_m3v3(v_quad[3], axis_mat, l_v4->v->co); - - const bool split_13 = BLI_polyfill_beautify_quad_rotate_calc( - v_quad[0], v_quad[1], v_quad[2], v_quad[3]) < 0.0f; + float axis_mat[3][3], v_quad[4][2]; + axis_dominant_v3_to_m3(axis_mat, efa->no); + mul_v2_m3v3(v_quad[0], axis_mat, l_v1->v->co); + mul_v2_m3v3(v_quad[1], axis_mat, l_v2->v->co); + mul_v2_m3v3(v_quad[2], axis_mat, l_v3->v->co); + mul_v2_m3v3(v_quad[3], axis_mat, l_v4->v->co); + + const bool split_13 = BLI_polyfill_beautify_quad_rotate_calc( + v_quad[0], v_quad[1], v_quad[2], v_quad[3]) < 0.0f; #endif - BMLoop **l_ptr_a = looptris[i++]; - BMLoop **l_ptr_b = looptris[i++]; - if (split_13) { - l_ptr_a[0] = l_v1; - l_ptr_a[1] = l_v2; - l_ptr_a[2] = l_v3; - - l_ptr_b[0] = l_v1; - l_ptr_b[1] = l_v3; - l_ptr_b[2] = l_v4; - } - else { - l_ptr_a[0] = l_v1; - l_ptr_a[1] = l_v2; - l_ptr_a[2] = l_v4; - - l_ptr_b[0] = l_v2; - l_ptr_b[1] = l_v3; - l_ptr_b[2] = l_v4; - } - } - else { - int j; - - BMLoop *l_iter; - BMLoop *l_first; - BMLoop **l_arr; - - float axis_mat[3][3]; - float (*projverts)[2]; - unsigned int (*tris)[3]; - - const int totfilltri = efa->len - 2; - - if (UNLIKELY(pf_arena == NULL)) { - pf_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE); - } - - tris = BLI_memarena_alloc(pf_arena, sizeof(*tris) * totfilltri); - l_arr = BLI_memarena_alloc(pf_arena, sizeof(*l_arr) * efa->len); - projverts = BLI_memarena_alloc(pf_arena, sizeof(*projverts) * efa->len); - - axis_dominant_v3_to_m3_negate(axis_mat, efa->no); - - j = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - l_arr[j] = l_iter; - mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); - j++; - } while ((l_iter = l_iter->next) != l_first); - - BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, pf_arena); - - BLI_polyfill_beautify(projverts, efa->len, tris, pf_arena, pf_heap); - - for (j = 0; j < totfilltri; j++) { - BMLoop **l_ptr = looptris[i++]; - unsigned int *tri = tris[j]; - - l_ptr[0] = l_arr[tri[0]]; - l_ptr[1] = l_arr[tri[1]]; - l_ptr[2] = l_arr[tri[2]]; - } - - BLI_memarena_clear(pf_arena); - } - } - - if (pf_arena) { - BLI_memarena_free(pf_arena); - - BLI_heap_free(pf_heap, NULL); - } - - *r_looptris_tot = i; - - BLI_assert(i <= looptris_tot); - + BMLoop **l_ptr_a = looptris[i++]; + BMLoop **l_ptr_b = looptris[i++]; + if (split_13) { + l_ptr_a[0] = l_v1; + l_ptr_a[1] = l_v2; + l_ptr_a[2] = l_v3; + + l_ptr_b[0] = l_v1; + l_ptr_b[1] = l_v3; + l_ptr_b[2] = l_v4; + } + else { + l_ptr_a[0] = l_v1; + l_ptr_a[1] = l_v2; + l_ptr_a[2] = l_v4; + + l_ptr_b[0] = l_v2; + l_ptr_b[1] = l_v3; + l_ptr_b[2] = l_v4; + } + } + else { + int j; + + BMLoop *l_iter; + BMLoop *l_first; + BMLoop **l_arr; + + float axis_mat[3][3]; + float(*projverts)[2]; + unsigned int(*tris)[3]; + + const int totfilltri = efa->len - 2; + + if (UNLIKELY(pf_arena == NULL)) { + pf_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE); + } + + tris = BLI_memarena_alloc(pf_arena, sizeof(*tris) * totfilltri); + l_arr = BLI_memarena_alloc(pf_arena, sizeof(*l_arr) * efa->len); + projverts = BLI_memarena_alloc(pf_arena, sizeof(*projverts) * efa->len); + + axis_dominant_v3_to_m3_negate(axis_mat, efa->no); + + j = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + l_arr[j] = l_iter; + mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); + j++; + } while ((l_iter = l_iter->next) != l_first); + + BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, pf_arena); + + BLI_polyfill_beautify(projverts, efa->len, tris, pf_arena, pf_heap); + + for (j = 0; j < totfilltri; j++) { + BMLoop **l_ptr = looptris[i++]; + unsigned int *tri = tris[j]; + + l_ptr[0] = l_arr[tri[0]]; + l_ptr[1] = l_arr[tri[1]]; + l_ptr[2] = l_arr[tri[2]]; + } + + BLI_memarena_clear(pf_arena); + } + } + + if (pf_arena) { + BLI_memarena_free(pf_arena); + + BLI_heap_free(pf_heap, NULL); + } + + *r_looptris_tot = i; + + BLI_assert(i <= looptris_tot); } diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index ff93ce94c77..191ebd86f4a 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -25,67 +25,77 @@ struct Heap; #include "BLI_compiler_attrs.h" -void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot); -void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot); - -void BM_face_calc_tessellation( - const BMFace *f, const bool use_fixed_quad, - BMLoop **r_loops, uint (*r_index)[3]); -void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]); +void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot); +void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot); + +void BM_face_calc_tessellation(const BMFace *f, + const bool use_fixed_quad, + BMLoop **r_loops, + uint (*r_index)[3]); +void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]); float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL(); -float BM_face_calc_normal_vcos( - const BMesh *bm, const BMFace *f, float r_no[3], - float const (*vertexCos)[3]) ATTR_NONNULL(); -float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3]) ATTR_NONNULL(); +float BM_face_calc_normal_vcos(const BMesh *bm, + const BMFace *f, + float r_no[3], + float const (*vertexCos)[3]) ATTR_NONNULL(); +float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3]) + ATTR_NONNULL(); float BM_face_calc_area(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); float BM_face_calc_perimeter(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void BM_face_calc_tangent_edge(const BMFace *f, float r_plane[3]) ATTR_NONNULL(); -void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_plane[3]) ATTR_NONNULL(); -void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL(); -void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL(); -void BM_face_calc_tangent_auto(const BMFace *f, float r_plane[3]) ATTR_NONNULL(); -void BM_face_calc_center_bounds(const BMFace *f, float center[3]) ATTR_NONNULL(); -void BM_face_calc_center_median(const BMFace *f, float center[3]) ATTR_NONNULL(); -void BM_face_calc_center_median_vcos( - const BMesh *bm, const BMFace *f, float r_cent[3], - float const (*vertexCos)[3]) ATTR_NONNULL(); -void BM_face_calc_center_median_weighted(const BMFace *f, float center[3]) ATTR_NONNULL(); +float BM_face_calc_perimeter_with_mat3(const BMFace *f, + const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +void BM_face_calc_tangent_edge(const BMFace *f, float r_plane[3]) ATTR_NONNULL(); +void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_plane[3]) ATTR_NONNULL(); +void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL(); +void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL(); +void BM_face_calc_tangent_auto(const BMFace *f, float r_plane[3]) ATTR_NONNULL(); +void BM_face_calc_center_bounds(const BMFace *f, float center[3]) ATTR_NONNULL(); +void BM_face_calc_center_median(const BMFace *f, float center[3]) ATTR_NONNULL(); +void BM_face_calc_center_median_vcos(const BMesh *bm, + const BMFace *f, + float r_cent[3], + float const (*vertexCos)[3]) ATTR_NONNULL(); +void BM_face_calc_center_median_weighted(const BMFace *f, float center[3]) ATTR_NONNULL(); void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3]); -void BM_face_normal_update(BMFace *f) ATTR_NONNULL(); - -void BM_edge_normals_update(BMEdge *e) ATTR_NONNULL(); - -bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3]); -bool BM_vert_calc_normal(const BMVert *v, float r_no[3]); -void BM_vert_normal_update(BMVert *v) ATTR_NONNULL(); -void BM_vert_normal_update_all(BMVert *v) ATTR_NONNULL(); - -void BM_face_normal_flip_ex( - BMesh *bm, BMFace *f, - const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip) ATTR_NONNULL(); -void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL(); -bool BM_face_point_inside_test(const BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); - -void BM_face_triangulate( - BMesh *bm, BMFace *f, - BMFace **r_faces_new, - int *r_faces_new_tot, - BMEdge **r_edges_new, - int *r_edges_new_tot, - struct LinkNode **r_faces_double, - const int quad_method, const int ngon_method, - const bool use_tag, - struct MemArena *pf_arena, - struct Heap *pf_heap - ) ATTR_NONNULL(1, 2); - -void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL(); -void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL(); +void BM_face_normal_update(BMFace *f) ATTR_NONNULL(); + +void BM_edge_normals_update(BMEdge *e) ATTR_NONNULL(); + +bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3]); +bool BM_vert_calc_normal(const BMVert *v, float r_no[3]); +void BM_vert_normal_update(BMVert *v) ATTR_NONNULL(); +void BM_vert_normal_update_all(BMVert *v) ATTR_NONNULL(); + +void BM_face_normal_flip_ex(BMesh *bm, + BMFace *f, + const int cd_loop_mdisp_offset, + const bool use_loop_mdisp_flip) ATTR_NONNULL(); +void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL(); +bool BM_face_point_inside_test(const BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); + +void BM_face_triangulate(BMesh *bm, + BMFace *f, + BMFace **r_faces_new, + int *r_faces_new_tot, + BMEdge **r_edges_new, + int *r_edges_new_tot, + struct LinkNode **r_faces_double, + const int quad_method, + const int ngon_method, + const bool use_tag, + struct MemArena *pf_arena, + struct Heap *pf_heap) ATTR_NONNULL(1, 2); + +void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL(); +void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL(); void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]) ATTR_NONNULL(); void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) ATTR_NONNULL(); diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 76c0dcc1dfa..e2b117536f3 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -52,167 +52,169 @@ /* 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 +#define FACE_NET _FLAG_WALK /* edge is apart of the edge-net we're filling */ -#define EDGE_NET _FLAG_WALK +#define EDGE_NET _FLAG_WALK /* tag verts we've visit */ #define VERT_VISIT _FLAG_WALK #define VERT_IN_QUEUE _FLAG_WALK_ALT struct VertOrder { - float angle; - BMVert *v; + float angle; + BMVert *v; }; static uint bm_edge_flagged_radial_count(BMEdge *e) { - uint 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; + uint 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; + 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 void normalize_v2_m3_v3v3(float out[2], float axis_mat[3][3], const float v1[3], const float v2[3]) +static void normalize_v2_m3_v3v3(float out[2], + float axis_mat[3][3], + const float v1[3], + const float v2[3]) { - float dir[3]; - sub_v3_v3v3(dir, v1, v2); - mul_v2_m3v3(out, axis_mat, dir); - normalize_v2(out); + float dir[3]; + sub_v3_v3v3(dir, v1, v2); + mul_v2_m3v3(out, axis_mat, dir); + normalize_v2(out); } - /** * \note Be sure to update #bm_face_split_edgenet_find_loop_pair_exists * when making changed to edge picking logic. */ -static bool bm_face_split_edgenet_find_loop_pair( - BMVert *v_init, - const float face_normal[3], float face_normal_matrix[3][3], - BMEdge *e_pair[2]) +static bool bm_face_split_edgenet_find_loop_pair(BMVert *v_init, + const float face_normal[3], + float face_normal_matrix[3][3], + BMEdge *e_pair[2]) { - /* Always find one boundary edge (to determine winding) - * and one wire (if available), otherwise another boundary. - */ - - /* 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; - - { - BMEdge *e, *e_first; - e = e_first = v_init->e; - do { - if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) { - const uint 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++; - } - } - } while ((e = BM_DISK_EDGE_NEXT(e, v_init)) != e_first); - } - - /* first edge should always be boundary */ - if (edges_boundary_len == 0) { - return false; - } - e_pair[0] = BLI_SMALLSTACK_POP(edges_boundary); - - /* use to hold boundary OR wire edges */ - BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *); - - /* attempt one boundary and one wire, or 2 boundary */ - if (edges_wire_len == 0) { - if (edges_boundary_len > 1) { - e_pair[1] = BLI_SMALLSTACK_POP(edges_boundary); - - if (edges_boundary_len > 2) { - BLI_SMALLSTACK_SWAP(edges_search, edges_boundary); - } - } - else { - /* one boundary and no wire */ - return false; - } - } - else { - e_pair[1] = BLI_SMALLSTACK_POP(edges_wire); - if (edges_wire_len > 1) { - BLI_SMALLSTACK_SWAP(edges_search, edges_wire); - } - } - - /* if we swapped above, search this list for the best edge */ - if (!BLI_SMALLSTACK_IS_EMPTY(edges_search)) { - /* find the best edge in 'edge_list' to use for 'e_pair[1]' */ - const BMVert *v_prev = BM_edge_other_vert(e_pair[0], v_init); - const BMVert *v_next = BM_edge_other_vert(e_pair[1], v_init); - - float dir_prev[2], dir_next[2]; - - normalize_v2_m3_v3v3(dir_prev, face_normal_matrix, v_prev->co, v_init->co); - normalize_v2_m3_v3v3(dir_next, face_normal_matrix, v_next->co, v_init->co); - float angle_best_cos = dot_v2v2(dir_next, dir_prev); - - BMEdge *e; - while ((e = BLI_SMALLSTACK_POP(edges_search))) { - v_next = BM_edge_other_vert(e, v_init); - float dir_test[2]; - - normalize_v2_m3_v3v3(dir_test, face_normal_matrix, v_next->co, v_init->co); - const float angle_test_cos = dot_v2v2(dir_prev, dir_test); - - if (angle_test_cos > angle_best_cos) { - angle_best_cos = angle_test_cos; - 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; + /* Always find one boundary edge (to determine winding) + * and one wire (if available), otherwise another boundary. + */ + + /* 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; + + { + BMEdge *e, *e_first; + e = e_first = v_init->e; + do { + if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) { + const uint 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++; + } + } + } while ((e = BM_DISK_EDGE_NEXT(e, v_init)) != e_first); + } + + /* first edge should always be boundary */ + if (edges_boundary_len == 0) { + return false; + } + e_pair[0] = BLI_SMALLSTACK_POP(edges_boundary); + + /* use to hold boundary OR wire edges */ + BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *); + + /* attempt one boundary and one wire, or 2 boundary */ + if (edges_wire_len == 0) { + if (edges_boundary_len > 1) { + e_pair[1] = BLI_SMALLSTACK_POP(edges_boundary); + + if (edges_boundary_len > 2) { + BLI_SMALLSTACK_SWAP(edges_search, edges_boundary); + } + } + else { + /* one boundary and no wire */ + return false; + } + } + else { + e_pair[1] = BLI_SMALLSTACK_POP(edges_wire); + if (edges_wire_len > 1) { + BLI_SMALLSTACK_SWAP(edges_search, edges_wire); + } + } + + /* if we swapped above, search this list for the best edge */ + if (!BLI_SMALLSTACK_IS_EMPTY(edges_search)) { + /* find the best edge in 'edge_list' to use for 'e_pair[1]' */ + const BMVert *v_prev = BM_edge_other_vert(e_pair[0], v_init); + const BMVert *v_next = BM_edge_other_vert(e_pair[1], v_init); + + float dir_prev[2], dir_next[2]; + + normalize_v2_m3_v3v3(dir_prev, face_normal_matrix, v_prev->co, v_init->co); + normalize_v2_m3_v3v3(dir_next, face_normal_matrix, v_next->co, v_init->co); + float angle_best_cos = dot_v2v2(dir_next, dir_prev); + + BMEdge *e; + while ((e = BLI_SMALLSTACK_POP(edges_search))) { + v_next = BM_edge_other_vert(e, v_init); + float dir_test[2]; + + normalize_v2_m3_v3v3(dir_test, face_normal_matrix, v_next->co, v_init->co); + const float angle_test_cos = dot_v2v2(dir_prev, dir_test); + + if (angle_test_cos > angle_best_cos) { + angle_best_cos = angle_test_cos; + 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; } /** @@ -223,226 +225,233 @@ static bool bm_face_split_edgenet_find_loop_pair( * since between this check and running #bm_face_split_edgenet_find_loop, * the selected edges may have had faces attached. */ -static bool bm_face_split_edgenet_find_loop_pair_exists( - BMVert *v_init) +static bool bm_face_split_edgenet_find_loop_pair_exists(BMVert *v_init) { - int edges_boundary_len = 0; - int edges_wire_len = 0; - - { - BMEdge *e, *e_first; - e = e_first = v_init->e; - do { - if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) { - const uint count = bm_edge_flagged_radial_count(e); - if (count == 1) { - edges_boundary_len++; - } - else if (count == 0) { - edges_wire_len++; - } - } - } while ((e = BM_DISK_EDGE_NEXT(e, v_init)) != e_first); - } - - /* first edge should always be boundary */ - if (edges_boundary_len == 0) { - return false; - } - - /* attempt one boundary and one wire, or 2 boundary */ - if (edges_wire_len == 0) { - if (edges_boundary_len >= 2) { - /* pass */ - } - else { - /* one boundary and no wire */ - return false; - } - } - else { - /* pass */ - } - - return true; + int edges_boundary_len = 0; + int edges_wire_len = 0; + + { + BMEdge *e, *e_first; + e = e_first = v_init->e; + do { + if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) { + const uint count = bm_edge_flagged_radial_count(e); + if (count == 1) { + edges_boundary_len++; + } + else if (count == 0) { + edges_wire_len++; + } + } + } while ((e = BM_DISK_EDGE_NEXT(e, v_init)) != e_first); + } + + /* first edge should always be boundary */ + if (edges_boundary_len == 0) { + return false; + } + + /* attempt one boundary and one wire, or 2 boundary */ + if (edges_wire_len == 0) { + if (edges_boundary_len >= 2) { + /* pass */ + } + else { + /* one boundary and no wire */ + return false; + } + } + else { + /* pass */ + } + + 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 uint edge_order_len, - BMEdge *e_pair[2]) +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 uint 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 */ + /* 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; + BMVert *v; + BMVert *v_dst; + bool found = false; - struct VertOrder *eo; - STACK_DECLARE(edge_order); + 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 *); + /* 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 *); + /* 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); + 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); + /* 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); + 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)); + 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))) { + /* 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))) { #ifdef USE_FASTPATH_NOFORK -walk_nofork: + walk_nofork: #else - BLI_SMALLSTACK_PUSH(vert_visit, v); - BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT); + BLI_SMALLSTACK_PUSH(vert_visit, v); + BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT); #endif - BLI_assert(STACK_SIZE(edge_order) == 0); + BLI_assert(STACK_SIZE(edge_order) == 0); - /* check if we're done! */ - if (v == v_dst) { - found = true; - goto finally; - } + /* check if we're done! */ + if (v == v_dst) { + found = true; + goto finally; + } - BMEdge *e_next, *e_first; - e_first = v->e; - e_next = BM_DISK_EDGE_NEXT(e_first, v); /* always skip this verts edge */ + BMEdge *e_next, *e_first; + e_first = v->e; + e_next = BM_DISK_EDGE_NEXT(e_first, v); /* always skip this verts edge */ - /* in rare cases there may be edges with a single connecting vertex */ - if (e_next != e_first) { - do { - if ((BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) && - (bm_edge_flagged_radial_count(e_next) < 2)) - { - BMVert *v_next; + /* in rare cases there may be edges with a single connecting vertex */ + if (e_next != e_first) { + do { + if ((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); - BLI_assert(v->e != e_next); + v_next = BM_edge_other_vert(e_next, v); + BLI_assert(v->e != e_next); #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); - } + /* 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; + 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; - } - } - } while ((e_next = BM_DISK_EDGE_NEXT(e_next, v)) != e_first); - } + v_next->e = e_next; + } + } + } while ((e_next = BM_DISK_EDGE_NEXT(e_next, v)) != e_first); + } #ifdef USE_FASTPATH_NOFORK - if (STACK_SIZE(edge_order) == 1) { - eo = STACK_POP_PTR(edge_order); - v = eo->v; + if (STACK_SIZE(edge_order) == 1) { + eo = STACK_POP_PTR(edge_order); + v = eo->v; - goto walk_nofork; - } + goto walk_nofork; + } #endif - /* sort by angle if needed */ - if (STACK_SIZE(edge_order) > 1) { - uint j; - BMVert *v_prev = BM_edge_other_vert(v->e, v); + /* sort by angle if needed */ + if (STACK_SIZE(edge_order) > 1) { + uint 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); + 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); + /* 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); - } - } + 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); - } + /* clear flag for next execution */ + while ((v = BLI_SMALLSTACK_POP(vert_visit))) { + BM_ELEM_API_FLAG_DISABLE(v, VERT_VISIT); + } - return found; + return found; #undef USE_FASTPATH_NOFORK } -static bool bm_face_split_edgenet_find_loop( - BMVert *v_init, const float face_normal[3], float face_normal_matrix[3][3], - /* cache to avoid realloc every time */ - struct VertOrder *edge_order, const uint edge_order_len, - BMVert **r_face_verts, int *r_face_verts_len) +static bool bm_face_split_edgenet_find_loop(BMVert *v_init, + const float face_normal[3], + float face_normal_matrix[3][3], + /* cache to avoid realloc every time */ + struct VertOrder *edge_order, + const uint 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, face_normal_matrix, 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)) { - uint 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; - } + BMEdge *e_pair[2]; + BMVert *v; + + if (!bm_face_split_edgenet_find_loop_pair(v_init, face_normal, face_normal_matrix, 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)) { + uint 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; + } } /** @@ -453,237 +462,232 @@ static bool bm_face_split_edgenet_find_loop( * - 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) +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); + /* re-use for new face verts */ + BMVert **face_verts; + int face_verts_len; - BMVert **vert_queue; - STACK_DECLARE(vert_queue); - int i; + BMFace **face_arr = NULL; + BLI_array_declare(face_arr); - struct VertOrder *edge_order; - const uint edge_order_len = edge_net_len + 2; + BMVert **vert_queue; + STACK_DECLARE(vert_queue); + int i; - BMVert *v; + struct VertOrder *edge_order; + const uint edge_order_len = edge_net_len + 2; - BMLoop *l_iter, *l_first; + 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; - } + 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); + /* 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); + /* 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); + 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); + 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); + 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 - /* Note: 'VERT_IN_QUEUE' is often not needed at all, - * however in rare cases verts are added multiple times to the queue, - * that on it's own is harmless but in _very_ rare cases, - * the queue will overflow its maximum size, - * so we better be strict about this! see: T51539 */ - - for (i = 0; i < edge_net_len; i++) { - BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET); - BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_IN_QUEUE); - BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_IN_QUEUE); - } - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET); - BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_IN_QUEUE); - } while ((l_iter = l_iter->next) != l_first); - - float face_normal_matrix[3][3]; - axis_dominant_v3_to_m3(face_normal_matrix, f->no); - - - /* any vert can be used to begin with */ - STACK_PUSH(vert_queue, l_first->v); - BM_ELEM_API_FLAG_ENABLE(l_first->v, VERT_IN_QUEUE); - - while ((v = STACK_POP(vert_queue))) { - BM_ELEM_API_FLAG_DISABLE(v, VERT_IN_QUEUE); - if (bm_face_split_edgenet_find_loop( - v, f->no, face_normal_matrix, - 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) { - BLI_array_append(face_arr, f_new); - copy_v3_v3(f_new->no, f->no); - - /* warning, normally don't do this, - * its needed for mesh intersection - which tracks face-sides based on selection */ - f_new->head.hflag = f->head.hflag; - if (f->head.hflag & BM_ELEM_SELECT) { - bm->totfacesel++; - } - - 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); - do { - /* Avoid adding to queue multiple times (not common but happens). */ - if (!BM_ELEM_API_FLAG_TEST(l_iter->v, VERT_IN_QUEUE) && - bm_face_split_edgenet_find_loop_pair_exists(l_iter->v)) - { - STACK_PUSH(vert_queue, l_iter->v); - BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_IN_QUEUE); - } - } 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 ((void)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_len(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_len(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_len(face_arr); - } - else { - if (face_arr) { - MEM_freeN(face_arr); - } - } - - return true; + /* Note: 'VERT_IN_QUEUE' is often not needed at all, + * however in rare cases verts are added multiple times to the queue, + * that on it's own is harmless but in _very_ rare cases, + * the queue will overflow its maximum size, + * so we better be strict about this! see: T51539 */ + + for (i = 0; i < edge_net_len; i++) { + BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET); + BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_IN_QUEUE); + BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_IN_QUEUE); + } + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET); + BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_IN_QUEUE); + } while ((l_iter = l_iter->next) != l_first); + + float face_normal_matrix[3][3]; + axis_dominant_v3_to_m3(face_normal_matrix, f->no); + + /* any vert can be used to begin with */ + STACK_PUSH(vert_queue, l_first->v); + BM_ELEM_API_FLAG_ENABLE(l_first->v, VERT_IN_QUEUE); + + while ((v = STACK_POP(vert_queue))) { + BM_ELEM_API_FLAG_DISABLE(v, VERT_IN_QUEUE); + if (bm_face_split_edgenet_find_loop(v, + f->no, + face_normal_matrix, + 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) { + BLI_array_append(face_arr, f_new); + copy_v3_v3(f_new->no, f->no); + + /* warning, normally don't do this, + * its needed for mesh intersection - which tracks face-sides based on selection */ + f_new->head.hflag = f->head.hflag; + if (f->head.hflag & BM_ELEM_SELECT) { + bm->totfacesel++; + } + + 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); + do { + /* Avoid adding to queue multiple times (not common but happens). */ + if (!BM_ELEM_API_FLAG_TEST(l_iter->v, VERT_IN_QUEUE) && + bm_face_split_edgenet_find_loop_pair_exists(l_iter->v)) { + STACK_PUSH(vert_queue, l_iter->v); + BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_IN_QUEUE); + } + } 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 ((void)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_len(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_len(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_len(face_arr); + } + else { + if (face_arr) { + MEM_freeN(face_arr); + } + } + + return true; } #undef FACE_NET @@ -692,7 +696,6 @@ bool BM_face_split_edgenet( /** \} */ - /* -------------------------------------------------------------------- */ /* Face Split Edge-Net Connect Islands */ @@ -707,41 +710,41 @@ bool BM_face_split_edgenet( * * \{ */ - #define USE_PARTIAL_CONNECT - #define VERT_IS_VALID BM_ELEM_INTERNAL_TAG /* can be X or Y */ #define SORT_AXIS 0 -BLI_INLINE bool edge_isect_verts_point_2d( - const BMEdge *e, const BMVert *v_a, const BMVert *v_b, - float r_isect[2]) +BLI_INLINE bool edge_isect_verts_point_2d(const BMEdge *e, + const BMVert *v_a, + const BMVert *v_b, + float r_isect[2]) { - /* This bias seems like it could be too large, - * mostly its not needed, see T52329 for example where it is. */ - const float endpoint_bias = 1e-4f; - return ((isect_seg_seg_v2_point_ex(v_a->co, v_b->co, e->v1->co, e->v2->co, endpoint_bias, r_isect) == 1) && - ((e->v1 != v_a) && (e->v2 != v_a) && (e->v1 != v_b) && (e->v2 != v_b))); + /* This bias seems like it could be too large, + * mostly its not needed, see T52329 for example where it is. */ + const float endpoint_bias = 1e-4f; + return ((isect_seg_seg_v2_point_ex( + v_a->co, v_b->co, e->v1->co, e->v2->co, endpoint_bias, r_isect) == 1) && + ((e->v1 != v_a) && (e->v2 != v_a) && (e->v1 != v_b) && (e->v2 != v_b))); } BLI_INLINE int axis_pt_cmp(const float pt_a[2], const float pt_b[2]) { - if (pt_a[0] < pt_b[0]) { - return -1; - } - if (pt_a[0] > pt_b[0]) { - return 1; - } - if (pt_a[1] < pt_b[1]) { - return -1; - } - if (pt_a[1] > pt_b[1]) { - return 1; - } - return 0; + if (pt_a[0] < pt_b[0]) { + return -1; + } + if (pt_a[0] > pt_b[0]) { + return 1; + } + if (pt_a[1] < pt_b[1]) { + return -1; + } + if (pt_a[1] > pt_b[1]) { + return 1; + } + return 0; } /** @@ -750,106 +753,107 @@ BLI_INLINE int axis_pt_cmp(const float pt_a[2], const float pt_b[2]) * (edges remain in `edge_links`). */ struct EdgeGroupIsland { - LinkNode edge_links; /* keep first */ - uint vert_len, edge_len; - - /* Set the following vars once we have >1 groups */ - - /* when when an edge in a previous group connects to this one, - * so theres no need to create one pointing back. */ - uint has_prev_edge : 1; - - /* verts in the group which has the lowest & highest values, - * the lower vertex is connected to the first edge */ - struct { - BMVert *min, *max; - /* used for sorting only */ - float min_axis[2]; - float max_axis[2]; - } vert_span; + LinkNode edge_links; /* keep first */ + uint vert_len, edge_len; + + /* Set the following vars once we have >1 groups */ + + /* when when an edge in a previous group connects to this one, + * so theres no need to create one pointing back. */ + uint has_prev_edge : 1; + + /* verts in the group which has the lowest & highest values, + * the lower vertex is connected to the first edge */ + struct { + BMVert *min, *max; + /* used for sorting only */ + float min_axis[2]; + float max_axis[2]; + } vert_span; }; static int group_min_cmp_fn(const void *p1, const void *p2) { - const struct EdgeGroupIsland *g1 = *(struct EdgeGroupIsland **)p1; - const struct EdgeGroupIsland *g2 = *(struct EdgeGroupIsland **)p2; - /* min->co[SORT_AXIS] hasn't been applied yet */ - int test = axis_pt_cmp(g1->vert_span.min_axis, g2->vert_span.min_axis); - if (UNLIKELY(test == 0)) { - test = axis_pt_cmp(g1->vert_span.max_axis, g2->vert_span.max_axis); - } - return test; + const struct EdgeGroupIsland *g1 = *(struct EdgeGroupIsland **)p1; + const struct EdgeGroupIsland *g2 = *(struct EdgeGroupIsland **)p2; + /* min->co[SORT_AXIS] hasn't been applied yet */ + int test = axis_pt_cmp(g1->vert_span.min_axis, g2->vert_span.min_axis); + if (UNLIKELY(test == 0)) { + test = axis_pt_cmp(g1->vert_span.max_axis, g2->vert_span.max_axis); + } + return test; } struct Edges_VertVert_BVHTreeTest { - float dist_orig; - BMEdge **edge_arr; + float dist_orig; + BMEdge **edge_arr; - BMVert *v_origin; - BMVert *v_other; + BMVert *v_origin; + BMVert *v_other; - const uint *vert_range; + const uint *vert_range; }; struct Edges_VertRay_BVHTreeTest { - BMEdge **edge_arr; + BMEdge **edge_arr; - BMVert *v_origin; + BMVert *v_origin; - const uint *vert_range; + const uint *vert_range; }; -static void bvhtree_test_edges_isect_2d_vert_cb( - void *user_data, int index, const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit) +static void bvhtree_test_edges_isect_2d_vert_cb(void *user_data, + int index, + const BVHTreeRay *UNUSED(ray), + BVHTreeRayHit *hit) { - struct Edges_VertVert_BVHTreeTest *data = user_data; - const BMEdge *e = data->edge_arr[index]; - const int v1_index = BM_elem_index_get(e->v1); - float co_isect[2]; - - if (edge_isect_verts_point_2d(e, data->v_origin, data->v_other, co_isect)) { - const float t = line_point_factor_v2(co_isect, data->v_origin->co, data->v_other->co); - const float dist_new = data->dist_orig * t; - /* avoid float precision issues, possible this is greater, - * check above zero to allow some overlap - * (and needed for partial-connect which will overlap vertices) */ - if (LIKELY((dist_new < hit->dist) && (dist_new > 0.0f))) { - /* v1/v2 will both be in the same group */ - if (v1_index < (int)data->vert_range[0] || - v1_index >= (int)data->vert_range[1]) - { - hit->dist = dist_new; - hit->index = index; - } - } - } + struct Edges_VertVert_BVHTreeTest *data = user_data; + const BMEdge *e = data->edge_arr[index]; + const int v1_index = BM_elem_index_get(e->v1); + float co_isect[2]; + + if (edge_isect_verts_point_2d(e, data->v_origin, data->v_other, co_isect)) { + const float t = line_point_factor_v2(co_isect, data->v_origin->co, data->v_other->co); + const float dist_new = data->dist_orig * t; + /* avoid float precision issues, possible this is greater, + * check above zero to allow some overlap + * (and needed for partial-connect which will overlap vertices) */ + if (LIKELY((dist_new < hit->dist) && (dist_new > 0.0f))) { + /* v1/v2 will both be in the same group */ + if (v1_index < (int)data->vert_range[0] || v1_index >= (int)data->vert_range[1]) { + hit->dist = dist_new; + hit->index = index; + } + } + } } -static void bvhtree_test_edges_isect_2d_ray_cb( - void *user_data, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) +static void bvhtree_test_edges_isect_2d_ray_cb(void *user_data, + int index, + const BVHTreeRay *ray, + BVHTreeRayHit *hit) { - struct Edges_VertRay_BVHTreeTest *data = user_data; - const BMEdge *e = data->edge_arr[index]; - - /* direction is normalized, so this will be the distance */ - float dist_new; - if (isect_ray_seg_v2(data->v_origin->co, ray->direction, e->v1->co, e->v2->co, &dist_new, NULL)) { - /* avoid float precision issues, possible this is greater, - * check above zero to allow some overlap - * (and needed for partial-connect which will overlap vertices) */ - if (LIKELY(dist_new < hit->dist && (dist_new > 0.0f))) { - if (e->v1 != data->v_origin && e->v2 != data->v_origin) { - const int v1_index = BM_elem_index_get(e->v1); - /* v1/v2 will both be in the same group */ - if (v1_index < (int)data->vert_range[0] || - v1_index >= (int)data->vert_range[1]) - { - hit->dist = dist_new; - hit->index = index; - } - } - } - } + struct Edges_VertRay_BVHTreeTest *data = user_data; + const BMEdge *e = data->edge_arr[index]; + + /* direction is normalized, so this will be the distance */ + float dist_new; + if (isect_ray_seg_v2( + data->v_origin->co, ray->direction, e->v1->co, e->v2->co, &dist_new, NULL)) { + /* avoid float precision issues, possible this is greater, + * check above zero to allow some overlap + * (and needed for partial-connect which will overlap vertices) */ + if (LIKELY(dist_new < hit->dist && (dist_new > 0.0f))) { + if (e->v1 != data->v_origin && e->v2 != data->v_origin) { + const int v1_index = BM_elem_index_get(e->v1); + /* v1/v2 will both be in the same group */ + if (v1_index < (int)data->vert_range[0] || v1_index >= (int)data->vert_range[1]) { + hit->dist = dist_new; + hit->index = index; + } + } + } + } } /** @@ -859,186 +863,193 @@ static void bvhtree_test_edges_isect_2d_ray_cb( * ... which don't change each call. */ struct EdgeGroup_FindConnection_Args { - BVHTree *bvhtree; - BMEdge **edge_arr; - uint edge_arr_len; + BVHTree *bvhtree; + BMEdge **edge_arr; + uint edge_arr_len; - BMEdge **edge_arr_new; - uint edge_arr_new_len; + BMEdge **edge_arr_new; + uint edge_arr_new_len; - const uint *vert_range; + const uint *vert_range; }; -static BMEdge *test_edges_isect_2d_vert( - const struct EdgeGroup_FindConnection_Args *args, - BMVert *v_origin, BMVert *v_other) +static BMEdge *test_edges_isect_2d_vert(const struct EdgeGroup_FindConnection_Args *args, + BMVert *v_origin, + BMVert *v_other) { - int index; - - BVHTreeRayHit hit = {0}; - float dir[3]; - - sub_v2_v2v2(dir, v_other->co, v_origin->co); - dir[2] = 0.0f; - hit.index = -1; - hit.dist = normalize_v2(dir); - - struct Edges_VertVert_BVHTreeTest user_data = {0}; - user_data.dist_orig = hit.dist; - user_data.edge_arr = args->edge_arr; - user_data.v_origin = v_origin; - user_data.v_other = v_other; - user_data.vert_range = args->vert_range; - - index = BLI_bvhtree_ray_cast_ex( - args->bvhtree, v_origin->co, dir, 0.0f, &hit, - bvhtree_test_edges_isect_2d_vert_cb, &user_data, 0); - - BMEdge *e_hit = (index != -1) ? args->edge_arr[index] : NULL; - - /* check existing connections (no spatial optimization here since we're continually adding). */ - if (LIKELY(index == -1)) { - float t_best = 1.0f; - for (uint i = 0; i < args->edge_arr_new_len; i++) { - float co_isect[2]; - if (UNLIKELY(edge_isect_verts_point_2d(args->edge_arr_new[i], v_origin, v_other, co_isect))) { - const float t_test = line_point_factor_v2(co_isect, v_origin->co, v_other->co); - if (t_test < t_best) { - t_best = t_test; - - e_hit = args->edge_arr_new[i]; - } - } - } - } - - return e_hit; + int index; + + BVHTreeRayHit hit = {0}; + float dir[3]; + + sub_v2_v2v2(dir, v_other->co, v_origin->co); + dir[2] = 0.0f; + hit.index = -1; + hit.dist = normalize_v2(dir); + + struct Edges_VertVert_BVHTreeTest user_data = {0}; + user_data.dist_orig = hit.dist; + user_data.edge_arr = args->edge_arr; + user_data.v_origin = v_origin; + user_data.v_other = v_other; + user_data.vert_range = args->vert_range; + + index = BLI_bvhtree_ray_cast_ex(args->bvhtree, + v_origin->co, + dir, + 0.0f, + &hit, + bvhtree_test_edges_isect_2d_vert_cb, + &user_data, + 0); + + BMEdge *e_hit = (index != -1) ? args->edge_arr[index] : NULL; + + /* check existing connections (no spatial optimization here since we're continually adding). */ + if (LIKELY(index == -1)) { + float t_best = 1.0f; + for (uint i = 0; i < args->edge_arr_new_len; i++) { + float co_isect[2]; + if (UNLIKELY( + edge_isect_verts_point_2d(args->edge_arr_new[i], v_origin, v_other, co_isect))) { + const float t_test = line_point_factor_v2(co_isect, v_origin->co, v_other->co); + if (t_test < t_best) { + t_best = t_test; + + e_hit = args->edge_arr_new[i]; + } + } + } + } + + return e_hit; } /** * Similar to #test_edges_isect_2d_vert but we're casting into a direction, * (not to a vertex) */ -static BMEdge *test_edges_isect_2d_ray( - const struct EdgeGroup_FindConnection_Args *args, - BMVert *v_origin, const float dir[3]) +static BMEdge *test_edges_isect_2d_ray(const struct EdgeGroup_FindConnection_Args *args, + BMVert *v_origin, + const float dir[3]) { - int index; - BVHTreeRayHit hit = {0}; - - BLI_ASSERT_UNIT_V2(dir); - - hit.index = -1; - hit.dist = BVH_RAYCAST_DIST_MAX; - - struct Edges_VertRay_BVHTreeTest user_data = {0}; - user_data.edge_arr = args->edge_arr; - user_data.v_origin = v_origin; - user_data.vert_range = args->vert_range; - - index = BLI_bvhtree_ray_cast_ex( - args->bvhtree, v_origin->co, dir, 0.0f, &hit, - bvhtree_test_edges_isect_2d_ray_cb, &user_data, 0); - - BMEdge *e_hit = (index != -1) ? args->edge_arr[index] : NULL; - - /* check existing connections (no spatial optimization here since we're continually adding). */ - if (LIKELY(index != -1)) { - for (uint i = 0; i < args->edge_arr_new_len; i++) { - BMEdge *e = args->edge_arr_new[i]; - float dist_new; - if (isect_ray_seg_v2(v_origin->co, dir, e->v1->co, e->v2->co, &dist_new, NULL)) { - if (e->v1 != v_origin && e->v2 != v_origin) { - /* avoid float precision issues, possible this is greater */ - if (LIKELY(dist_new < hit.dist)) { - hit.dist = dist_new; - - e_hit = args->edge_arr_new[i]; - } - } - } - } - } - - return e_hit; + int index; + BVHTreeRayHit hit = {0}; + + BLI_ASSERT_UNIT_V2(dir); + + hit.index = -1; + hit.dist = BVH_RAYCAST_DIST_MAX; + + struct Edges_VertRay_BVHTreeTest user_data = {0}; + user_data.edge_arr = args->edge_arr; + user_data.v_origin = v_origin; + user_data.vert_range = args->vert_range; + + index = BLI_bvhtree_ray_cast_ex(args->bvhtree, + v_origin->co, + dir, + 0.0f, + &hit, + bvhtree_test_edges_isect_2d_ray_cb, + &user_data, + 0); + + BMEdge *e_hit = (index != -1) ? args->edge_arr[index] : NULL; + + /* check existing connections (no spatial optimization here since we're continually adding). */ + if (LIKELY(index != -1)) { + for (uint i = 0; i < args->edge_arr_new_len; i++) { + BMEdge *e = args->edge_arr_new[i]; + float dist_new; + if (isect_ray_seg_v2(v_origin->co, dir, e->v1->co, e->v2->co, &dist_new, NULL)) { + if (e->v1 != v_origin && e->v2 != v_origin) { + /* avoid float precision issues, possible this is greater */ + if (LIKELY(dist_new < hit.dist)) { + hit.dist = dist_new; + + e_hit = args->edge_arr_new[i]; + } + } + } + } + } + + return e_hit; } -static int bm_face_split_edgenet_find_connection( - const struct EdgeGroup_FindConnection_Args *args, - BMVert *v_origin, - /* false = negative, true = positive */ - bool direction_sign) +static int bm_face_split_edgenet_find_connection(const struct EdgeGroup_FindConnection_Args *args, + BMVert *v_origin, + /* false = negative, true = positive */ + bool direction_sign) { - /** - * Method for finding connection is as follows: - * - * - Cast a ray along either the positive or negative directions. - * - Take the hit-edge, and cast rays to their vertices checking those rays don't intersect a closer edge. - * - Keep taking the hit-edge and testing its verts until a vertex is found which isn't blocked by an edge. - * - * \note It's possible none of the verts can be accessed (with self-intersecting lines). - * In that case theres no right answer (without subdividing edges), - * so return a fall-back vertex in that case. - */ - - const float dir[3] = {[SORT_AXIS] = direction_sign ? 1.0f : -1.0f}; - BMEdge *e_hit = test_edges_isect_2d_ray(args, v_origin, dir); - BMVert *v_other = NULL; - - if (e_hit) { - BMVert *v_other_fallback = NULL; - - BLI_SMALLSTACK_DECLARE(vert_search, BMVert *); - - /* ensure we never add verts multiple times (not all that likely - but possible) */ - BLI_SMALLSTACK_DECLARE(vert_blacklist, BMVert *); - - do { - BMVert *v_pair[2]; - /* ensure the closest vertex is popped back off the stack first */ - if (len_squared_v2v2(v_origin->co, e_hit->v1->co) > - len_squared_v2v2(v_origin->co, e_hit->v2->co)) - { - ARRAY_SET_ITEMS(v_pair, e_hit->v1, e_hit->v2); - } - else { - ARRAY_SET_ITEMS(v_pair, e_hit->v2, e_hit->v1); - } - - for (int j = 0; j < 2; j++) { - BMVert *v_iter = v_pair[j]; - if (BM_elem_flag_test(v_iter, VERT_IS_VALID)) { - if (direction_sign ? (v_iter->co[SORT_AXIS] > v_origin->co[SORT_AXIS]) : - (v_iter->co[SORT_AXIS] < v_origin->co[SORT_AXIS])) - { - BLI_SMALLSTACK_PUSH(vert_search, v_iter); - BLI_SMALLSTACK_PUSH(vert_blacklist, v_iter); - BM_elem_flag_disable(v_iter, VERT_IS_VALID); - } - } - } - v_other_fallback = v_other; - - } while ((v_other = BLI_SMALLSTACK_POP(vert_search)) && - (e_hit = test_edges_isect_2d_vert(args, v_origin, v_other))); - - if (v_other == NULL) { - printf("Using fallback\n"); - v_other = v_other_fallback; - } - - /* reset the blacklist flag, for future use */ - BMVert *v; - while ((v = BLI_SMALLSTACK_POP(vert_blacklist))) { - BM_elem_flag_enable(v, VERT_IS_VALID); - } - } - - /* if we reach this line, v_other is either the best vertex or its NULL */ - return v_other ? BM_elem_index_get(v_other) : -1; + /** + * Method for finding connection is as follows: + * + * - Cast a ray along either the positive or negative directions. + * - Take the hit-edge, and cast rays to their vertices checking those rays don't intersect a closer edge. + * - Keep taking the hit-edge and testing its verts until a vertex is found which isn't blocked by an edge. + * + * \note It's possible none of the verts can be accessed (with self-intersecting lines). + * In that case theres no right answer (without subdividing edges), + * so return a fall-back vertex in that case. + */ + + const float dir[3] = {[SORT_AXIS] = direction_sign ? 1.0f : -1.0f}; + BMEdge *e_hit = test_edges_isect_2d_ray(args, v_origin, dir); + BMVert *v_other = NULL; + + if (e_hit) { + BMVert *v_other_fallback = NULL; + + BLI_SMALLSTACK_DECLARE(vert_search, BMVert *); + + /* ensure we never add verts multiple times (not all that likely - but possible) */ + BLI_SMALLSTACK_DECLARE(vert_blacklist, BMVert *); + + do { + BMVert *v_pair[2]; + /* ensure the closest vertex is popped back off the stack first */ + if (len_squared_v2v2(v_origin->co, e_hit->v1->co) > + len_squared_v2v2(v_origin->co, e_hit->v2->co)) { + ARRAY_SET_ITEMS(v_pair, e_hit->v1, e_hit->v2); + } + else { + ARRAY_SET_ITEMS(v_pair, e_hit->v2, e_hit->v1); + } + + for (int j = 0; j < 2; j++) { + BMVert *v_iter = v_pair[j]; + if (BM_elem_flag_test(v_iter, VERT_IS_VALID)) { + if (direction_sign ? (v_iter->co[SORT_AXIS] > v_origin->co[SORT_AXIS]) : + (v_iter->co[SORT_AXIS] < v_origin->co[SORT_AXIS])) { + BLI_SMALLSTACK_PUSH(vert_search, v_iter); + BLI_SMALLSTACK_PUSH(vert_blacklist, v_iter); + BM_elem_flag_disable(v_iter, VERT_IS_VALID); + } + } + } + v_other_fallback = v_other; + + } while ((v_other = BLI_SMALLSTACK_POP(vert_search)) && + (e_hit = test_edges_isect_2d_vert(args, v_origin, v_other))); + + if (v_other == NULL) { + printf("Using fallback\n"); + v_other = v_other_fallback; + } + + /* reset the blacklist flag, for future use */ + BMVert *v; + while ((v = BLI_SMALLSTACK_POP(vert_blacklist))) { + BM_elem_flag_enable(v, VERT_IS_VALID); + } + } + + /* if we reach this line, v_other is either the best vertex or its NULL */ + return v_other ? BM_elem_index_get(v_other) : -1; } - /** * Support for connecting islands that have single-edge connections. * This options is not very optimal (however its not needed for booleans either). @@ -1051,8 +1062,8 @@ static int bm_face_split_edgenet_find_connection( */ static bool test_tagged_and_notface(BMEdge *e, void *fptr) { - BMFace *f = (BMFace *)fptr; - return BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) && !BM_edge_in_face(e, f); + BMFace *f = (BMFace *)fptr; + return BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) && !BM_edge_in_face(e, f); } /** @@ -1064,148 +1075,144 @@ static bool test_tagged_and_notface(BMEdge *e, void *fptr) */ static BMVert *bm_face_split_edgenet_partial_connect(BMesh *bm, BMVert *v_delimit, BMFace *f) { - /* -------------------------------------------------------------------- */ - /* Initial check that we may be a delimiting vert (keep this fast) */ - - /* initial check - see if we have 3+ flagged edges attached to 'v_delimit' - * if not, we can early exit */ - LinkNode *e_delimit_list = NULL; - uint e_delimit_list_len = 0; - -#define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG -#define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG - -#define FOREACH_VERT_EDGE(v_, e_, body_) { \ - BMEdge *e_ = v_->e; \ - do { body_ } while ((e_ = BM_DISK_EDGE_NEXT(e_, v_)) != v_->e); \ -} ((void)0) - - /* start with face edges, since we need to split away wire-only edges */ - BMEdge *e_face_init = NULL; - - FOREACH_VERT_EDGE(v_delimit, e_iter, { - if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) { - BLI_assert(BM_elem_flag_test(BM_edge_other_vert(e_iter, v_delimit), VERT_NOT_IN_STACK)); - BLI_linklist_prepend_alloca(&e_delimit_list, e_iter); - e_delimit_list_len++; - if (e_iter->l != NULL && BM_edge_in_face(e_iter, f)) { - e_face_init = e_iter; - } - } - }); - - /* skip typical edge-chain verts */ - if (LIKELY(e_delimit_list_len <= 2)) { - return NULL; - } - - - /* -------------------------------------------------------------------- */ - /* Complicated stuff starts now! */ - - - /* Store connected vertices for restoring the flag */ - LinkNode *vert_stack = NULL; - BLI_linklist_prepend_alloca(&vert_stack, v_delimit); - BM_elem_flag_disable(v_delimit, VERT_NOT_IN_STACK); - - /* Walk the net... */ - { - BLI_SMALLSTACK_DECLARE(search, BMVert *); - BMVert *v_other = BM_edge_other_vert(e_face_init ? e_face_init : v_delimit->e, v_delimit); - - BLI_SMALLSTACK_PUSH(search, v_other); - BM_elem_flag_disable(v_other, VERT_NOT_IN_STACK); - - while ((v_other = BLI_SMALLSTACK_POP(search))) { - BLI_assert(BM_elem_flag_test(v_other, VERT_NOT_IN_STACK) == false); - BLI_linklist_prepend_alloca(&vert_stack, v_other); - BMEdge *e_iter = v_other->e; - do { - BMVert *v_step = BM_edge_other_vert(e_iter, v_other); - if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) { - if (BM_elem_flag_test(v_step, VERT_NOT_IN_STACK)) { - BM_elem_flag_disable(v_step, VERT_NOT_IN_STACK); - BLI_SMALLSTACK_PUSH(search, v_step); - } - } - } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_other)) != v_other->e); - } - } - - /* Detect if this is a delimiter by checking if we didn't walk any of edges connected to 'v_delimit' */ - bool is_delimit = false; - FOREACH_VERT_EDGE(v_delimit, e_iter, { - BMVert *v_step = BM_edge_other_vert(e_iter, v_delimit); - if (BM_elem_flag_test(v_step, VERT_NOT_IN_STACK) && !BM_edge_in_face(e_iter, f)) { - is_delimit = true; /* if one vertex is valid - we have a mix */ - } - else { - /* match the vertex flag (only for edges around 'v_delimit') */ - BM_elem_flag_disable(e_iter, EDGE_NOT_IN_STACK); - } - }); - -#undef FOREACH_VERT_EDGE - - /* Execute the split */ - BMVert *v_split = NULL; - if (is_delimit) { - v_split = BM_vert_create(bm, v_delimit->co, NULL, 0); - BM_vert_separate_tested_edges(bm, v_split, v_delimit, test_tagged_and_notface, f); - BM_elem_flag_enable(v_split, VERT_NOT_IN_STACK); - - BLI_assert(v_delimit->e != NULL); - - /* Degenerate, avoid eternal loop, see: T59074. */ -#if 0 - BLI_assert(v_split->e != NULL); -#else - if (UNLIKELY(v_split->e == NULL)) { - BM_vert_kill(bm, v_split); - v_split = NULL; - } -#endif - } - - /* Restore flags */ - do { - BM_elem_flag_enable((BMVert *)vert_stack->link, VERT_NOT_IN_STACK); - } while ((vert_stack = vert_stack->next)); - - do { - BM_elem_flag_enable((BMEdge *)e_delimit_list->link, EDGE_NOT_IN_STACK); - } while ((e_delimit_list = e_delimit_list->next)); - -#undef EDGE_NOT_IN_STACK -#undef VERT_NOT_IN_STACK - - return v_split; + /* -------------------------------------------------------------------- */ + /* Initial check that we may be a delimiting vert (keep this fast) */ + + /* initial check - see if we have 3+ flagged edges attached to 'v_delimit' + * if not, we can early exit */ + LinkNode *e_delimit_list = NULL; + uint e_delimit_list_len = 0; + +# define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG +# define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG + +# define FOREACH_VERT_EDGE(v_, e_, body_) \ + { \ + BMEdge *e_ = v_->e; \ + do { \ + body_ \ + } while ((e_ = BM_DISK_EDGE_NEXT(e_, v_)) != v_->e); \ + } \ + ((void)0) + + /* start with face edges, since we need to split away wire-only edges */ + BMEdge *e_face_init = NULL; + + FOREACH_VERT_EDGE(v_delimit, e_iter, { + if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) { + BLI_assert(BM_elem_flag_test(BM_edge_other_vert(e_iter, v_delimit), VERT_NOT_IN_STACK)); + BLI_linklist_prepend_alloca(&e_delimit_list, e_iter); + e_delimit_list_len++; + if (e_iter->l != NULL && BM_edge_in_face(e_iter, f)) { + e_face_init = e_iter; + } + } + }); + + /* skip typical edge-chain verts */ + if (LIKELY(e_delimit_list_len <= 2)) { + return NULL; + } + + /* -------------------------------------------------------------------- */ + /* Complicated stuff starts now! */ + + /* Store connected vertices for restoring the flag */ + LinkNode *vert_stack = NULL; + BLI_linklist_prepend_alloca(&vert_stack, v_delimit); + BM_elem_flag_disable(v_delimit, VERT_NOT_IN_STACK); + + /* Walk the net... */ + { + BLI_SMALLSTACK_DECLARE(search, BMVert *); + BMVert *v_other = BM_edge_other_vert(e_face_init ? e_face_init : v_delimit->e, v_delimit); + + BLI_SMALLSTACK_PUSH(search, v_other); + BM_elem_flag_disable(v_other, VERT_NOT_IN_STACK); + + while ((v_other = BLI_SMALLSTACK_POP(search))) { + BLI_assert(BM_elem_flag_test(v_other, VERT_NOT_IN_STACK) == false); + BLI_linklist_prepend_alloca(&vert_stack, v_other); + BMEdge *e_iter = v_other->e; + do { + BMVert *v_step = BM_edge_other_vert(e_iter, v_other); + if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) { + if (BM_elem_flag_test(v_step, VERT_NOT_IN_STACK)) { + BM_elem_flag_disable(v_step, VERT_NOT_IN_STACK); + BLI_SMALLSTACK_PUSH(search, v_step); + } + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_other)) != v_other->e); + } + } + + /* Detect if this is a delimiter by checking if we didn't walk any of edges connected to 'v_delimit' */ + bool is_delimit = false; + FOREACH_VERT_EDGE(v_delimit, e_iter, { + BMVert *v_step = BM_edge_other_vert(e_iter, v_delimit); + if (BM_elem_flag_test(v_step, VERT_NOT_IN_STACK) && !BM_edge_in_face(e_iter, f)) { + is_delimit = true; /* if one vertex is valid - we have a mix */ + } + else { + /* match the vertex flag (only for edges around 'v_delimit') */ + BM_elem_flag_disable(e_iter, EDGE_NOT_IN_STACK); + } + }); + +# undef FOREACH_VERT_EDGE + + /* Execute the split */ + BMVert *v_split = NULL; + if (is_delimit) { + v_split = BM_vert_create(bm, v_delimit->co, NULL, 0); + BM_vert_separate_tested_edges(bm, v_split, v_delimit, test_tagged_and_notface, f); + BM_elem_flag_enable(v_split, VERT_NOT_IN_STACK); + + BLI_assert(v_delimit->e != NULL); + + /* Degenerate, avoid eternal loop, see: T59074. */ +# if 0 + BLI_assert(v_split->e != NULL); +# else + if (UNLIKELY(v_split->e == NULL)) { + BM_vert_kill(bm, v_split); + v_split = NULL; + } +# endif + } + + /* Restore flags */ + do { + BM_elem_flag_enable((BMVert *)vert_stack->link, VERT_NOT_IN_STACK); + } while ((vert_stack = vert_stack->next)); + + do { + BM_elem_flag_enable((BMEdge *)e_delimit_list->link, EDGE_NOT_IN_STACK); + } while ((e_delimit_list = e_delimit_list->next)); + +# undef EDGE_NOT_IN_STACK +# undef VERT_NOT_IN_STACK + + return v_split; } - /** * Check if connecting vertices would cause an edge with duplicate verts. */ -static bool bm_vert_partial_connect_check_overlap( - const int *remap, - const int v_a_index, const int v_b_index) +static bool bm_vert_partial_connect_check_overlap(const int *remap, + const int v_a_index, + const int v_b_index) { - /* connected to eachother */ - if (UNLIKELY((remap[v_a_index] == v_b_index) || - (remap[v_b_index] == v_a_index))) - { - return true; - } - else { - return false; - } + /* connected to eachother */ + if (UNLIKELY((remap[v_a_index] == v_b_index) || (remap[v_b_index] == v_a_index))) { + return true; + } + else { + return false; + } } - -#endif /* USE_PARTIAL_CONNECT */ - - +#endif /* USE_PARTIAL_CONNECT */ /** * For when the edge-net has holes in it-this connects them. @@ -1215,476 +1222,470 @@ static bool bm_vert_partial_connect_check_overlap( * \param mem_arena: Avoids many small allocs & should be cleared after each use. * take care since \a r_edge_net_new is stored in \a r_edge_net_new. */ -bool BM_face_split_edgenet_connect_islands( - BMesh *bm, - BMFace *f, BMEdge **edge_net_init, const uint edge_net_init_len, - bool use_partial_connect, - MemArena *mem_arena, - BMEdge ***r_edge_net_new, uint *r_edge_net_new_len) +bool BM_face_split_edgenet_connect_islands(BMesh *bm, + BMFace *f, + BMEdge **edge_net_init, + const uint edge_net_init_len, + bool use_partial_connect, + MemArena *mem_arena, + BMEdge ***r_edge_net_new, + uint *r_edge_net_new_len) { - /* -------------------------------------------------------------------- */ - /* This function has 2 main parts. - * - * - Check if there are any holes. - * - Connect the holes with edges (if any are found). - * - * Keep the first part fast since it will run very often for edge-nets that have no holes. - * - * \note Don't use the mem_arena unless he have holes to fill. - * (avoid thrashing the area when the initial check isn't so intensive on the stack). - */ - - const uint edge_arr_len = (uint)edge_net_init_len + (uint)f->len; - BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len); - bool ok = false; - uint edge_net_new_len = (uint)edge_net_init_len; - - memcpy(edge_arr, edge_net_init, sizeof(*edge_arr) * (size_t)edge_net_init_len); - - /* _must_ clear on exit */ -#define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG -#define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG - - { - uint i = edge_net_init_len; - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BLI_assert(!BM_elem_flag_test(l_iter->v, VERT_NOT_IN_STACK)); - BLI_assert(!BM_elem_flag_test(l_iter->e, EDGE_NOT_IN_STACK)); - edge_arr[i++] = l_iter->e; - } while ((l_iter = l_iter->next) != l_first); - BLI_assert(i == edge_arr_len); - } - - for (uint i = 0; i < edge_arr_len; i++) { - BM_elem_flag_enable(edge_arr[i], EDGE_NOT_IN_STACK); - BM_elem_flag_enable(edge_arr[i]->v1, VERT_NOT_IN_STACK); - BM_elem_flag_enable(edge_arr[i]->v2, VERT_NOT_IN_STACK); - } - - + /* -------------------------------------------------------------------- */ + /* This function has 2 main parts. + * + * - Check if there are any holes. + * - Connect the holes with edges (if any are found). + * + * Keep the first part fast since it will run very often for edge-nets that have no holes. + * + * \note Don't use the mem_arena unless he have holes to fill. + * (avoid thrashing the area when the initial check isn't so intensive on the stack). + */ + + const uint edge_arr_len = (uint)edge_net_init_len + (uint)f->len; + BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len); + bool ok = false; + uint edge_net_new_len = (uint)edge_net_init_len; + + memcpy(edge_arr, edge_net_init, sizeof(*edge_arr) * (size_t)edge_net_init_len); + + /* _must_ clear on exit */ +#define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG +#define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG + + { + uint i = edge_net_init_len; + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BLI_assert(!BM_elem_flag_test(l_iter->v, VERT_NOT_IN_STACK)); + BLI_assert(!BM_elem_flag_test(l_iter->e, EDGE_NOT_IN_STACK)); + edge_arr[i++] = l_iter->e; + } while ((l_iter = l_iter->next) != l_first); + BLI_assert(i == edge_arr_len); + } + + for (uint i = 0; i < edge_arr_len; i++) { + BM_elem_flag_enable(edge_arr[i], EDGE_NOT_IN_STACK); + BM_elem_flag_enable(edge_arr[i]->v1, VERT_NOT_IN_STACK); + BM_elem_flag_enable(edge_arr[i]->v2, VERT_NOT_IN_STACK); + } #ifdef USE_PARTIAL_CONNECT - /* Split-out delimiting vertices */ - struct TempVertPair { - struct TempVertPair *next; - BMVert *v_temp; - BMVert *v_orig; - }; - - struct { - struct TempVertPair *list; - uint len; - int *remap; /* temp -> orig mapping */ - } temp_vert_pairs = {NULL}; - - if (use_partial_connect) { - for (uint i = 0; i < edge_net_init_len; i++) { - for (unsigned j = 0; j < 2; j++) { - BMVert *v_delimit = (&edge_arr[i]->v1)[j]; - BMVert *v_other; - - /* note, remapping will _never_ map a vertex to an already mapped vertex */ - while (UNLIKELY((v_other = bm_face_split_edgenet_partial_connect(bm, v_delimit, f)))) { - struct TempVertPair *tvp = BLI_memarena_alloc(mem_arena, sizeof(*tvp)); - tvp->next = temp_vert_pairs.list; - tvp->v_orig = v_delimit; - tvp->v_temp = v_other; - temp_vert_pairs.list = tvp; - temp_vert_pairs.len++; - } - } - } - - if (temp_vert_pairs.len == 0) { - use_partial_connect = false; - } - } -#endif /* USE_PARTIAL_CONNECT */ - - - - uint group_arr_len = 0; - LinkNode *group_head = NULL; - { - /* scan 'edge_arr' backwards so the outer face boundary is handled first - * (since its likely to be the largest) */ - uint edge_index = (edge_arr_len - 1); - uint edge_in_group_tot = 0; - - BLI_SMALLSTACK_DECLARE(vstack, BMVert *); - - while (true) { - LinkNode *edge_links = NULL; - uint unique_verts_in_group = 0, unique_edges_in_group = 0; - - /* list of groups */ - BLI_assert(BM_elem_flag_test(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK)); - BLI_SMALLSTACK_PUSH(vstack, edge_arr[edge_index]->v1); - BM_elem_flag_disable(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK); - - BMVert *v_iter; - while ((v_iter = BLI_SMALLSTACK_POP(vstack))) { - unique_verts_in_group++; - - BMEdge *e_iter = v_iter->e; - do { - if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) { - BM_elem_flag_disable(e_iter, EDGE_NOT_IN_STACK); - unique_edges_in_group++; - - BLI_linklist_prepend_alloca(&edge_links, e_iter); - - BMVert *v_other = BM_edge_other_vert(e_iter, v_iter); - if (BM_elem_flag_test(v_other, VERT_NOT_IN_STACK)) { - BLI_SMALLSTACK_PUSH(vstack, v_other); - BM_elem_flag_disable(v_other, VERT_NOT_IN_STACK); - } - } - } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_iter)) != v_iter->e); - } - - struct EdgeGroupIsland *g = alloca(sizeof(*g)); - g->vert_len = unique_verts_in_group; - g->edge_len = unique_edges_in_group; - edge_in_group_tot += unique_edges_in_group; - - BLI_linklist_prepend_nlink(&group_head, edge_links, (LinkNode *)g); - - group_arr_len++; - - if (edge_in_group_tot == edge_arr_len) { - break; - } - - /* skip edges in the stack */ - while (BM_elem_flag_test(edge_arr[edge_index], EDGE_NOT_IN_STACK) == false) { - BLI_assert(edge_index != 0); - edge_index--; - } - } - } - - /* single group - no holes */ - if (group_arr_len == 1) { - goto finally; - } - - - /* -------------------------------------------------------------------- */ - /* Previous checks need to be kept fast, since they will run very often, - * now we know there are holes, so calculate a spatial lookup info and - * other per-group data. - */ - - float axis_mat[3][3]; - axis_dominant_v3_to_m3(axis_mat, f->no); + /* Split-out delimiting vertices */ + struct TempVertPair { + struct TempVertPair *next; + BMVert *v_temp; + BMVert *v_orig; + }; + + struct { + struct TempVertPair *list; + uint len; + int *remap; /* temp -> orig mapping */ + } temp_vert_pairs = {NULL}; + + if (use_partial_connect) { + for (uint i = 0; i < edge_net_init_len; i++) { + for (unsigned j = 0; j < 2; j++) { + BMVert *v_delimit = (&edge_arr[i]->v1)[j]; + BMVert *v_other; + + /* note, remapping will _never_ map a vertex to an already mapped vertex */ + while (UNLIKELY((v_other = bm_face_split_edgenet_partial_connect(bm, v_delimit, f)))) { + struct TempVertPair *tvp = BLI_memarena_alloc(mem_arena, sizeof(*tvp)); + tvp->next = temp_vert_pairs.list; + tvp->v_orig = v_delimit; + tvp->v_temp = v_other; + temp_vert_pairs.list = tvp; + temp_vert_pairs.len++; + } + } + } + + if (temp_vert_pairs.len == 0) { + use_partial_connect = false; + } + } +#endif /* USE_PARTIAL_CONNECT */ + + uint group_arr_len = 0; + LinkNode *group_head = NULL; + { + /* scan 'edge_arr' backwards so the outer face boundary is handled first + * (since its likely to be the largest) */ + uint edge_index = (edge_arr_len - 1); + uint edge_in_group_tot = 0; + + BLI_SMALLSTACK_DECLARE(vstack, BMVert *); + + while (true) { + LinkNode *edge_links = NULL; + uint unique_verts_in_group = 0, unique_edges_in_group = 0; + + /* list of groups */ + BLI_assert(BM_elem_flag_test(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK)); + BLI_SMALLSTACK_PUSH(vstack, edge_arr[edge_index]->v1); + BM_elem_flag_disable(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK); + + BMVert *v_iter; + while ((v_iter = BLI_SMALLSTACK_POP(vstack))) { + unique_verts_in_group++; + + BMEdge *e_iter = v_iter->e; + do { + if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) { + BM_elem_flag_disable(e_iter, EDGE_NOT_IN_STACK); + unique_edges_in_group++; + + BLI_linklist_prepend_alloca(&edge_links, e_iter); + + BMVert *v_other = BM_edge_other_vert(e_iter, v_iter); + if (BM_elem_flag_test(v_other, VERT_NOT_IN_STACK)) { + BLI_SMALLSTACK_PUSH(vstack, v_other); + BM_elem_flag_disable(v_other, VERT_NOT_IN_STACK); + } + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_iter)) != v_iter->e); + } + + struct EdgeGroupIsland *g = alloca(sizeof(*g)); + g->vert_len = unique_verts_in_group; + g->edge_len = unique_edges_in_group; + edge_in_group_tot += unique_edges_in_group; + + BLI_linklist_prepend_nlink(&group_head, edge_links, (LinkNode *)g); + + group_arr_len++; + + if (edge_in_group_tot == edge_arr_len) { + break; + } + + /* skip edges in the stack */ + while (BM_elem_flag_test(edge_arr[edge_index], EDGE_NOT_IN_STACK) == false) { + BLI_assert(edge_index != 0); + edge_index--; + } + } + } + + /* single group - no holes */ + if (group_arr_len == 1) { + goto finally; + } + + /* -------------------------------------------------------------------- */ + /* Previous checks need to be kept fast, since they will run very often, + * now we know there are holes, so calculate a spatial lookup info and + * other per-group data. + */ + + float axis_mat[3][3]; + axis_dominant_v3_to_m3(axis_mat, f->no); #define VERT_IN_ARRAY BM_ELEM_INTERNAL_TAG - struct EdgeGroupIsland **group_arr = BLI_memarena_alloc(mem_arena, sizeof(*group_arr) * group_arr_len); - uint vert_arr_len = 0; - /* sort groups by lowest value vertex */ - { - /* fill 'groups_arr' in reverse order so the boundary face is first */ - struct EdgeGroupIsland **group_arr_p = &group_arr[group_arr_len]; - - for (struct EdgeGroupIsland *g = (void *)group_head; g; g = (struct EdgeGroupIsland *)g->edge_links.next) { - LinkNode *edge_links = g->edge_links.link; - - /* init with *any* different verts */ - g->vert_span.min = ((BMEdge *)edge_links->link)->v1; - g->vert_span.max = ((BMEdge *)edge_links->link)->v2; - float min_axis[2] = {FLT_MAX, FLT_MAX}; - float max_axis[2] = {-FLT_MAX, -FLT_MAX}; - - do { - BMEdge *e = edge_links->link; - BLI_assert(e->head.htype == BM_EDGE); - - for (int j = 0; j < 2; j++) { - BMVert *v_iter = (&e->v1)[j]; - BLI_assert(v_iter->head.htype == BM_VERT); - /* ideally we could use 'v_iter->co[SORT_AXIS]' here, - * but we need to sort the groups before setting the vertex array order */ - const float axis_value[2] = { + struct EdgeGroupIsland **group_arr = BLI_memarena_alloc(mem_arena, + sizeof(*group_arr) * group_arr_len); + uint vert_arr_len = 0; + /* sort groups by lowest value vertex */ + { + /* fill 'groups_arr' in reverse order so the boundary face is first */ + struct EdgeGroupIsland **group_arr_p = &group_arr[group_arr_len]; + + for (struct EdgeGroupIsland *g = (void *)group_head; g; + g = (struct EdgeGroupIsland *)g->edge_links.next) { + LinkNode *edge_links = g->edge_links.link; + + /* init with *any* different verts */ + g->vert_span.min = ((BMEdge *)edge_links->link)->v1; + g->vert_span.max = ((BMEdge *)edge_links->link)->v2; + float min_axis[2] = {FLT_MAX, FLT_MAX}; + float max_axis[2] = {-FLT_MAX, -FLT_MAX}; + + do { + BMEdge *e = edge_links->link; + BLI_assert(e->head.htype == BM_EDGE); + + for (int j = 0; j < 2; j++) { + BMVert *v_iter = (&e->v1)[j]; + BLI_assert(v_iter->head.htype == BM_VERT); + /* ideally we could use 'v_iter->co[SORT_AXIS]' here, + * but we need to sort the groups before setting the vertex array order */ + const float axis_value[2] = { #if SORT_AXIS == 0 - dot_m3_v3_row_x(axis_mat, v_iter->co), - dot_m3_v3_row_y(axis_mat, v_iter->co), + dot_m3_v3_row_x(axis_mat, v_iter->co), + dot_m3_v3_row_y(axis_mat, v_iter->co), #else - dot_m3_v3_row_y(axis_mat, v_iter->co), - dot_m3_v3_row_x(axis_mat, v_iter->co), + dot_m3_v3_row_y(axis_mat, v_iter->co), + dot_m3_v3_row_x(axis_mat, v_iter->co), #endif - }; - - if (axis_pt_cmp(axis_value, min_axis) == -1) { - g->vert_span.min = v_iter; - copy_v2_v2(min_axis, axis_value); - } - if (axis_pt_cmp(axis_value, max_axis) == 1) { - g->vert_span.max = v_iter; - copy_v2_v2(max_axis, axis_value); - } - } - } while ((edge_links = edge_links->next)); - - copy_v2_v2(g->vert_span.min_axis, min_axis); - copy_v2_v2(g->vert_span.max_axis, max_axis); - - g->has_prev_edge = false; - - vert_arr_len += g->vert_len; - - *(--group_arr_p) = g; - } - } - - qsort(group_arr, group_arr_len, sizeof(*group_arr), group_min_cmp_fn); - - /* we don't know how many unique verts there are connecting the edges, so over-alloc */ - BMVert **vert_arr = BLI_memarena_alloc(mem_arena, sizeof(*vert_arr) * vert_arr_len); - /* map vertex -> group index */ - uint *verts_group_table = BLI_memarena_alloc(mem_arena, sizeof(*verts_group_table) * vert_arr_len); - - float (*vert_coords_backup)[3] = BLI_memarena_alloc(mem_arena, sizeof(*vert_coords_backup) * vert_arr_len); - - { - /* relative location, for higher precision calculations */ - const float f_co_ref[3] = {UNPACK3(BM_FACE_FIRST_LOOP(f)->v->co)}; - - int v_index = 0; /* global vert index */ - for (uint g_index = 0; g_index < group_arr_len; g_index++) { - LinkNode *edge_links = group_arr[g_index]->edge_links.link; - do { - BMEdge *e = edge_links->link; - for (int j = 0; j < 2; j++) { - BMVert *v_iter = (&e->v1)[j]; - if (!BM_elem_flag_test(v_iter, VERT_IN_ARRAY)) { - BM_elem_flag_enable(v_iter, VERT_IN_ARRAY); - - /* not nice, but alternatives arent much better :S */ - { - copy_v3_v3(vert_coords_backup[v_index], v_iter->co); - - /* for higher precision */ - sub_v3_v3(v_iter->co, f_co_ref); - - float co_2d[2]; - mul_v2_m3v3(co_2d, axis_mat, v_iter->co); - v_iter->co[0] = co_2d[0]; - v_iter->co[1] = co_2d[1]; - v_iter->co[2] = 0.0f; - } - - BM_elem_index_set(v_iter, v_index); /* set_dirty */ - - vert_arr[v_index] = v_iter; - verts_group_table[v_index] = g_index; - v_index++; - } - } - } while ((edge_links = edge_links->next)); - } - } - - bm->elem_index_dirty |= BM_VERT; - - /* Now create bvh tree - * - * Note that a large epsilon is used because meshes with dimensions of around 100+ need it. see T52329. */ - BVHTree *bvhtree = BLI_bvhtree_new(edge_arr_len, 1e-4f, 8, 8); - for (uint i = 0; i < edge_arr_len; i++) { - const float e_cos[2][3] = { - {UNPACK2(edge_arr[i]->v1->co), 0.0f}, - {UNPACK2(edge_arr[i]->v2->co), 0.0f}, - }; - BLI_bvhtree_insert(bvhtree, i, (const float *)e_cos, 2); - } - BLI_bvhtree_balance(bvhtree); - - + }; + + if (axis_pt_cmp(axis_value, min_axis) == -1) { + g->vert_span.min = v_iter; + copy_v2_v2(min_axis, axis_value); + } + if (axis_pt_cmp(axis_value, max_axis) == 1) { + g->vert_span.max = v_iter; + copy_v2_v2(max_axis, axis_value); + } + } + } while ((edge_links = edge_links->next)); + + copy_v2_v2(g->vert_span.min_axis, min_axis); + copy_v2_v2(g->vert_span.max_axis, max_axis); + + g->has_prev_edge = false; + + vert_arr_len += g->vert_len; + + *(--group_arr_p) = g; + } + } + + qsort(group_arr, group_arr_len, sizeof(*group_arr), group_min_cmp_fn); + + /* we don't know how many unique verts there are connecting the edges, so over-alloc */ + BMVert **vert_arr = BLI_memarena_alloc(mem_arena, sizeof(*vert_arr) * vert_arr_len); + /* map vertex -> group index */ + uint *verts_group_table = BLI_memarena_alloc(mem_arena, + sizeof(*verts_group_table) * vert_arr_len); + + float(*vert_coords_backup)[3] = BLI_memarena_alloc(mem_arena, + sizeof(*vert_coords_backup) * vert_arr_len); + + { + /* relative location, for higher precision calculations */ + const float f_co_ref[3] = {UNPACK3(BM_FACE_FIRST_LOOP(f)->v->co)}; + + int v_index = 0; /* global vert index */ + for (uint g_index = 0; g_index < group_arr_len; g_index++) { + LinkNode *edge_links = group_arr[g_index]->edge_links.link; + do { + BMEdge *e = edge_links->link; + for (int j = 0; j < 2; j++) { + BMVert *v_iter = (&e->v1)[j]; + if (!BM_elem_flag_test(v_iter, VERT_IN_ARRAY)) { + BM_elem_flag_enable(v_iter, VERT_IN_ARRAY); + + /* not nice, but alternatives arent much better :S */ + { + copy_v3_v3(vert_coords_backup[v_index], v_iter->co); + + /* for higher precision */ + sub_v3_v3(v_iter->co, f_co_ref); + + float co_2d[2]; + mul_v2_m3v3(co_2d, axis_mat, v_iter->co); + v_iter->co[0] = co_2d[0]; + v_iter->co[1] = co_2d[1]; + v_iter->co[2] = 0.0f; + } + + BM_elem_index_set(v_iter, v_index); /* set_dirty */ + + vert_arr[v_index] = v_iter; + verts_group_table[v_index] = g_index; + v_index++; + } + } + } while ((edge_links = edge_links->next)); + } + } + + bm->elem_index_dirty |= BM_VERT; + + /* Now create bvh tree + * + * Note that a large epsilon is used because meshes with dimensions of around 100+ need it. see T52329. */ + BVHTree *bvhtree = BLI_bvhtree_new(edge_arr_len, 1e-4f, 8, 8); + for (uint i = 0; i < edge_arr_len; i++) { + const float e_cos[2][3] = { + {UNPACK2(edge_arr[i]->v1->co), 0.0f}, + {UNPACK2(edge_arr[i]->v2->co), 0.0f}, + }; + BLI_bvhtree_insert(bvhtree, i, (const float *)e_cos, 2); + } + BLI_bvhtree_balance(bvhtree); #ifdef USE_PARTIAL_CONNECT - if (use_partial_connect) { - /* needs to be done once the vertex indices have been written into */ - temp_vert_pairs.remap = BLI_memarena_alloc(mem_arena, sizeof(*temp_vert_pairs.remap) * vert_arr_len); - copy_vn_i(temp_vert_pairs.remap, vert_arr_len, -1); + if (use_partial_connect) { + /* needs to be done once the vertex indices have been written into */ + temp_vert_pairs.remap = BLI_memarena_alloc(mem_arena, + sizeof(*temp_vert_pairs.remap) * vert_arr_len); + copy_vn_i(temp_vert_pairs.remap, vert_arr_len, -1); - struct TempVertPair *tvp = temp_vert_pairs.list; - do { - temp_vert_pairs.remap[BM_elem_index_get(tvp->v_temp)] = BM_elem_index_get(tvp->v_orig); - } while ((tvp = tvp->next)); - } -#endif /* USE_PARTIAL_CONNECT */ + struct TempVertPair *tvp = temp_vert_pairs.list; + do { + temp_vert_pairs.remap[BM_elem_index_get(tvp->v_temp)] = BM_elem_index_get(tvp->v_orig); + } while ((tvp = tvp->next)); + } +#endif /* USE_PARTIAL_CONNECT */ + /* Create connections between groups */ + /* may be an over-alloc, but not by much */ + edge_net_new_len = (uint)edge_net_init_len + ((group_arr_len - 1) * 2); + BMEdge **edge_net_new = BLI_memarena_alloc(mem_arena, sizeof(*edge_net_new) * edge_net_new_len); + memcpy(edge_net_new, edge_net_init, sizeof(*edge_net_new) * (size_t)edge_net_init_len); - /* Create connections between groups */ + { + uint edge_net_new_index = edge_net_init_len; + /* start-end of the verts in the current group */ - /* may be an over-alloc, but not by much */ - edge_net_new_len = (uint)edge_net_init_len + ((group_arr_len - 1) * 2); - BMEdge **edge_net_new = BLI_memarena_alloc(mem_arena, sizeof(*edge_net_new) * edge_net_new_len); - memcpy(edge_net_new, edge_net_init, sizeof(*edge_net_new) * (size_t)edge_net_init_len); + uint vert_range[2]; - { - uint edge_net_new_index = edge_net_init_len; - /* start-end of the verts in the current group */ + vert_range[0] = 0; + vert_range[1] = group_arr[0]->vert_len; - uint vert_range[2]; + struct EdgeGroup_FindConnection_Args args = { + .bvhtree = bvhtree, - vert_range[0] = 0; - vert_range[1] = group_arr[0]->vert_len; + /* use the new edge array so we can scan edges which have been added */ + .edge_arr = edge_arr, + .edge_arr_len = edge_arr_len, - struct EdgeGroup_FindConnection_Args args = { - .bvhtree = bvhtree, + /* we only want to check newly created edges */ + .edge_arr_new = edge_net_new + edge_net_init_len, + .edge_arr_new_len = 0, - /* use the new edge array so we can scan edges which have been added */ - .edge_arr = edge_arr, - .edge_arr_len = edge_arr_len, + .vert_range = vert_range, + }; - /* we only want to check newly created edges */ - .edge_arr_new = edge_net_new + edge_net_init_len, - .edge_arr_new_len = 0, + for (uint g_index = 1; g_index < group_arr_len; g_index++) { + struct EdgeGroupIsland *g = group_arr[g_index]; - .vert_range = vert_range, - }; + /* the range of verts this group uses in 'verts_arr' (not uncluding the last index) */ + vert_range[0] = vert_range[1]; + vert_range[1] += g->vert_len; - for (uint g_index = 1; g_index < group_arr_len; g_index++) { - struct EdgeGroupIsland *g = group_arr[g_index]; + if (g->has_prev_edge == false) { + BMVert *v_origin = g->vert_span.min; - /* the range of verts this group uses in 'verts_arr' (not uncluding the last index) */ - vert_range[0] = vert_range[1]; - vert_range[1] += g->vert_len; + const int index_other = bm_face_split_edgenet_find_connection(&args, v_origin, false); + // BLI_assert(index_other >= 0 && index_other < (int)vert_arr_len); - if (g->has_prev_edge == false) { - BMVert *v_origin = g->vert_span.min; - - const int index_other = bm_face_split_edgenet_find_connection(&args, v_origin, false); - // BLI_assert(index_other >= 0 && index_other < (int)vert_arr_len); - - /* only for degenerate geometry */ - if (index_other != -1) { + /* only for degenerate geometry */ + if (index_other != -1) { #ifdef USE_PARTIAL_CONNECT - if ((use_partial_connect == false) || - (bm_vert_partial_connect_check_overlap( - temp_vert_pairs.remap, - BM_elem_index_get(v_origin), index_other) == false)) + if ((use_partial_connect == false) || + (bm_vert_partial_connect_check_overlap( + temp_vert_pairs.remap, BM_elem_index_get(v_origin), index_other) == false)) #endif - { - BMVert *v_end = vert_arr[index_other]; + { + BMVert *v_end = vert_arr[index_other]; - edge_net_new[edge_net_new_index] = BM_edge_create(bm, v_origin, v_end, NULL, 0); + edge_net_new[edge_net_new_index] = BM_edge_create(bm, v_origin, v_end, NULL, 0); #ifdef USE_PARTIAL_CONNECT - BM_elem_index_set(edge_net_new[edge_net_new_index], edge_net_new_index); + BM_elem_index_set(edge_net_new[edge_net_new_index], edge_net_new_index); #endif - edge_net_new_index++; - args.edge_arr_new_len++; - } - } - } + edge_net_new_index++; + args.edge_arr_new_len++; + } + } + } - { - BMVert *v_origin = g->vert_span.max; + { + BMVert *v_origin = g->vert_span.max; - const int index_other = bm_face_split_edgenet_find_connection(&args, v_origin, true); - // BLI_assert(index_other >= 0 && index_other < (int)vert_arr_len); + const int index_other = bm_face_split_edgenet_find_connection(&args, v_origin, true); + // BLI_assert(index_other >= 0 && index_other < (int)vert_arr_len); - /* only for degenerate geometry */ - if (index_other != -1) { + /* only for degenerate geometry */ + if (index_other != -1) { #ifdef USE_PARTIAL_CONNECT - if ((use_partial_connect == false) || - (bm_vert_partial_connect_check_overlap( - temp_vert_pairs.remap, - BM_elem_index_get(v_origin), index_other) == false)) + if ((use_partial_connect == false) || + (bm_vert_partial_connect_check_overlap( + temp_vert_pairs.remap, BM_elem_index_get(v_origin), index_other) == false)) #endif - { - BMVert *v_end = vert_arr[index_other]; - edge_net_new[edge_net_new_index] = BM_edge_create(bm, v_origin, v_end, NULL, 0); + { + BMVert *v_end = vert_arr[index_other]; + edge_net_new[edge_net_new_index] = BM_edge_create(bm, v_origin, v_end, NULL, 0); #ifdef USE_PARTIAL_CONNECT - BM_elem_index_set(edge_net_new[edge_net_new_index], edge_net_new_index); + BM_elem_index_set(edge_net_new[edge_net_new_index], edge_net_new_index); #endif - edge_net_new_index++; - args.edge_arr_new_len++; - } - - /* tell the 'next' group it doesn't need to create its own back-link */ - uint g_index_other = verts_group_table[index_other]; - group_arr[g_index_other]->has_prev_edge = true; - } - } - - } - BLI_assert(edge_net_new_len >= edge_net_new_index); - edge_net_new_len = edge_net_new_index; - } - - BLI_bvhtree_free(bvhtree); - - *r_edge_net_new = edge_net_new; - *r_edge_net_new_len = edge_net_new_len; - ok = true; - - for (uint i = 0; i < vert_arr_len; i++) { - copy_v3_v3(vert_arr[i]->co, vert_coords_backup[i]); - } + edge_net_new_index++; + args.edge_arr_new_len++; + } + + /* tell the 'next' group it doesn't need to create its own back-link */ + uint g_index_other = verts_group_table[index_other]; + group_arr[g_index_other]->has_prev_edge = true; + } + } + } + BLI_assert(edge_net_new_len >= edge_net_new_index); + edge_net_new_len = edge_net_new_index; + } + + BLI_bvhtree_free(bvhtree); + + *r_edge_net_new = edge_net_new; + *r_edge_net_new_len = edge_net_new_len; + ok = true; + + for (uint i = 0; i < vert_arr_len; i++) { + copy_v3_v3(vert_arr[i]->co, vert_coords_backup[i]); + } finally: #ifdef USE_PARTIAL_CONNECT - /* don't free 'vert_temp_pair_list', its part of the arena */ - if (use_partial_connect) { - - /* Sanity check: ensure we don't have connecting edges before splicing begins. */ -#ifdef DEBUG - { - struct TempVertPair *tvp = temp_vert_pairs.list; - do { - /* we must _never_ create connections here - * (inface the islands can't have a connection at all) */ - BLI_assert(BM_edge_exists(tvp->v_orig, tvp->v_temp) == NULL); - } while ((tvp = tvp->next)); - } -#endif - - struct TempVertPair *tvp = temp_vert_pairs.list; - do { - /* its _very_ unlikely the edge exists, - * however splicing may case this. see: T48012 */ - if (!BM_edge_exists(tvp->v_orig, tvp->v_temp)) { - BM_vert_splice(bm, tvp->v_orig, tvp->v_temp); - } - } while ((tvp = tvp->next)); - - /* Remove edges which have become doubles since splicing vertices together, - * its less trouble then detecting future-doubles on edge-creation. */ - for (uint i = edge_net_init_len; i < edge_net_new_len; i++) { - while (BM_edge_find_double(edge_net_new[i])) { - BM_edge_kill(bm, edge_net_new[i]); - edge_net_new_len--; - if (i == edge_net_new_len) { - break; - } - edge_net_new[i] = edge_net_new[edge_net_new_len]; - } - } - - *r_edge_net_new_len = edge_net_new_len; - } + /* don't free 'vert_temp_pair_list', its part of the arena */ + if (use_partial_connect) { + + /* Sanity check: ensure we don't have connecting edges before splicing begins. */ +# ifdef DEBUG + { + struct TempVertPair *tvp = temp_vert_pairs.list; + do { + /* we must _never_ create connections here + * (inface the islands can't have a connection at all) */ + BLI_assert(BM_edge_exists(tvp->v_orig, tvp->v_temp) == NULL); + } while ((tvp = tvp->next)); + } +# endif + + struct TempVertPair *tvp = temp_vert_pairs.list; + do { + /* its _very_ unlikely the edge exists, + * however splicing may case this. see: T48012 */ + if (!BM_edge_exists(tvp->v_orig, tvp->v_temp)) { + BM_vert_splice(bm, tvp->v_orig, tvp->v_temp); + } + } while ((tvp = tvp->next)); + + /* Remove edges which have become doubles since splicing vertices together, + * its less trouble then detecting future-doubles on edge-creation. */ + for (uint i = edge_net_init_len; i < edge_net_new_len; i++) { + while (BM_edge_find_double(edge_net_new[i])) { + BM_edge_kill(bm, edge_net_new[i]); + edge_net_new_len--; + if (i == edge_net_new_len) { + break; + } + edge_net_new[i] = edge_net_new[edge_net_new_len]; + } + } + + *r_edge_net_new_len = edge_net_new_len; + } #endif - - for (uint i = 0; i < edge_arr_len; i++) { - BM_elem_flag_disable(edge_arr[i], EDGE_NOT_IN_STACK); - BM_elem_flag_disable(edge_arr[i]->v1, VERT_NOT_IN_STACK); - BM_elem_flag_disable(edge_arr[i]->v2, VERT_NOT_IN_STACK); - } + for (uint i = 0; i < edge_arr_len; i++) { + BM_elem_flag_disable(edge_arr[i], EDGE_NOT_IN_STACK); + BM_elem_flag_disable(edge_arr[i]->v1, VERT_NOT_IN_STACK); + BM_elem_flag_disable(edge_arr[i]->v2, VERT_NOT_IN_STACK); + } #undef VERT_IN_ARRAY #undef VERT_NOT_IN_STACK #undef EDGE_NOT_IN_STACK - return ok; + return ok; } #undef SORT_AXIS diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h index 7e57f648704..38af944d0cd 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h @@ -21,17 +21,21 @@ * \ingroup bmesh */ -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); +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); -bool BM_face_split_edgenet_connect_islands( - BMesh *bm, - BMFace *f, BMEdge **edge_net_init, const uint edge_net_init_len, - bool use_partial_connect, - struct MemArena *arena, - BMEdge ***r_edge_net_new, uint *r_edge_net_new_len) -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 6, 7, 8); +bool BM_face_split_edgenet_connect_islands(BMesh *bm, + BMFace *f, + BMEdge **edge_net_init, + const uint edge_net_init_len, + bool use_partial_connect, + struct MemArena *arena, + BMEdge ***r_edge_net_new, + uint *r_edge_net_new_len) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(1, 2, 3, 6, 7, 8); -#endif /* __BMESH_POLYGON_EDGENET_H__ */ +#endif /* __BMESH_POLYGON_EDGENET_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h index c0f74c50a3a..b77243f7b26 100644 --- a/source/blender/bmesh/intern/bmesh_private.h +++ b/source/blender/bmesh/intern/bmesh_private.h @@ -31,19 +31,23 @@ /* returns positive nonzero on error */ #ifdef NDEBUG - /* no error checking for release, +/* no error checking for release, * it can take most of the CPU time when running some tools */ -# define BM_CHECK_ELEMENT(el) (void)(el) +# define BM_CHECK_ELEMENT(el) (void)(el) #else int bmesh_elem_check(void *element, const char htype); -# define BM_CHECK_ELEMENT(el) { \ - if (bmesh_elem_check(el, ((BMHeader *)el)->htype)) { \ - printf("check_element failure, with code %i on line %i in file\n" \ - " \"%s\"\n\n", \ - bmesh_elem_check(el, ((BMHeader *)el)->htype), \ - __LINE__, __FILE__); \ - } \ -} ((void)0) +# define BM_CHECK_ELEMENT(el) \ + { \ + if (bmesh_elem_check(el, ((BMHeader *)el)->htype)) { \ + printf( \ + "check_element failure, with code %i on line %i in file\n" \ + " \"%s\"\n\n", \ + bmesh_elem_check(el, ((BMHeader *)el)->htype), \ + __LINE__, \ + __FILE__); \ + } \ + } \ + ((void)0) #endif int bmesh_radial_length(const BMLoop *l); @@ -55,20 +59,32 @@ int bmesh_disk_count(const BMVert *v); * \note Ensure different parts of the API do not conflict * on using these internal flags!*/ enum { - _FLAG_JF = (1 << 0), /* join faces */ - _FLAG_MF = (1 << 1), /* make face */ - _FLAG_MV = (1 << 1), /* make face, vertex */ - _FLAG_OVERLAP = (1 << 2), /* general overlap flag */ - _FLAG_WALK = (1 << 3), /* general walk flag (keep clean) */ - _FLAG_WALK_ALT = (1 << 4), /* same as _FLAG_WALK, for when a second tag is needed */ + _FLAG_JF = (1 << 0), /* join faces */ + _FLAG_MF = (1 << 1), /* make face */ + _FLAG_MV = (1 << 1), /* make face, vertex */ + _FLAG_OVERLAP = (1 << 2), /* general overlap flag */ + _FLAG_WALK = (1 << 3), /* general walk flag (keep clean) */ + _FLAG_WALK_ALT = (1 << 4), /* same as _FLAG_WALK, for when a second tag is needed */ - _FLAG_ELEM_CHECK = (1 << 7), /* reserved for bmesh_elem_check */ + _FLAG_ELEM_CHECK = (1 << 7), /* reserved for bmesh_elem_check */ }; -#define BM_ELEM_API_FLAG_ENABLE(element, f) { ((element)->head.api_flag |= (f)); } (void)0 -#define BM_ELEM_API_FLAG_DISABLE(element, f) { ((element)->head.api_flag &= (uchar)~(f)); } (void)0 -#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f)) -#define BM_ELEM_API_FLAG_CLEAR(element) { ((element)->head.api_flag = 0); } (void)0 +#define BM_ELEM_API_FLAG_ENABLE(element, f) \ + { \ + ((element)->head.api_flag |= (f)); \ + } \ + (void)0 +#define BM_ELEM_API_FLAG_DISABLE(element, f) \ + { \ + ((element)->head.api_flag &= (uchar) ~(f)); \ + } \ + (void)0 +#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f)) +#define BM_ELEM_API_FLAG_CLEAR(element) \ + { \ + ((element)->head.api_flag = 0); \ + } \ + (void)0 void poly_rotate_plane(const float normal[3], float (*verts)[3], unsigned const int nverts); diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c index 4b34e1fe07d..98ad30b6a28 100644 --- a/source/blender/bmesh/intern/bmesh_query.c +++ b/source/blender/bmesh/intern/bmesh_query.c @@ -57,9 +57,9 @@ */ BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v) { - BMLoop *l = BM_face_edge_share_loop(f, e); - BLI_assert(l != NULL); - return BM_loop_other_edge_loop(l, v); + BMLoop *l = BM_face_edge_share_loop(f, e); + BLI_assert(l != NULL); + return BM_loop_other_edge_loop(l, v); } /** @@ -68,8 +68,8 @@ BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v) */ BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v) { - BLI_assert(BM_vert_in_edge(l->e, v)); - return l->v == v ? l->prev : l->next; + BLI_assert(BM_vert_in_edge(l->e, v)); + return l->v == v ? l->prev : l->next; } /** @@ -96,28 +96,28 @@ BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v) */ BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v) { - BMLoop *l_iter = BM_face_vert_share_loop(f, v); + BMLoop *l_iter = BM_face_vert_share_loop(f, v); - BLI_assert(BM_edge_exists(v_prev, v) != NULL); + BLI_assert(BM_edge_exists(v_prev, v) != NULL); - if (l_iter) { - if (l_iter->prev->v == v_prev) { - return l_iter->next; - } - else if (l_iter->next->v == v_prev) { - return l_iter->prev; - } - else { - /* invalid args */ - BLI_assert(0); - return NULL; - } - } - else { - /* invalid args */ - BLI_assert(0); - return NULL; - } + if (l_iter) { + if (l_iter->prev->v == v_prev) { + return l_iter->next; + } + else if (l_iter->next->v == v_prev) { + return l_iter->prev; + } + else { + /* invalid args */ + BLI_assert(0); + return NULL; + } + } + else { + /* invalid args */ + BLI_assert(0); + return NULL; + } } /** @@ -139,149 +139,144 @@ BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v) BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v) { #if 0 /* works but slow */ - return BM_face_other_vert_loop(l->f, BM_edge_other_vert(l->e, v), v); + return BM_face_other_vert_loop(l->f, BM_edge_other_vert(l->e, v), v); #else - BMEdge *e = l->e; - BMVert *v_prev = BM_edge_other_vert(e, v); - if (l->v == v) { - if (l->prev->v == v_prev) { - return l->next; - } - else { - BLI_assert(l->next->v == v_prev); - - return l->prev; - } - } - else { - BLI_assert(l->v == v_prev); - - if (l->prev->v == v) { - return l->prev->prev; - } - else { - BLI_assert(l->next->v == v); - return l->next->next; - } - } + BMEdge *e = l->e; + BMVert *v_prev = BM_edge_other_vert(e, v); + if (l->v == v) { + if (l->prev->v == v_prev) { + return l->next; + } + else { + BLI_assert(l->next->v == v_prev); + + return l->prev; + } + } + else { + BLI_assert(l->v == v_prev); + + if (l->prev->v == v) { + return l->prev->prev; + } + else { + BLI_assert(l->next->v == v); + return l->next->next; + } + } #endif } /** * Check if verts share a face. */ -bool BM_vert_pair_share_face_check( - BMVert *v_a, BMVert *v_b) +bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b) { - if (v_a->e && v_b->e) { - BMIter iter; - BMFace *f; + if (v_a->e && v_b->e) { + BMIter iter; + BMFace *f; - BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) { - if (BM_vert_in_face(v_b, f)) { - return true; - } - } - } + BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) { + if (BM_vert_in_face(v_b, f)) { + return true; + } + } + } - return false; + return false; } -bool BM_vert_pair_share_face_check_cb( - BMVert *v_a, BMVert *v_b, - bool (*test_fn)(BMFace *, void *user_data), void *user_data) +bool BM_vert_pair_share_face_check_cb(BMVert *v_a, + BMVert *v_b, + bool (*test_fn)(BMFace *, void *user_data), + void *user_data) { - if (v_a->e && v_b->e) { - BMIter iter; - BMFace *f; + if (v_a->e && v_b->e) { + BMIter iter; + BMFace *f; - BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) { - if (test_fn(f, user_data)) { - if (BM_vert_in_face(v_b, f)) { - return true; - } - } - } - } + BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) { + if (test_fn(f, user_data)) { + if (BM_vert_in_face(v_b, f)) { + return true; + } + } + } + } - return false; + return false; } /** * Given 2 verts, find the smallest face they share and give back both loops. */ BMFace *BM_vert_pair_share_face_by_len( - BMVert *v_a, BMVert *v_b, - BMLoop **r_l_a, BMLoop **r_l_b, - const bool allow_adjacent) + BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent) { - BMLoop *l_cur_a = NULL, *l_cur_b = NULL; - BMFace *f_cur = NULL; + BMLoop *l_cur_a = NULL, *l_cur_b = NULL; + BMFace *f_cur = NULL; - if (v_a->e && v_b->e) { - BMIter iter; - BMLoop *l_a, *l_b; + if (v_a->e && v_b->e) { + BMIter iter; + BMLoop *l_a, *l_b; - BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) { - if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) { - l_b = BM_face_vert_share_loop(l_a->f, v_b); - if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) { - f_cur = l_a->f; - l_cur_a = l_a; - l_cur_b = l_b; - } - } - } - } + BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) { + if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) { + l_b = BM_face_vert_share_loop(l_a->f, v_b); + if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) { + f_cur = l_a->f; + l_cur_a = l_a; + l_cur_b = l_b; + } + } + } + } - *r_l_a = l_cur_a; - *r_l_b = l_cur_b; + *r_l_a = l_cur_a; + *r_l_b = l_cur_b; - return f_cur; + return f_cur; } BMFace *BM_edge_pair_share_face_by_len( - BMEdge *e_a, BMEdge *e_b, - BMLoop **r_l_a, BMLoop **r_l_b, - const bool allow_adjacent) + BMEdge *e_a, BMEdge *e_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent) { - BMLoop *l_cur_a = NULL, *l_cur_b = NULL; - BMFace *f_cur = NULL; + BMLoop *l_cur_a = NULL, *l_cur_b = NULL; + BMFace *f_cur = NULL; - if (e_a->l && e_b->l) { - BMIter iter; - BMLoop *l_a, *l_b; + if (e_a->l && e_b->l) { + BMIter iter; + BMLoop *l_a, *l_b; - BM_ITER_ELEM (l_a, &iter, e_a, BM_LOOPS_OF_EDGE) { - if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) { - l_b = BM_face_edge_share_loop(l_a->f, e_b); - if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) { - f_cur = l_a->f; - l_cur_a = l_a; - l_cur_b = l_b; - } - } - } - } + BM_ITER_ELEM (l_a, &iter, e_a, BM_LOOPS_OF_EDGE) { + if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) { + l_b = BM_face_edge_share_loop(l_a->f, e_b); + if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) { + f_cur = l_a->f; + l_cur_a = l_a; + l_cur_b = l_b; + } + } + } + } - *r_l_a = l_cur_a; - *r_l_b = l_cur_b; + *r_l_a = l_cur_a; + *r_l_b = l_cur_b; - return f_cur; + return f_cur; } static float bm_face_calc_split_dot(BMLoop *l_a, BMLoop *l_b) { - float no[2][3]; + float no[2][3]; - if ((BM_face_calc_normal_subset(l_a, l_b, no[0]) != 0.0f) && - (BM_face_calc_normal_subset(l_b, l_a, no[1]) != 0.0f)) - { - return dot_v3v3(no[0], no[1]); - } - else { - return -1.0f; - } + if ((BM_face_calc_normal_subset(l_a, l_b, no[0]) != 0.0f) && + (BM_face_calc_normal_subset(l_b, l_a, no[1]) != 0.0f)) { + return dot_v3v3(no[0], no[1]); + } + else { + return -1.0f; + } } /** @@ -292,8 +287,8 @@ static float bm_face_calc_split_dot(BMLoop *l_a, BMLoop *l_b) */ float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) { - const float *axis = l->f->no; - return dist_signed_squared_to_corner_v3v3v3(co, l->prev->v->co, l->v->co, l->next->v->co, axis); + const float *axis = l->f->no; + return dist_signed_squared_to_corner_v3v3v3(co, l->prev->v->co, l->v->co, l->next->v->co, axis); } /** @@ -304,15 +299,15 @@ float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) */ float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) { - const float *axis = l->f->no; - float dir[3]; - float plane[4]; + const float *axis = l->f->no; + float dir[3]; + float plane[4]; - sub_v3_v3v3(dir, l->next->v->co, l->v->co); - cross_v3_v3v3(plane, axis, dir); + sub_v3_v3v3(dir, l->next->v->co, l->v->co); + cross_v3_v3v3(plane, axis, dir); - plane[3] = -dot_v3v3(plane, l->v->co); - return dist_signed_squared_to_plane_v3(co, plane); + plane[3] = -dot_v3v3(plane, l->v->co); + return dist_signed_squared_to_plane_v3(co, plane); } /** @@ -321,68 +316,65 @@ float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) * This can be better then #BM_vert_pair_share_face_by_len because concave splits are ranked lowest. */ BMFace *BM_vert_pair_share_face_by_angle( - BMVert *v_a, BMVert *v_b, - BMLoop **r_l_a, BMLoop **r_l_b, - const bool allow_adjacent) + BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent) { - BMLoop *l_cur_a = NULL, *l_cur_b = NULL; - BMFace *f_cur = NULL; + BMLoop *l_cur_a = NULL, *l_cur_b = NULL; + BMFace *f_cur = NULL; - if (v_a->e && v_b->e) { - BMIter iter; - BMLoop *l_a, *l_b; - float dot_best = -1.0f; + if (v_a->e && v_b->e) { + BMIter iter; + BMLoop *l_a, *l_b; + float dot_best = -1.0f; - BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) { - l_b = BM_face_vert_share_loop(l_a->f, v_b); - if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) { + BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) { + l_b = BM_face_vert_share_loop(l_a->f, v_b); + if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) { - if (f_cur == NULL) { - f_cur = l_a->f; - l_cur_a = l_a; - l_cur_b = l_b; - } - else { - /* avoid expensive calculations if we only ever find one face */ - float dot; - if (dot_best == -1.0f) { - dot_best = bm_face_calc_split_dot(l_cur_a, l_cur_b); - } + if (f_cur == NULL) { + f_cur = l_a->f; + l_cur_a = l_a; + l_cur_b = l_b; + } + else { + /* avoid expensive calculations if we only ever find one face */ + float dot; + if (dot_best == -1.0f) { + dot_best = bm_face_calc_split_dot(l_cur_a, l_cur_b); + } - dot = bm_face_calc_split_dot(l_a, l_b); - if (dot > dot_best) { - dot_best = dot; + dot = bm_face_calc_split_dot(l_a, l_b); + if (dot > dot_best) { + dot_best = dot; - f_cur = l_a->f; - l_cur_a = l_a; - l_cur_b = l_b; - } - } - } - } - } + f_cur = l_a->f; + l_cur_a = l_a; + l_cur_b = l_b; + } + } + } + } + } - *r_l_a = l_cur_a; - *r_l_b = l_cur_b; + *r_l_a = l_cur_a; + *r_l_b = l_cur_b; - return f_cur; + return f_cur; } - /** * Get the first loop of a vert. Uses the same initialization code for the first loop of the * iterator API */ BMLoop *BM_vert_find_first_loop(BMVert *v) { - return v->e ? bmesh_disk_faceloop_find_first(v->e, v) : NULL; + return v->e ? bmesh_disk_faceloop_find_first(v->e, v) : NULL; } /** * A version of #BM_vert_find_first_loop that ignores hidden loops. */ BMLoop *BM_vert_find_first_loop_visible(BMVert *v) { - return v->e ? bmesh_disk_faceloop_find_first_visible(v->e, v) : NULL; + return v->e ? bmesh_disk_faceloop_find_first_visible(v->e, v) : NULL; } /** @@ -390,26 +382,26 @@ BMLoop *BM_vert_find_first_loop_visible(BMVert *v) */ bool BM_vert_in_face(BMVert *v, BMFace *f) { - BMLoop *l_iter, *l_first; + BMLoop *l_iter, *l_first; #ifdef USE_BMESH_HOLES - BMLoopList *lst; - for (lst = f->loops.first; lst; lst = lst->next) + BMLoopList *lst; + for (lst = f->loops.first; lst; lst = lst->next) #endif - { + { #ifdef USE_BMESH_HOLES - l_iter = l_first = lst->first; + l_iter = l_first = lst->first; #else - l_iter = l_first = f->l_first; + l_iter = l_first = f->l_first; #endif - do { - if (l_iter->v == v) { - return true; - } - } while ((l_iter = l_iter->next) != l_first); - } + do { + if (l_iter->v == v) { + return true; + } + } while ((l_iter = l_iter->next) != l_first); + } - return false; + return false; } /** @@ -418,96 +410,95 @@ bool BM_vert_in_face(BMVert *v, BMFace *f) */ int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) { - BMLoop *l_iter, *l_first; + BMLoop *l_iter, *l_first; #ifdef USE_BMESH_HOLES - BMLoopList *lst; + BMLoopList *lst; #endif - int i, count = 0; + int i, count = 0; - for (i = 0; i < len; i++) { - BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); - } + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); + } #ifdef USE_BMESH_HOLES - for (lst = f->loops.first; lst; lst = lst->next) + for (lst = f->loops.first; lst; lst = lst->next) #endif - { + { #ifdef USE_BMESH_HOLES - l_iter = l_first = lst->first; + l_iter = l_first = lst->first; #else - l_iter = l_first = f->l_first; + l_iter = l_first = f->l_first; #endif - do { - if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) { - count++; - } + do { + if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) { + count++; + } - } while ((l_iter = l_iter->next) != l_first); - } + } while ((l_iter = l_iter->next) != l_first); + } - for (i = 0; i < len; i++) { - BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); - } + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); + } - return count; + return count; } - /** * Return true if all verts are in the face. */ bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) { - BMLoop *l_iter, *l_first; + BMLoop *l_iter, *l_first; #ifdef USE_BMESH_HOLES - BMLoopList *lst; + BMLoopList *lst; #endif - int i; - bool ok = true; + int i; + bool ok = true; - /* simple check, we know can't succeed */ - if (f->len < len) { - return false; - } + /* simple check, we know can't succeed */ + if (f->len < len) { + return false; + } - for (i = 0; i < len; i++) { - BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); - } + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); + } #ifdef USE_BMESH_HOLES - for (lst = f->loops.first; lst; lst = lst->next) + for (lst = f->loops.first; lst; lst = lst->next) #endif - { + { #ifdef USE_BMESH_HOLES - l_iter = l_first = lst->first; + l_iter = l_first = lst->first; #else - l_iter = l_first = f->l_first; + l_iter = l_first = f->l_first; #endif - do { - if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) { - /* pass */ - } - else { - ok = false; - break; - } + do { + if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) { + /* pass */ + } + else { + ok = false; + break; + } - } while ((l_iter = l_iter->next) != l_first); - } + } while ((l_iter = l_iter->next) != l_first); + } - for (i = 0; i < len; i++) { - BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); - } + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); + } - return ok; + return ok; } /** @@ -515,18 +506,18 @@ bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) */ bool BM_edge_in_face(const BMEdge *e, const BMFace *f) { - if (e->l) { - const BMLoop *l_iter, *l_first; + if (e->l) { + const BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - if (l_iter->f == f) { - return true; - } - } while ((l_iter = l_iter->radial_next) != l_first); - } + l_iter = l_first = e->l; + do { + if (l_iter->f == f) { + return true; + } + } while ((l_iter = l_iter->radial_next) != l_first); + } - return false; + return false; } /** @@ -547,27 +538,27 @@ bool BM_edge_in_face(const BMEdge *e, const BMFace *f) */ BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l) { - BMLoop *l_other; + BMLoop *l_other; - // BLI_assert(BM_edge_is_manifold(e)); // TOO strict, just check if we have another radial face - BLI_assert(e->l && e->l->radial_next != e->l); - BLI_assert(BM_vert_in_edge(e, l->v)); + // BLI_assert(BM_edge_is_manifold(e)); // TOO strict, just check if we have another radial face + BLI_assert(e->l && e->l->radial_next != e->l); + BLI_assert(BM_vert_in_edge(e, l->v)); - l_other = (l->e == e) ? l : l->prev; - l_other = l_other->radial_next; - BLI_assert(l_other->e == e); + l_other = (l->e == e) ? l : l->prev; + l_other = l_other->radial_next; + BLI_assert(l_other->e == e); - if (l_other->v == l->v) { - /* pass */ - } - else if (l_other->next->v == l->v) { - l_other = l_other->next; - } - else { - BLI_assert(0); - } + if (l_other->v == l->v) { + /* pass */ + } + else if (l_other->next->v == l->v) { + l_other = l_other->next; + } + else { + BLI_assert(0); + } - return l_other; + return l_other; } /** @@ -597,29 +588,27 @@ BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l) BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step) { - BMEdge *e_prev = *e_step; - BMEdge *e_next; - if (l->e == e_prev) { - e_next = l->prev->e; - } - else if (l->prev->e == e_prev) { - e_next = l->e; - } - else { - BLI_assert(0); - return NULL; - } + BMEdge *e_prev = *e_step; + BMEdge *e_next; + if (l->e == e_prev) { + e_next = l->prev->e; + } + else if (l->prev->e == e_prev) { + e_next = l->e; + } + else { + BLI_assert(0); + return NULL; + } - if (BM_edge_is_manifold(e_next)) { - return BM_edge_other_loop((*e_step = e_next), l); - } - else { - return NULL; - } + if (BM_edge_is_manifold(e_next)) { + return BM_edge_other_loop((*e_step = e_next), l); + } + else { + return NULL; + } } - - /** * The function takes a vertex at the center of a fan and returns the opposite edge in the fan. * All edges in the fan must be manifold, otherwise return NULL. @@ -628,49 +617,48 @@ BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step) */ BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first) { - BMLoop *l_a; - int tot = 0; - int i; + BMLoop *l_a; + int tot = 0; + int i; - BLI_assert(BM_vert_in_edge(e_first, v)); + BLI_assert(BM_vert_in_edge(e_first, v)); - l_a = e_first->l; - do { - l_a = BM_loop_other_vert_loop(l_a, v); - l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev; - if (BM_edge_is_manifold(l_a->e)) { - l_a = l_a->radial_next; - } - else { - return NULL; - } + l_a = e_first->l; + do { + l_a = BM_loop_other_vert_loop(l_a, v); + l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev; + if (BM_edge_is_manifold(l_a->e)) { + l_a = l_a->radial_next; + } + else { + return NULL; + } - tot++; - } while (l_a != e_first->l); + tot++; + } while (l_a != e_first->l); - /* we know the total, now loop half way */ - tot /= 2; - i = 0; + /* we know the total, now loop half way */ + tot /= 2; + i = 0; - l_a = e_first->l; - do { - if (i == tot) { - l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev; - return l_a->e; - } + l_a = e_first->l; + do { + if (i == tot) { + l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev; + return l_a->e; + } - l_a = BM_loop_other_vert_loop(l_a, v); - l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev; - if (BM_edge_is_manifold(l_a->e)) { - l_a = l_a->radial_next; - } - /* this wont have changed from the previous loop */ + l_a = BM_loop_other_vert_loop(l_a, v); + l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev; + if (BM_edge_is_manifold(l_a->e)) { + l_a = l_a->radial_next; + } + /* this wont have changed from the previous loop */ + i++; + } while (l_a != e_first->l); - i++; - } while (l_a != e_first->l); - - return NULL; + return NULL; } /** @@ -678,7 +666,7 @@ BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first) */ float BM_edge_calc_length(const BMEdge *e) { - return len_v3v3(e->v1->co, e->v2->co); + return len_v3v3(e->v1->co, e->v2->co); } /** @@ -686,7 +674,7 @@ float BM_edge_calc_length(const BMEdge *e) */ float BM_edge_calc_length_squared(const BMEdge *e) { - return len_squared_v3v3(e->v1->co, e->v2->co); + return len_squared_v3v3(e->v1->co, e->v2->co); } /** @@ -697,22 +685,18 @@ float BM_edge_calc_length_squared(const BMEdge *e) */ bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) { - BMLoop *la, *lb; + BMLoop *la, *lb; - if ((la = e->l) && - (lb = la->radial_next) && - (la != lb) && - (lb->radial_next == la)) - { - *r_fa = la->f; - *r_fb = lb->f; - return true; - } - else { - *r_fa = NULL; - *r_fb = NULL; - return false; - } + if ((la = e->l) && (lb = la->radial_next) && (la != lb) && (lb->radial_next == la)) { + *r_fa = la->f; + *r_fb = lb->f; + return true; + } + else { + *r_fa = NULL; + *r_fb = NULL; + return false; + } } /** @@ -723,22 +707,18 @@ bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) */ bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) { - BMLoop *la, *lb; + BMLoop *la, *lb; - if ((la = e->l) && - (lb = la->radial_next) && - (la != lb) && - (lb->radial_next == la)) - { - *r_la = la; - *r_lb = lb; - return true; - } - else { - *r_la = NULL; - *r_lb = NULL; - return false; - } + if ((la = e->l) && (lb = la->radial_next) && (la != lb) && (lb->radial_next == la)) { + *r_la = la; + *r_lb = lb; + return true; + } + else { + *r_la = NULL; + *r_lb = NULL; + return false; + } } /** @@ -746,12 +726,12 @@ bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) */ bool BM_vert_is_edge_pair(const BMVert *v) { - const BMEdge *e = v->e; - if (e) { - BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v); - return ((e_other != e) && (BM_DISK_EDGE_NEXT(e_other, v) == e)); - } - return false; + const BMEdge *e = v->e; + if (e) { + BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v); + return ((e_other != e) && (BM_DISK_EDGE_NEXT(e_other, v) == e)); + } + return false; } /** @@ -760,14 +740,14 @@ bool BM_vert_is_edge_pair(const BMVert *v) */ bool BM_vert_is_edge_pair_manifold(const BMVert *v) { - const BMEdge *e = v->e; - if (e) { - BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v); - if (((e_other != e) && (BM_DISK_EDGE_NEXT(e_other, v) == e))) { - return BM_edge_is_manifold(e) && BM_edge_is_manifold(e_other); - } - } - return false; + const BMEdge *e = v->e; + if (e) { + BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v); + if (((e_other != e) && (BM_DISK_EDGE_NEXT(e_other, v) == e))) { + return BM_edge_is_manifold(e) && BM_edge_is_manifold(e_other); + } + } + return false; } /** @@ -777,19 +757,19 @@ bool BM_vert_is_edge_pair_manifold(const BMVert *v) */ bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b) { - BMEdge *e_a = v->e; - if (e_a) { - BMEdge *e_b = BM_DISK_EDGE_NEXT(e_a, v); - if ((e_b != e_a) && (BM_DISK_EDGE_NEXT(e_b, v) == e_a)) { - *r_e_a = e_a; - *r_e_b = e_b; - return true; - } - } + BMEdge *e_a = v->e; + if (e_a) { + BMEdge *e_b = BM_DISK_EDGE_NEXT(e_a, v); + if ((e_b != e_a) && (BM_DISK_EDGE_NEXT(e_b, v) == e_a)) { + *r_e_a = e_a; + *r_e_b = e_b; + return true; + } + } - *r_e_a = NULL; - *r_e_b = NULL; - return false; + *r_e_a = NULL; + *r_e_b = NULL; + return false; } /** @@ -797,62 +777,62 @@ bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b) */ int BM_vert_edge_count(const BMVert *v) { - return bmesh_disk_count(v); + return bmesh_disk_count(v); } int BM_vert_edge_count_at_most(const BMVert *v, const int count_max) { - return bmesh_disk_count_at_most(v, count_max); + return bmesh_disk_count_at_most(v, count_max); } int BM_vert_edge_count_nonwire(const BMVert *v) { - int count = 0; - BMIter eiter; - BMEdge *edge; - BM_ITER_ELEM (edge, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) { - if (edge->l) { - count++; - } - } - return count; + int count = 0; + BMIter eiter; + BMEdge *edge; + BM_ITER_ELEM (edge, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) { + if (edge->l) { + count++; + } + } + return count; } /** * Returns the number of faces around this edge */ int BM_edge_face_count(const BMEdge *e) { - int count = 0; + int count = 0; - if (e->l) { - BMLoop *l_iter, *l_first; + if (e->l) { + BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - count++; - } while ((l_iter = l_iter->radial_next) != l_first); - } + l_iter = l_first = e->l; + do { + count++; + } while ((l_iter = l_iter->radial_next) != l_first); + } - return count; + return count; } int BM_edge_face_count_at_most(const BMEdge *e, const int count_max) { - int count = 0; + int count = 0; - if (e->l) { - BMLoop *l_iter, *l_first; + if (e->l) { + BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - count++; - if (count == count_max) { - break; - } - } while ((l_iter = l_iter->radial_next) != l_first); - } + l_iter = l_first = e->l; + do { + count++; + if (count == count_max) { + break; + } + } while ((l_iter = l_iter->radial_next) != l_first); + } - return count; + return count; } /** @@ -861,12 +841,12 @@ int BM_edge_face_count_at_most(const BMEdge *e, const int count_max) */ int BM_vert_face_count(const BMVert *v) { - return bmesh_disk_facevert_count(v); + return bmesh_disk_facevert_count(v); } int BM_vert_face_count_at_most(const BMVert *v, int count_max) { - return bmesh_disk_facevert_count_at_most(v, count_max); + return bmesh_disk_facevert_count_at_most(v, count_max); } /** @@ -876,16 +856,16 @@ int BM_vert_face_count_at_most(const BMVert *v, int count_max) */ bool BM_vert_face_check(const BMVert *v) { - if (v->e != NULL) { - const BMEdge *e_iter, *e_first; - e_first = e_iter = v->e; - do { - if (e_iter->l != NULL) { - return true; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - } - return false; + if (v->e != NULL) { + const BMEdge *e_iter, *e_first; + e_first = e_iter = v->e; + do { + if (e_iter->l != NULL) { + return true; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } + return false; } /** @@ -894,21 +874,21 @@ bool BM_vert_face_check(const BMVert *v) */ bool BM_vert_is_wire(const BMVert *v) { - if (v->e) { - BMEdge *e_first, *e_iter; + if (v->e) { + BMEdge *e_first, *e_iter; - e_first = e_iter = v->e; - do { - if (e_iter->l) { - return false; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + e_first = e_iter = v->e; + do { + if (e_iter->l) { + return false; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - return true; - } - else { - return false; - } + return true; + } + else { + return false; + } } /** @@ -920,61 +900,61 @@ bool BM_vert_is_wire(const BMVert *v) */ bool BM_vert_is_manifold(const BMVert *v) { - BMEdge *e_iter, *e_first, *e_prev; - BMLoop *l_iter, *l_first; - int loop_num = 0, loop_num_region = 0, boundary_num = 0; - - if (v->e == NULL) { - /* loose vert */ - return false; - } - - /* count edges while looking for non-manifold edges */ - e_first = e_iter = v->e; - /* may be null */ - l_first = e_iter->l; - do { - /* loose edge or edge shared by more than two faces, - * edges with 1 face user are OK, otherwise we could - * use BM_edge_is_manifold() here */ - if (e_iter->l == NULL || (e_iter->l != e_iter->l->radial_next->radial_next)) { - return false; - } - - /* count radial loops */ - if (e_iter->l->v == v) { - loop_num += 1; - } - - if (!BM_edge_is_boundary(e_iter)) { - /* non boundary check opposite loop */ - if (e_iter->l->radial_next->v == v) { - loop_num += 1; - } - } - else { - /* start at the boundary */ - l_first = e_iter->l; - boundary_num += 1; - /* >2 boundaries cant be manifold */ - if (boundary_num == 3) { - return false; - } - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - - e_first = l_first->e; - l_first = (l_first->v == v) ? l_first : l_first->next; - BLI_assert(l_first->v == v); - - l_iter = l_first; - e_prev = e_first; - - do { - loop_num_region += 1; - } while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)); - - return (loop_num == loop_num_region); + BMEdge *e_iter, *e_first, *e_prev; + BMLoop *l_iter, *l_first; + int loop_num = 0, loop_num_region = 0, boundary_num = 0; + + if (v->e == NULL) { + /* loose vert */ + return false; + } + + /* count edges while looking for non-manifold edges */ + e_first = e_iter = v->e; + /* may be null */ + l_first = e_iter->l; + do { + /* loose edge or edge shared by more than two faces, + * edges with 1 face user are OK, otherwise we could + * use BM_edge_is_manifold() here */ + if (e_iter->l == NULL || (e_iter->l != e_iter->l->radial_next->radial_next)) { + return false; + } + + /* count radial loops */ + if (e_iter->l->v == v) { + loop_num += 1; + } + + if (!BM_edge_is_boundary(e_iter)) { + /* non boundary check opposite loop */ + if (e_iter->l->radial_next->v == v) { + loop_num += 1; + } + } + else { + /* start at the boundary */ + l_first = e_iter->l; + boundary_num += 1; + /* >2 boundaries cant be manifold */ + if (boundary_num == 3) { + return false; + } + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + + e_first = l_first->e; + l_first = (l_first->v == v) ? l_first : l_first->next; + BLI_assert(l_first->v == v); + + l_iter = l_first; + e_prev = e_first; + + do { + loop_num_region += 1; + } while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)); + + return (loop_num == loop_num_region); } #define LOOP_VISIT _FLAG_WALK @@ -982,64 +962,64 @@ bool BM_vert_is_manifold(const BMVert *v) static int bm_loop_region_count__recursive(BMEdge *e, BMVert *v) { - BMLoop *l_iter, *l_first; - int count = 0; - - BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)); - BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT); - - l_iter = l_first = e->l; - do { - if (l_iter->v == v) { - BMEdge *e_other = l_iter->prev->e; - if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { - BM_ELEM_API_FLAG_ENABLE(l_iter, LOOP_VISIT); - count += 1; - } - if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) { - count += bm_loop_region_count__recursive(e_other, v); - } - } - else if (l_iter->next->v == v) { - BMEdge *e_other = l_iter->next->e; - if (!BM_ELEM_API_FLAG_TEST(l_iter->next, LOOP_VISIT)) { - BM_ELEM_API_FLAG_ENABLE(l_iter->next, LOOP_VISIT); - count += 1; - } - if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) { - count += bm_loop_region_count__recursive(e_other, v); - } - } - else { - BLI_assert(0); - } - } while ((l_iter = l_iter->radial_next) != l_first); - - return count; + BMLoop *l_iter, *l_first; + int count = 0; + + BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)); + BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT); + + l_iter = l_first = e->l; + do { + if (l_iter->v == v) { + BMEdge *e_other = l_iter->prev->e; + if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { + BM_ELEM_API_FLAG_ENABLE(l_iter, LOOP_VISIT); + count += 1; + } + if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) { + count += bm_loop_region_count__recursive(e_other, v); + } + } + else if (l_iter->next->v == v) { + BMEdge *e_other = l_iter->next->e; + if (!BM_ELEM_API_FLAG_TEST(l_iter->next, LOOP_VISIT)) { + BM_ELEM_API_FLAG_ENABLE(l_iter->next, LOOP_VISIT); + count += 1; + } + if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) { + count += bm_loop_region_count__recursive(e_other, v); + } + } + else { + BLI_assert(0); + } + } while ((l_iter = l_iter->radial_next) != l_first); + + return count; } static int bm_loop_region_count__clear(BMLoop *l) { - int count = 0; - BMEdge *e_iter, *e_first; + int count = 0; + BMEdge *e_iter, *e_first; - /* clear flags */ - e_iter = e_first = l->e; - do { - BM_ELEM_API_FLAG_DISABLE(e_iter, EDGE_VISIT); - if (e_iter->l) { - BMLoop *l_iter, *l_first; - l_iter = l_first = e_iter->l; - do { - if (l_iter->v == l->v) { - BM_ELEM_API_FLAG_DISABLE(l_iter, LOOP_VISIT); - count += 1; - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, l->v)) != e_first); + /* clear flags */ + e_iter = e_first = l->e; + do { + BM_ELEM_API_FLAG_DISABLE(e_iter, EDGE_VISIT); + if (e_iter->l) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e_iter->l; + do { + if (l_iter->v == l->v) { + BM_ELEM_API_FLAG_DISABLE(l_iter, LOOP_VISIT); + count += 1; + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, l->v)) != e_first); - return count; + return count; } /** @@ -1047,12 +1027,12 @@ static int bm_loop_region_count__clear(BMLoop *l) */ int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total) { - const int count = bm_loop_region_count__recursive(l->e, l->v); - const int count_total = bm_loop_region_count__clear(l); - if (r_loop_total) { - *r_loop_total = count_total; - } - return count; + const int count = bm_loop_region_count__recursive(l->e, l->v); + const int count_total = bm_loop_region_count__clear(l); + if (r_loop_total) { + *r_loop_total = count_total; + } + return count; } #undef LOOP_VISIT @@ -1060,7 +1040,7 @@ int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total) int BM_loop_region_loops_count(BMLoop *l) { - return BM_loop_region_loops_count_at_most(l, NULL); + return BM_loop_region_loops_count_at_most(l, NULL); } /** @@ -1069,13 +1049,13 @@ int BM_loop_region_loops_count(BMLoop *l) */ bool BM_vert_is_manifold_region(const BMVert *v) { - BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v); - if (l_first) { - int count, count_total; - count = BM_loop_region_loops_count_at_most(l_first, &count_total); - return (count == count_total); - } - return true; + BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v); + if (l_first) { + int count, count_total; + count = BM_loop_region_loops_count_at_most(l_first, &count_total); + return (count == count_total); + } + return true; } /** @@ -1084,85 +1064,82 @@ bool BM_vert_is_manifold_region(const BMVert *v) */ bool BM_edge_is_convex(const BMEdge *e) { - if (BM_edge_is_manifold(e)) { - BMLoop *l1 = e->l; - BMLoop *l2 = e->l->radial_next; - if (!equals_v3v3(l1->f->no, l2->f->no)) { - float cross[3]; - float l_dir[3]; - cross_v3_v3v3(cross, l1->f->no, l2->f->no); - /* we assume contiguous normals, otherwise the result isn't meaningful */ - sub_v3_v3v3(l_dir, l1->next->v->co, l1->v->co); - return (dot_v3v3(l_dir, cross) > 0.0f); - } - } - return true; + if (BM_edge_is_manifold(e)) { + BMLoop *l1 = e->l; + BMLoop *l2 = e->l->radial_next; + if (!equals_v3v3(l1->f->no, l2->f->no)) { + float cross[3]; + float l_dir[3]; + cross_v3_v3v3(cross, l1->f->no, l2->f->no); + /* we assume contiguous normals, otherwise the result isn't meaningful */ + sub_v3_v3v3(l_dir, l1->next->v->co, l1->v->co); + return (dot_v3v3(l_dir, cross) > 0.0f); + } + } + return true; } /** * \return true when loop customdata is contiguous. */ -bool BM_edge_is_contiguous_loop_cd( - const BMEdge *e, - const int cd_loop_type, const int cd_loop_offset) -{ - BLI_assert(cd_loop_offset != -1); - - if (e->l && e->l->radial_next != e->l) { - const BMLoop *l_base_v1 = e->l; - const BMLoop *l_base_v2 = e->l->next; - const void *l_base_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_base_v1, cd_loop_offset); - const void *l_base_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_base_v2, cd_loop_offset); - const BMLoop *l_iter = e->l->radial_next; - do { - const BMLoop *l_iter_v1; - const BMLoop *l_iter_v2; - const void *l_iter_cd_v1; - const void *l_iter_cd_v2; - - if (l_iter->v == l_base_v1->v) { - l_iter_v1 = l_iter; - l_iter_v2 = l_iter->next; - } - else { - l_iter_v1 = l_iter->next; - l_iter_v2 = l_iter; - } - BLI_assert((l_iter_v1->v == l_base_v1->v) && - (l_iter_v2->v == l_base_v2->v)); - - l_iter_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_iter_v1, cd_loop_offset); - l_iter_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_iter_v2, cd_loop_offset); - - - if ((CustomData_data_equals(cd_loop_type, l_base_cd_v1, l_iter_cd_v1) == 0) || - (CustomData_data_equals(cd_loop_type, l_base_cd_v2, l_iter_cd_v2) == 0)) - { - return false; - } - - } while ((l_iter = l_iter->radial_next) != e->l); - } - return true; +bool BM_edge_is_contiguous_loop_cd(const BMEdge *e, + const int cd_loop_type, + const int cd_loop_offset) +{ + BLI_assert(cd_loop_offset != -1); + + if (e->l && e->l->radial_next != e->l) { + const BMLoop *l_base_v1 = e->l; + const BMLoop *l_base_v2 = e->l->next; + const void *l_base_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_base_v1, cd_loop_offset); + const void *l_base_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_base_v2, cd_loop_offset); + const BMLoop *l_iter = e->l->radial_next; + do { + const BMLoop *l_iter_v1; + const BMLoop *l_iter_v2; + const void *l_iter_cd_v1; + const void *l_iter_cd_v2; + + if (l_iter->v == l_base_v1->v) { + l_iter_v1 = l_iter; + l_iter_v2 = l_iter->next; + } + else { + l_iter_v1 = l_iter->next; + l_iter_v2 = l_iter; + } + BLI_assert((l_iter_v1->v == l_base_v1->v) && (l_iter_v2->v == l_base_v2->v)); + + l_iter_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_iter_v1, cd_loop_offset); + l_iter_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_iter_v2, cd_loop_offset); + + if ((CustomData_data_equals(cd_loop_type, l_base_cd_v1, l_iter_cd_v1) == 0) || + (CustomData_data_equals(cd_loop_type, l_base_cd_v2, l_iter_cd_v2) == 0)) { + return false; + } + + } while ((l_iter = l_iter->radial_next) != e->l); + } + return true; } bool BM_vert_is_boundary(const BMVert *v) { - if (v->e) { - BMEdge *e_first, *e_iter; + if (v->e) { + BMEdge *e_first, *e_iter; - e_first = e_iter = v->e; - do { - if (BM_edge_is_boundary(e_iter)) { - return true; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + e_first = e_iter = v->e; + do { + if (BM_edge_is_boundary(e_iter)) { + return true; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - return false; - } - else { - return false; - } + return false; + } + else { + return false; + } } /** @@ -1172,20 +1149,20 @@ bool BM_vert_is_boundary(const BMVert *v) */ int BM_face_share_face_count(BMFace *f1, BMFace *f2) { - BMIter iter1, iter2; - BMEdge *e; - BMFace *f; - int count = 0; + BMIter iter1, iter2; + BMEdge *e; + BMFace *f; + int count = 0; - BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { - BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { - if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) { - count++; - } - } - } + BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { + if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) { + count++; + } + } + } - return count; + return count; } /** @@ -1193,19 +1170,19 @@ int BM_face_share_face_count(BMFace *f1, BMFace *f2) */ bool BM_face_share_face_check(BMFace *f1, BMFace *f2) { - BMIter iter1, iter2; - BMEdge *e; - BMFace *f; + BMIter iter1, iter2; + BMEdge *e; + BMFace *f; - BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { - BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { - if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) { - return true; - } - } - } + BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { + if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) { + return true; + } + } + } - return false; + return false; } /** @@ -1213,18 +1190,18 @@ bool BM_face_share_face_check(BMFace *f1, BMFace *f2) */ int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b) { - BMLoop *l_iter; - BMLoop *l_first; - int count = 0; + BMLoop *l_iter; + BMLoop *l_first; + int count = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f_a); - do { - if (BM_edge_in_face(l_iter->e, f_b)) { - count++; - } - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f_a); + do { + if (BM_edge_in_face(l_iter->e, f_b)) { + count++; + } + } while ((l_iter = l_iter->next) != l_first); - return count; + return count; } /** @@ -1232,17 +1209,17 @@ int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b) */ bool BM_face_share_edge_check(BMFace *f1, BMFace *f2) { - BMLoop *l_iter; - BMLoop *l_first; + BMLoop *l_iter; + BMLoop *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f1); - do { - if (BM_edge_in_face(l_iter->e, f2)) { - return true; - } - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f1); + do { + if (BM_edge_in_face(l_iter->e, f2)) { + return true; + } + } while ((l_iter = l_iter->next) != l_first); - return false; + return false; } /** @@ -1250,18 +1227,18 @@ bool BM_face_share_edge_check(BMFace *f1, BMFace *f2) */ int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b) { - BMLoop *l_iter; - BMLoop *l_first; - int count = 0; + BMLoop *l_iter; + BMLoop *l_first; + int count = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f_a); - do { - if (BM_vert_in_face(l_iter->v, f_b)) { - count++; - } - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f_a); + do { + if (BM_vert_in_face(l_iter->v, f_b)) { + count++; + } + } while ((l_iter = l_iter->next) != l_first); - return count; + return count; } /** @@ -1269,17 +1246,17 @@ int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b) */ bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b) { - BMLoop *l_iter; - BMLoop *l_first; + BMLoop *l_iter; + BMLoop *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f_a); - do { - if (BM_vert_in_face(l_iter->v, f_b)) { - return true; - } - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f_a); + do { + if (BM_vert_in_face(l_iter->v, f_b)) { + return true; + } + } while ((l_iter = l_iter->next) != l_first); - return false; + return false; } /** @@ -1287,9 +1264,8 @@ bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b) */ bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b) { - BLI_assert(l_a->v == l_b->v); - return (ELEM(l_a->e, l_b->e, l_b->prev->e) || - ELEM(l_b->e, l_a->e, l_a->prev->e)); + BLI_assert(l_a->v == l_b->v); + return (ELEM(l_a->e, l_b->e, l_b->prev->e) || ELEM(l_b->e, l_a->e, l_a->prev->e)); } /** @@ -1297,20 +1273,20 @@ bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b) */ bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) { - BMLoop *l; - BMFace *f; + BMLoop *l; + BMFace *f; - if (e1->l && e2->l) { - l = e1->l; - do { - f = l->f; - if (BM_edge_in_face(e2, f)) { - return true; - } - l = l->radial_next; - } while (l != e1->l); - } - return false; + if (e1->l && e2->l) { + l = e1->l; + do { + f = l->f; + if (BM_edge_in_face(e2, f)) { + return true; + } + l = l->radial_next; + } while (l != e1->l); + } + return false; } /** @@ -1318,22 +1294,22 @@ bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) */ bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) { - BMLoop *l; - BMFace *f; + BMLoop *l; + BMFace *f; - if (e1->l && e2->l) { - l = e1->l; - do { - f = l->f; - if (f->len == 4) { - if (BM_edge_in_face(e2, f)) { - return true; - } - } - l = l->radial_next; - } while (l != e1->l); - } - return false; + if (e1->l && e2->l) { + l = e1->l; + do { + f = l->f; + if (f->len == 4) { + if (BM_edge_in_face(e2, f)) { + return true; + } + } + l = l->radial_next; + } while (l != e1->l); + } + return false; } /** @@ -1341,10 +1317,7 @@ bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) */ bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) { - return (e1->v1 == e2->v1 || - e1->v1 == e2->v2 || - e1->v2 == e2->v1 || - e1->v2 == e2->v2); + return (e1->v1 == e2->v1 || e1->v1 == e2->v2 || e1->v2 == e2->v1 || e1->v2 == e2->v2); } /** @@ -1352,16 +1325,16 @@ bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) */ BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2) { - BLI_assert(e1 != e2); - if (BM_vert_in_edge(e2, e1->v1)) { - return e1->v1; - } - else if (BM_vert_in_edge(e2, e1->v2)) { - return e1->v2; - } - else { - return NULL; - } + BLI_assert(e1 != e2); + if (BM_vert_in_edge(e2, e1->v1)) { + return e1->v1; + } + else if (BM_vert_in_edge(e2, e1->v2)) { + return e1->v2; + } + else { + return NULL; + } } /** @@ -1374,13 +1347,13 @@ BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2) */ BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v) { - BLI_assert(BM_vert_in_edge(l->e, v)); - if (l->v == v) { - return l; - } - else { - return l->next; - } + BLI_assert(BM_vert_in_edge(l->e, v)); + if (l->v == v) { + return l; + } + else { + return l->next; + } } /** @@ -1393,17 +1366,17 @@ BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v) */ BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) { - BMLoop *l_first; - BMLoop *l_iter; + BMLoop *l_first; + BMLoop *l_iter; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (l_iter->v == v) { - return l_iter; - } - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (l_iter->v == v) { + return l_iter; + } + } while ((l_iter = l_iter->next) != l_first); - return NULL; + return NULL; } /** @@ -1416,17 +1389,17 @@ BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) */ BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) { - BMLoop *l_first; - BMLoop *l_iter; + BMLoop *l_first; + BMLoop *l_iter; - l_iter = l_first = e->l; - do { - if (l_iter->f == f) { - return l_iter; - } - } while ((l_iter = l_iter->radial_next) != l_first); + l_iter = l_first = e->l; + do { + if (l_iter->f == f) { + return l_iter; + } + } while ((l_iter = l_iter->radial_next) != l_first); - return NULL; + return NULL; } /** @@ -1440,19 +1413,20 @@ BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) * \note This is in fact quite a simple check, mainly include this function so the intent is more obvious. * We know these 2 verts will _always_ make up the loops edge */ -void BM_edge_ordered_verts_ex( - const BMEdge *edge, BMVert **r_v1, BMVert **r_v2, - const BMLoop *edge_loop) +void BM_edge_ordered_verts_ex(const BMEdge *edge, + BMVert **r_v1, + BMVert **r_v2, + const BMLoop *edge_loop) { - BLI_assert(edge_loop->e == edge); - (void)edge; /* quiet warning in release build */ - *r_v1 = edge_loop->v; - *r_v2 = edge_loop->next->v; + BLI_assert(edge_loop->e == edge); + (void)edge; /* quiet warning in release build */ + *r_v1 = edge_loop->v; + *r_v2 = edge_loop->next->v; } void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) { - BM_edge_ordered_verts_ex(edge, r_v1, r_v2, edge->l); + BM_edge_ordered_verts_ex(edge, r_v1, r_v2, edge->l); } /** @@ -1460,19 +1434,19 @@ void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) */ BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq) { - BMLoop *l_step = l->prev; + BMLoop *l_step = l->prev; - BLI_assert(!ELEM(l_stop, NULL, l)); + BLI_assert(!ELEM(l_stop, NULL, l)); - while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) { - l_step = l_step->prev; - BLI_assert(l_step != l); - if (UNLIKELY(l_step == l_stop)) { - return NULL; - } - } + while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) { + l_step = l_step->prev; + BLI_assert(l_step != l); + if (UNLIKELY(l_step == l_stop)) { + return NULL; + } + } - return l_step; + return l_step; } /** @@ -1480,19 +1454,19 @@ BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq */ BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq) { - BMLoop *l_step = l->next; + BMLoop *l_step = l->next; - BLI_assert(!ELEM(l_stop, NULL, l)); + BLI_assert(!ELEM(l_stop, NULL, l)); - while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) { - l_step = l_step->next; - BLI_assert(l_step != l); - if (UNLIKELY(l_step == l_stop)) { - return NULL; - } - } + while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) { + l_step = l_step->next; + BLI_assert(l_step != l); + if (UNLIKELY(l_step == l_stop)) { + return NULL; + } + } - return l_step; + return l_step; } /** @@ -1501,14 +1475,14 @@ BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq */ bool BM_loop_is_convex(const BMLoop *l) { - float e_dir_prev[3]; - float e_dir_next[3]; - float l_no[3]; + float e_dir_prev[3]; + float e_dir_next[3]; + float l_no[3]; - sub_v3_v3v3(e_dir_prev, l->prev->v->co, l->v->co); - sub_v3_v3v3(e_dir_next, l->next->v->co, l->v->co); - cross_v3_v3v3(l_no, e_dir_next, e_dir_prev); - return dot_v3v3(l_no, l->f->no) > 0.0f; + sub_v3_v3v3(e_dir_prev, l->prev->v->co, l->v->co); + sub_v3_v3v3(e_dir_next, l->next->v->co, l->v->co); + cross_v3_v3v3(l_no, e_dir_next, e_dir_prev); + return dot_v3v3(l_no, l->f->no) > 0.0f; } /** @@ -1519,9 +1493,7 @@ bool BM_loop_is_convex(const BMLoop *l) */ float BM_loop_calc_face_angle(const BMLoop *l) { - return angle_v3v3v3(l->prev->v->co, - l->v->co, - l->next->v->co); + return angle_v3v3v3(l->prev->v->co, l->v->co, l->next->v->co); } /** @@ -1535,30 +1507,30 @@ float BM_loop_calc_face_angle(const BMLoop *l) */ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3]) { - /* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors (vertex on a straight line) - * from zero value, because it does not normalize both vectors before making crossproduct. - * Instead of adding two costly normalize computations, just check ourselves for colinear case. */ - /* Note: FEPSILON might need some finer tweaking at some point? Seems to be working OK for now though. */ - float v1[3], v2[3], v_tmp[3]; - sub_v3_v3v3(v1, l->prev->v->co, l->v->co); - sub_v3_v3v3(v2, l->next->v->co, l->v->co); - - const float fac = - ((v2[0] == 0.0f) ? - ((v2[1] == 0.0f) ? - ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) : v1[1] / v2[1]) : v1[0] / v2[0]); - - mul_v3_v3fl(v_tmp, v2, fac); - sub_v3_v3(v_tmp, v1); - if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) { - /* Not co-linear, we can compute crossproduct and normalize it into normal. */ - cross_v3_v3v3(r_normal, v1, v2); - return normalize_v3(r_normal); - } - else { - copy_v3_v3(r_normal, l->f->no); - return 0.0f; - } + /* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors (vertex on a straight line) + * from zero value, because it does not normalize both vectors before making crossproduct. + * Instead of adding two costly normalize computations, just check ourselves for colinear case. */ + /* Note: FEPSILON might need some finer tweaking at some point? Seems to be working OK for now though. */ + float v1[3], v2[3], v_tmp[3]; + sub_v3_v3v3(v1, l->prev->v->co, l->v->co); + sub_v3_v3v3(v2, l->next->v->co, l->v->co); + + const float fac = ((v2[0] == 0.0f) ? + ((v2[1] == 0.0f) ? ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) : + v1[1] / v2[1]) : + v1[0] / v2[0]); + + mul_v3_v3fl(v_tmp, v2, fac); + sub_v3_v3(v_tmp, v1); + if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) { + /* Not co-linear, we can compute crossproduct and normalize it into normal. */ + cross_v3_v3v3(r_normal, v1, v2); + return normalize_v3(r_normal); + } + else { + copy_v3_v3(r_normal, l->f->no); + return 0.0f; + } } /** @@ -1568,7 +1540,7 @@ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, */ float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) { - return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal); + return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal); } /** @@ -1582,16 +1554,16 @@ float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) */ float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) { - float v1[3], v2[3]; - sub_v3_v3v3(v1, l->prev->v->co, l->v->co); - sub_v3_v3v3(v2, l->next->v->co, l->v->co); + float v1[3], v2[3]; + sub_v3_v3v3(v1, l->prev->v->co, l->v->co); + sub_v3_v3v3(v2, l->next->v->co, l->v->co); - cross_v3_v3v3(r_normal, v1, v2); - const float len = normalize_v3(r_normal); - if (UNLIKELY(len == 0.0f)) { - copy_v3_v3(r_normal, l->f->no); - } - return len; + cross_v3_v3v3(r_normal, v1, v2); + const float len = normalize_v3(r_normal); + if (UNLIKELY(len == 0.0f)) { + copy_v3_v3(r_normal, l->f->no); + } + return len; } /** @@ -1604,17 +1576,17 @@ float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) */ void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3]) { - float v_prev[3]; - float v_next[3]; + float v_prev[3]; + float v_next[3]; - sub_v3_v3v3(v_prev, l->v->co, l->prev->v->co); - sub_v3_v3v3(v_next, l->next->v->co, l->v->co); + sub_v3_v3v3(v_prev, l->v->co, l->prev->v->co); + sub_v3_v3v3(v_next, l->next->v->co, l->v->co); - normalize_v3(v_prev); - normalize_v3(v_next); + normalize_v3(v_prev); + normalize_v3(v_next); - add_v3_v3v3(r_dir, v_prev, v_next); - normalize_v3(r_dir); + add_v3_v3v3(r_dir, v_prev, v_next); + normalize_v3(r_dir); } /** @@ -1628,32 +1600,32 @@ void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3]) */ void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]) { - float v_prev[3]; - float v_next[3]; - float dir[3]; + float v_prev[3]; + float v_next[3]; + float dir[3]; - sub_v3_v3v3(v_prev, l->prev->v->co, l->v->co); - sub_v3_v3v3(v_next, l->v->co, l->next->v->co); + sub_v3_v3v3(v_prev, l->prev->v->co, l->v->co); + sub_v3_v3v3(v_next, l->v->co, l->next->v->co); - normalize_v3(v_prev); - normalize_v3(v_next); - add_v3_v3v3(dir, v_prev, v_next); + normalize_v3(v_prev); + normalize_v3(v_next); + add_v3_v3v3(dir, v_prev, v_next); - if (compare_v3v3(v_prev, v_next, FLT_EPSILON * 10.0f) == false) { - float nor[3]; /* for this purpose doesn't need to be normalized */ - cross_v3_v3v3(nor, v_prev, v_next); - /* concave face check */ - if (UNLIKELY(dot_v3v3(nor, l->f->no) < 0.0f)) { - negate_v3(nor); - } - cross_v3_v3v3(r_tangent, dir, nor); - } - else { - /* prev/next are the same - compare with face normal since we don't have one */ - cross_v3_v3v3(r_tangent, dir, l->f->no); - } + if (compare_v3v3(v_prev, v_next, FLT_EPSILON * 10.0f) == false) { + float nor[3]; /* for this purpose doesn't need to be normalized */ + cross_v3_v3v3(nor, v_prev, v_next); + /* concave face check */ + if (UNLIKELY(dot_v3v3(nor, l->f->no) < 0.0f)) { + negate_v3(nor); + } + cross_v3_v3v3(r_tangent, dir, nor); + } + else { + /* prev/next are the same - compare with face normal since we don't have one */ + cross_v3_v3v3(r_tangent, dir, l->f->no); + } - normalize_v3(r_tangent); + normalize_v3(r_tangent); } /** @@ -1666,18 +1638,18 @@ void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]) */ float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) { - if (BM_edge_is_manifold(e)) { - const BMLoop *l1 = e->l; - const BMLoop *l2 = e->l->radial_next; - return angle_normalized_v3v3(l1->f->no, l2->f->no); - } - else { - return fallback; - } + if (BM_edge_is_manifold(e)) { + const BMLoop *l1 = e->l; + const BMLoop *l2 = e->l->radial_next; + return angle_normalized_v3v3(l1->f->no, l2->f->no); + } + else { + return fallback; + } } float BM_edge_calc_face_angle(const BMEdge *e) { - return BM_edge_calc_face_angle_ex(e, DEG2RADF(90.0f)); + return BM_edge_calc_face_angle_ex(e, DEG2RADF(90.0f)); } /** @@ -1688,30 +1660,32 @@ float BM_edge_calc_face_angle(const BMEdge *e) * * \return angle in radians */ -float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e, const float imat3[3][3], const float fallback) +float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e, + const float imat3[3][3], + const float fallback) { - if (BM_edge_is_manifold(e)) { - const BMLoop *l1 = e->l; - const BMLoop *l2 = e->l->radial_next; - float no1[3], no2[3]; - copy_v3_v3(no1, l1->f->no); - copy_v3_v3(no2, l2->f->no); + if (BM_edge_is_manifold(e)) { + const BMLoop *l1 = e->l; + const BMLoop *l2 = e->l->radial_next; + float no1[3], no2[3]; + copy_v3_v3(no1, l1->f->no); + copy_v3_v3(no2, l2->f->no); - mul_transposed_m3_v3(imat3, no1); - mul_transposed_m3_v3(imat3, no2); + mul_transposed_m3_v3(imat3, no1); + mul_transposed_m3_v3(imat3, no2); - normalize_v3(no1); - normalize_v3(no2); + normalize_v3(no1); + normalize_v3(no2); - return angle_normalized_v3v3(no1, no2); - } - else { - return fallback; - } + return angle_normalized_v3v3(no1, no2); + } + else { + return fallback; + } } float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3]) { - return BM_edge_calc_face_angle_with_imat3_ex(e, imat3, DEG2RADF(90.0f)); + return BM_edge_calc_face_angle_with_imat3_ex(e, imat3, DEG2RADF(90.0f)); } /** @@ -1724,19 +1698,19 @@ float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3 */ float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback) { - if (BM_edge_is_manifold(e)) { - BMLoop *l1 = e->l; - BMLoop *l2 = e->l->radial_next; - const float angle = angle_normalized_v3v3(l1->f->no, l2->f->no); - return BM_edge_is_convex(e) ? angle : -angle; - } - else { - return fallback; - } + if (BM_edge_is_manifold(e)) { + BMLoop *l1 = e->l; + BMLoop *l2 = e->l->radial_next; + const float angle = angle_normalized_v3v3(l1->f->no, l2->f->no); + return BM_edge_is_convex(e) ? angle : -angle; + } + else { + return fallback; + } } float BM_edge_calc_face_angle_signed(const BMEdge *e) { - return BM_edge_calc_face_angle_signed_ex(e, DEG2RADF(90.0f)); + return BM_edge_calc_face_angle_signed_ex(e, DEG2RADF(90.0f)); } /** @@ -1754,15 +1728,15 @@ float BM_edge_calc_face_angle_signed(const BMEdge *e) void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) { - float tvec[3]; - BMVert *v1, *v2; - BM_edge_ordered_verts_ex(e, &v1, &v2, e_loop); + float tvec[3]; + BMVert *v1, *v2; + BM_edge_ordered_verts_ex(e, &v1, &v2, e_loop); - sub_v3_v3v3(tvec, v1->co, v2->co); /* use for temp storage */ - /* note, we could average the tangents of both loops, - * for non flat ngons it will give a better direction */ - cross_v3_v3v3(r_tangent, tvec, e_loop->f->no); - normalize_v3(r_tangent); + sub_v3_v3v3(tvec, v1->co, v2->co); /* use for temp storage */ + /* note, we could average the tangents of both loops, + * for non flat ngons it will give a better direction */ + cross_v3_v3v3(r_tangent, tvec, e_loop->f->no); + normalize_v3(r_tangent); } /** @@ -1774,30 +1748,27 @@ void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_ta */ float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) { - BMEdge *e1, *e2; + BMEdge *e1, *e2; - /* saves BM_vert_edge_count(v) and and edge iterator, - * get the edges and count them both at once */ + /* saves BM_vert_edge_count(v) and and edge iterator, + * get the edges and count them both at once */ - if ((e1 = v->e) && - (e2 = bmesh_disk_edge_next(e1, v)) && - (e1 != e2) && - /* make sure we come full circle and only have 2 connected edges */ - (e1 == bmesh_disk_edge_next(e2, v))) - { - BMVert *v1 = BM_edge_other_vert(e1, v); - BMVert *v2 = BM_edge_other_vert(e2, v); + if ((e1 = v->e) && (e2 = bmesh_disk_edge_next(e1, v)) && (e1 != e2) && + /* make sure we come full circle and only have 2 connected edges */ + (e1 == bmesh_disk_edge_next(e2, v))) { + BMVert *v1 = BM_edge_other_vert(e1, v); + BMVert *v2 = BM_edge_other_vert(e2, v); - return (float)M_PI - angle_v3v3v3(v1->co, v->co, v2->co); - } - else { - return fallback; - } + return (float)M_PI - angle_v3v3v3(v1->co, v->co, v2->co); + } + else { + return fallback; + } } float BM_vert_calc_edge_angle(const BMVert *v) { - return BM_vert_calc_edge_angle_ex(v, DEG2RADF(90.0f)); + return BM_vert_calc_edge_angle_ex(v, DEG2RADF(90.0f)); } /** @@ -1806,57 +1777,57 @@ float BM_vert_calc_edge_angle(const BMVert *v) */ float BM_vert_calc_shell_factor(const BMVert *v) { - BMIter iter; - BMLoop *l; - float accum_shell = 0.0f; - float accum_angle = 0.0f; + BMIter iter; + BMLoop *l; + float accum_shell = 0.0f; + float accum_angle = 0.0f; - BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) { - const float face_angle = BM_loop_calc_face_angle(l); - accum_shell += shell_v3v3_normalized_to_dist(v->no, l->f->no) * face_angle; - accum_angle += face_angle; - } + BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) { + const float face_angle = BM_loop_calc_face_angle(l); + accum_shell += shell_v3v3_normalized_to_dist(v->no, l->f->no) * face_angle; + accum_angle += face_angle; + } - if (accum_angle != 0.0f) { - return accum_shell / accum_angle; - } - else { - return 1.0f; - } + if (accum_angle != 0.0f) { + return accum_shell / accum_angle; + } + else { + return 1.0f; + } } /* alternate version of #BM_vert_calc_shell_factor which only * uses 'hflag' faces, but falls back to all if none found. */ float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag) { - BMIter iter; - const BMLoop *l; - float accum_shell = 0.0f; - float accum_angle = 0.0f; - int tot_sel = 0, tot = 0; - - BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) { - if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */ - const float face_angle = BM_loop_calc_face_angle(l); - accum_shell += shell_v3v3_normalized_to_dist(no, l->f->no) * face_angle; - accum_angle += face_angle; - tot_sel++; - } - tot++; - } - - if (accum_angle != 0.0f) { - return accum_shell / accum_angle; - } - else { - /* other main difference from BM_vert_calc_shell_factor! */ - if (tot != 0 && tot_sel == 0) { - /* none selected, so use all */ - return BM_vert_calc_shell_factor(v); - } - else { - return 1.0f; - } - } + BMIter iter; + const BMLoop *l; + float accum_shell = 0.0f; + float accum_angle = 0.0f; + int tot_sel = 0, tot = 0; + + BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) { + if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */ + const float face_angle = BM_loop_calc_face_angle(l); + accum_shell += shell_v3v3_normalized_to_dist(no, l->f->no) * face_angle; + accum_angle += face_angle; + tot_sel++; + } + tot++; + } + + if (accum_angle != 0.0f) { + return accum_shell / accum_angle; + } + else { + /* other main difference from BM_vert_calc_shell_factor! */ + if (tot != 0 && tot_sel == 0) { + /* none selected, so use all */ + return BM_vert_calc_shell_factor(v); + } + else { + return 1.0f; + } + } } /** @@ -1865,49 +1836,49 @@ float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const cha */ float BM_vert_calc_median_tagged_edge_length(const BMVert *v) { - BMIter iter; - BMEdge *e; - int tot; - float length = 0.0f; + BMIter iter; + BMEdge *e; + int tot; + float length = 0.0f; - BM_ITER_ELEM_INDEX (e, &iter, (BMVert *)v, BM_EDGES_OF_VERT, tot) { - const BMVert *v_other = BM_edge_other_vert(e, v); - if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) { - length += BM_edge_calc_length(e); - } - } + BM_ITER_ELEM_INDEX(e, &iter, (BMVert *)v, BM_EDGES_OF_VERT, tot) + { + const BMVert *v_other = BM_edge_other_vert(e, v); + if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) { + length += BM_edge_calc_length(e); + } + } - if (tot) { - return length / (float)tot; - } - else { - return 0.0f; - } + if (tot) { + return length / (float)tot; + } + else { + return 0.0f; + } } - /** * Returns the loop of the shortest edge in f. */ BMLoop *BM_face_find_shortest_loop(BMFace *f) { - BMLoop *shortest_loop = NULL; - float shortest_len = FLT_MAX; + BMLoop *shortest_loop = NULL; + float shortest_len = FLT_MAX; - BMLoop *l_iter; - BMLoop *l_first; + BMLoop *l_iter; + BMLoop *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co); - if (len_sq <= shortest_len) { - shortest_loop = l_iter; - shortest_len = len_sq; - } - } while ((l_iter = l_iter->next) != l_first); + do { + const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co); + if (len_sq <= shortest_len) { + shortest_loop = l_iter; + shortest_len = len_sq; + } + } while ((l_iter = l_iter->next) != l_first); - return shortest_loop; + return shortest_loop; } /** @@ -1915,23 +1886,23 @@ BMLoop *BM_face_find_shortest_loop(BMFace *f) */ BMLoop *BM_face_find_longest_loop(BMFace *f) { - BMLoop *longest_loop = NULL; - float len_max_sq = 0.0f; + BMLoop *longest_loop = NULL; + float len_max_sq = 0.0f; - BMLoop *l_iter; - BMLoop *l_first; + BMLoop *l_iter; + BMLoop *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co); - if (len_sq >= len_max_sq) { - longest_loop = l_iter; - len_max_sq = len_sq; - } - } while ((l_iter = l_iter->next) != l_first); + do { + const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co); + if (len_sq >= len_max_sq) { + longest_loop = l_iter; + len_max_sq = len_sq; + } + } while ((l_iter = l_iter->next) != l_first); - return longest_loop; + return longest_loop; } /** @@ -1943,46 +1914,46 @@ BMLoop *BM_face_find_longest_loop(BMFace *f) #if 0 BMEdge *BM_edge_exists(BMVert *v_a, BMVert *v_b) { - BMIter iter; - BMEdge *e; + BMIter iter; + BMEdge *e; - BLI_assert(v_a != v_b); - BLI_assert(v_a->head.htype == BM_VERT && v_b->head.htype == BM_VERT); + BLI_assert(v_a != v_b); + BLI_assert(v_a->head.htype == BM_VERT && v_b->head.htype == BM_VERT); - BM_ITER_ELEM (e, &iter, v_a, BM_EDGES_OF_VERT) { - if (e->v1 == v_b || e->v2 == v_b) - return e; - } + BM_ITER_ELEM (e, &iter, v_a, BM_EDGES_OF_VERT) { + if (e->v1 == v_b || e->v2 == v_b) + return e; + } - return NULL; + return NULL; } #else BMEdge *BM_edge_exists(BMVert *v_a, BMVert *v_b) { - /* speedup by looping over both edges verts - * where one vert may connect to many edges but not the other. */ + /* speedup by looping over both edges verts + * where one vert may connect to many edges but not the other. */ - BMEdge *e_a, *e_b; + BMEdge *e_a, *e_b; - BLI_assert(v_a != v_b); - BLI_assert(v_a->head.htype == BM_VERT && v_b->head.htype == BM_VERT); + BLI_assert(v_a != v_b); + BLI_assert(v_a->head.htype == BM_VERT && v_b->head.htype == BM_VERT); - if ((e_a = v_a->e) && (e_b = v_b->e)) { - BMEdge *e_a_iter = e_a, *e_b_iter = e_b; + if ((e_a = v_a->e) && (e_b = v_b->e)) { + BMEdge *e_a_iter = e_a, *e_b_iter = e_b; - do { - if (BM_vert_in_edge(e_a_iter, v_b)) { - return e_a_iter; - } - if (BM_vert_in_edge(e_b_iter, v_a)) { - return e_b_iter; - } - } while (((e_a_iter = bmesh_disk_edge_next(e_a_iter, v_a)) != e_a) && - ((e_b_iter = bmesh_disk_edge_next(e_b_iter, v_b)) != e_b)); - } + do { + if (BM_vert_in_edge(e_a_iter, v_b)) { + return e_a_iter; + } + if (BM_vert_in_edge(e_b_iter, v_a)) { + return e_b_iter; + } + } while (((e_a_iter = bmesh_disk_edge_next(e_a_iter, v_a)) != e_a) && + ((e_b_iter = bmesh_disk_edge_next(e_b_iter, v_b)) != e_b)); + } - return NULL; + return NULL; } #endif @@ -1993,19 +1964,19 @@ BMEdge *BM_edge_exists(BMVert *v_a, BMVert *v_b) */ BMEdge *BM_edge_find_double(BMEdge *e) { - BMVert *v = e->v1; - BMVert *v_other = e->v2; + BMVert *v = e->v1; + BMVert *v_other = e->v2; - BMEdge *e_iter; + BMEdge *e_iter; - e_iter = e; - while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e) { - if (UNLIKELY(BM_vert_in_edge(e_iter, v_other))) { - return e_iter; - } - } + e_iter = e; + while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e) { + if (UNLIKELY(BM_vert_in_edge(e_iter, v_other))) { + return e_iter; + } + } - return NULL; + return NULL; } /** @@ -2014,16 +1985,16 @@ BMEdge *BM_edge_find_double(BMEdge *e) */ BMLoop *BM_edge_find_first_loop_visible(BMEdge *e) { - if (e->l != NULL) { - BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) { - return l_iter; - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - return NULL; + if (e->l != NULL) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) { + return l_iter; + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + return NULL; } /** @@ -2035,53 +2006,50 @@ BMLoop *BM_edge_find_first_loop_visible(BMEdge *e) */ BMFace *BM_face_exists(BMVert **varr, int len) { - if (varr[0]->e) { - BMEdge *e_iter, *e_first; - e_iter = e_first = varr[0]->e; - - /* would normally use BM_LOOPS_OF_VERT, but this runs so often, - * its faster to iterate on the data directly */ - do { - if (e_iter->l) { - BMLoop *l_iter_radial, *l_first_radial; - l_iter_radial = l_first_radial = e_iter->l; - - do { - if ((l_iter_radial->v == varr[0]) && - (l_iter_radial->f->len == len)) - { - /* the fist 2 verts match, now check the remaining (len - 2) faces do too - * winding isn't known, so check in both directions */ - int i_walk = 2; - - if (l_iter_radial->next->v == varr[1]) { - BMLoop *l_walk = l_iter_radial->next->next; - do { - if (l_walk->v != varr[i_walk]) { - break; - } - } while ((void)(l_walk = l_walk->next), ++i_walk != len); - } - else if (l_iter_radial->prev->v == varr[1]) { - BMLoop *l_walk = l_iter_radial->prev->prev; - do { - if (l_walk->v != varr[i_walk]) { - break; - } - } while ((void)(l_walk = l_walk->prev), ++i_walk != len); - } - - if (i_walk == len) { - return l_iter_radial->f; - } - } - } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial); - - } - } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, varr[0])) != e_first); - } - - return NULL; + if (varr[0]->e) { + BMEdge *e_iter, *e_first; + e_iter = e_first = varr[0]->e; + + /* would normally use BM_LOOPS_OF_VERT, but this runs so often, + * its faster to iterate on the data directly */ + do { + if (e_iter->l) { + BMLoop *l_iter_radial, *l_first_radial; + l_iter_radial = l_first_radial = e_iter->l; + + do { + if ((l_iter_radial->v == varr[0]) && (l_iter_radial->f->len == len)) { + /* the fist 2 verts match, now check the remaining (len - 2) faces do too + * winding isn't known, so check in both directions */ + int i_walk = 2; + + if (l_iter_radial->next->v == varr[1]) { + BMLoop *l_walk = l_iter_radial->next->next; + do { + if (l_walk->v != varr[i_walk]) { + break; + } + } while ((void)(l_walk = l_walk->next), ++i_walk != len); + } + else if (l_iter_radial->prev->v == varr[1]) { + BMLoop *l_walk = l_iter_radial->prev->prev; + do { + if (l_walk->v != varr[i_walk]) { + break; + } + } while ((void)(l_walk = l_walk->prev), ++i_walk != len); + } + + if (i_walk == len) { + return l_iter_radial->f; + } + } + } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial); + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, varr[0])) != e_first); + } + + return NULL; } /** @@ -2089,34 +2057,34 @@ BMFace *BM_face_exists(BMVert **varr, int len) */ BMFace *BM_face_find_double(BMFace *f) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - for (BMLoop *l_iter = l_first->radial_next; l_first != l_iter; l_iter = l_iter->radial_next) { - if (l_iter->f->len == l_first->f->len) { - if (l_iter->v == l_first->v) { - BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter; - do { - if (l_a->e != l_b->e) { - break; - } - } while (((void)(l_a = l_a->next), (l_b = l_b->next)) != l_b_init); - if (l_b == l_b_init) { - return l_iter->f; - } - } - else { - BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter; - do { - if (l_a->e != l_b->e) { - break; - } - } while (((void)(l_a = l_a->prev), (l_b = l_b->next)) != l_b_init); - if (l_b == l_b_init) { - return l_iter->f; - } - } - } - } - return NULL; + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + for (BMLoop *l_iter = l_first->radial_next; l_first != l_iter; l_iter = l_iter->radial_next) { + if (l_iter->f->len == l_first->f->len) { + if (l_iter->v == l_first->v) { + BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter; + do { + if (l_a->e != l_b->e) { + break; + } + } while (((void)(l_a = l_a->next), (l_b = l_b->next)) != l_b_init); + if (l_b == l_b_init) { + return l_iter->f; + } + } + else { + BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter; + do { + if (l_a->e != l_b->e) { + break; + } + } while (((void)(l_a = l_a->prev), (l_b = l_b->next)) != l_b_init); + if (l_b == l_b_init) { + return l_iter->f; + } + } + } + } + return NULL; } /** @@ -2133,131 +2101,126 @@ BMFace *BM_face_find_double(BMFace *f) */ bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) { - BMFace *f; - BMEdge *e; - BMVert *v; - bool ok; - int tot_tag; - - BMIter fiter; - BMIter viter; - - int i; - - for (i = 0; i < len; i++) { - /* save some time by looping over edge faces rather then vert faces - * will still loop over some faces twice but not as many */ - BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) { - BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG); - BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) { - BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG); - } - } - - /* clear all edge tags */ - BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) { - BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); - } - } - - /* now tag all verts and edges in the boundary array as true so - * we can know if a face-vert is from our array */ - for (i = 0; i < len; i++) { - BM_elem_flag_enable(varr[i], BM_ELEM_INTERNAL_TAG); - BM_elem_flag_enable(earr[i], BM_ELEM_INTERNAL_TAG); - } - - - /* so! boundary is tagged, everything else cleared */ - - - /* 1) tag all faces connected to edges - if all their verts are boundary */ - tot_tag = 0; - for (i = 0; i < len; i++) { - BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) { - if (!BM_elem_flag_test(f, BM_ELEM_INTERNAL_TAG)) { - ok = true; - BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) { - if (!BM_elem_flag_test(v, BM_ELEM_INTERNAL_TAG)) { - ok = false; - break; - } - } - - if (ok) { - /* we only use boundary verts */ - BM_elem_flag_enable(f, BM_ELEM_INTERNAL_TAG); - tot_tag++; - } - } - else { - /* we already found! */ - } - } - } - - if (tot_tag == 0) { - /* no faces use only boundary verts, quit early */ - ok = false; - goto finally; - } - - /* 2) loop over non-boundary edges that use boundary verts, - * check each have 2 tagged faces connected (faces that only use 'varr' verts) */ - ok = true; - for (i = 0; i < len; i++) { - BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) { - - if (/* non-boundary edge */ - BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) == false && - /* ...using boundary verts */ - BM_elem_flag_test(e->v1, BM_ELEM_INTERNAL_TAG) && - BM_elem_flag_test(e->v2, BM_ELEM_INTERNAL_TAG)) - { - int tot_face_tag = 0; - BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { - if (BM_elem_flag_test(f, BM_ELEM_INTERNAL_TAG)) { - tot_face_tag++; - } - } - - if (tot_face_tag != 2) { - ok = false; - break; - } - - } - } - - if (ok == false) { - break; - } - } + BMFace *f; + BMEdge *e; + BMVert *v; + bool ok; + int tot_tag; + + BMIter fiter; + BMIter viter; + + int i; + + for (i = 0; i < len; i++) { + /* save some time by looping over edge faces rather then vert faces + * will still loop over some faces twice but not as many */ + BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) { + BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG); + BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) { + BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG); + } + } + + /* clear all edge tags */ + BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) { + BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); + } + } + + /* now tag all verts and edges in the boundary array as true so + * we can know if a face-vert is from our array */ + for (i = 0; i < len; i++) { + BM_elem_flag_enable(varr[i], BM_ELEM_INTERNAL_TAG); + BM_elem_flag_enable(earr[i], BM_ELEM_INTERNAL_TAG); + } + + /* so! boundary is tagged, everything else cleared */ + + /* 1) tag all faces connected to edges - if all their verts are boundary */ + tot_tag = 0; + for (i = 0; i < len; i++) { + BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) { + if (!BM_elem_flag_test(f, BM_ELEM_INTERNAL_TAG)) { + ok = true; + BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) { + if (!BM_elem_flag_test(v, BM_ELEM_INTERNAL_TAG)) { + ok = false; + break; + } + } + + if (ok) { + /* we only use boundary verts */ + BM_elem_flag_enable(f, BM_ELEM_INTERNAL_TAG); + tot_tag++; + } + } + else { + /* we already found! */ + } + } + } + + if (tot_tag == 0) { + /* no faces use only boundary verts, quit early */ + ok = false; + goto finally; + } + + /* 2) loop over non-boundary edges that use boundary verts, + * check each have 2 tagged faces connected (faces that only use 'varr' verts) */ + ok = true; + for (i = 0; i < len; i++) { + BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) { + + if (/* non-boundary edge */ + BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) == false && + /* ...using boundary verts */ + BM_elem_flag_test(e->v1, BM_ELEM_INTERNAL_TAG) && + BM_elem_flag_test(e->v2, BM_ELEM_INTERNAL_TAG)) { + int tot_face_tag = 0; + BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { + if (BM_elem_flag_test(f, BM_ELEM_INTERNAL_TAG)) { + tot_face_tag++; + } + } + + if (tot_face_tag != 2) { + ok = false; + break; + } + } + } + + if (ok == false) { + break; + } + } finally: - /* Cleanup */ - for (i = 0; i < len; i++) { - BM_elem_flag_disable(varr[i], BM_ELEM_INTERNAL_TAG); - BM_elem_flag_disable(earr[i], BM_ELEM_INTERNAL_TAG); - } - return ok; + /* Cleanup */ + for (i = 0; i < len; i++) { + BM_elem_flag_disable(varr[i], BM_ELEM_INTERNAL_TAG); + BM_elem_flag_disable(earr[i], BM_ELEM_INTERNAL_TAG); + } + return ok; } /* same as 'BM_face_exists_multi' but built vert array from edges */ bool BM_face_exists_multi_edge(BMEdge **earr, int len) { - BMVert **varr = BLI_array_alloca(varr, len); + BMVert **varr = BLI_array_alloca(varr, len); - /* first check if verts have edges, if not we can bail out early */ - if (!BM_verts_from_edges(varr, earr, len)) { - BMESH_ASSERT(0); - return false; - } + /* first check if verts have edges, if not we can bail out early */ + if (!BM_verts_from_edges(varr, earr, len)) { + BMESH_ASSERT(0); + return false; + } - return BM_face_exists_multi(varr, earr, len); + return BM_face_exists_multi(varr, earr, len); } - /** * Given a set of vertices (varr), find out if * all those vertices overlap an existing face. @@ -2274,40 +2237,40 @@ bool BM_face_exists_multi_edge(BMEdge **earr, int len) BMFace *BM_face_exists_overlap(BMVert **varr, const int len) { - BMIter viter; - BMFace *f; - int i; - BMFace *f_overlap = NULL; - LinkNode *f_lnk = NULL; + BMIter viter; + BMFace *f; + int i; + BMFace *f_overlap = NULL; + LinkNode *f_lnk = NULL; #ifdef DEBUG - /* check flag isn't already set */ - for (i = 0; i < len; i++) { - BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0); - } - } + /* check flag isn't already set */ + for (i = 0; i < len; i++) { + BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { + BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0); + } + } #endif - for (i = 0; i < len; i++) { - BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - if (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0) { - if (len <= BM_verts_in_face_count(varr, len, f)) { - f_overlap = f; - break; - } + for (i = 0; i < len; i++) { + BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { + if (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0) { + if (len <= BM_verts_in_face_count(varr, len, f)) { + f_overlap = f; + break; + } - BM_ELEM_API_FLAG_ENABLE(f, _FLAG_OVERLAP); - BLI_linklist_prepend_alloca(&f_lnk, f); - } - } - } + BM_ELEM_API_FLAG_ENABLE(f, _FLAG_OVERLAP); + BLI_linklist_prepend_alloca(&f_lnk, f); + } + } + } - for (; f_lnk; f_lnk = f_lnk->next) { - BM_ELEM_API_FLAG_DISABLE((BMFace *)f_lnk->link, _FLAG_OVERLAP); - } + for (; f_lnk; f_lnk = f_lnk->next) { + BM_ELEM_API_FLAG_DISABLE((BMFace *)f_lnk->link, _FLAG_OVERLAP); + } - return f_overlap; + return f_overlap; } /** @@ -2320,155 +2283,153 @@ BMFace *BM_face_exists_overlap(BMVert **varr, const int len) */ bool BM_face_exists_overlap_subset(BMVert **varr, const int len) { - BMIter viter; - BMFace *f; - bool is_init = false; - bool is_overlap = false; - LinkNode *f_lnk = NULL; + BMIter viter; + BMFace *f; + bool is_init = false; + bool is_overlap = false; + LinkNode *f_lnk = NULL; #ifdef DEBUG - /* check flag isn't already set */ - for (int i = 0; i < len; i++) { - BLI_assert(BM_ELEM_API_FLAG_TEST(varr[i], _FLAG_OVERLAP) == 0); - BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0); - } - } + /* check flag isn't already set */ + for (int i = 0; i < len; i++) { + BLI_assert(BM_ELEM_API_FLAG_TEST(varr[i], _FLAG_OVERLAP) == 0); + BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { + BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0); + } + } #endif - for (int i = 0; i < len; i++) { - BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - if ((f->len <= len) && (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0)) { - /* check if all vers in this face are flagged*/ - BMLoop *l_iter, *l_first; - - if (is_init == false) { - is_init = true; - for (int j = 0; j < len; j++) { - BM_ELEM_API_FLAG_ENABLE(varr[j], _FLAG_OVERLAP); - } - } - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - is_overlap = true; - do { - if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP) == 0) { - is_overlap = false; - break; - } - } while ((l_iter = l_iter->next) != l_first); - - if (is_overlap) { - break; - } - - BM_ELEM_API_FLAG_ENABLE(f, _FLAG_OVERLAP); - BLI_linklist_prepend_alloca(&f_lnk, f); - } - } - } - - if (is_init == true) { - for (int i = 0; i < len; i++) { - BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); - } - } - - for (; f_lnk; f_lnk = f_lnk->next) { - BM_ELEM_API_FLAG_DISABLE((BMFace *)f_lnk->link, _FLAG_OVERLAP); - } - - return is_overlap; + for (int i = 0; i < len; i++) { + BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { + if ((f->len <= len) && (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0)) { + /* check if all vers in this face are flagged*/ + BMLoop *l_iter, *l_first; + + if (is_init == false) { + is_init = true; + for (int j = 0; j < len; j++) { + BM_ELEM_API_FLAG_ENABLE(varr[j], _FLAG_OVERLAP); + } + } + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + is_overlap = true; + do { + if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP) == 0) { + is_overlap = false; + break; + } + } while ((l_iter = l_iter->next) != l_first); + + if (is_overlap) { + break; + } + + BM_ELEM_API_FLAG_ENABLE(f, _FLAG_OVERLAP); + BLI_linklist_prepend_alloca(&f_lnk, f); + } + } + } + + if (is_init == true) { + for (int i = 0; i < len; i++) { + BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); + } + } + + for (; f_lnk; f_lnk = f_lnk->next) { + BM_ELEM_API_FLAG_DISABLE((BMFace *)f_lnk->link, _FLAG_OVERLAP); + } + + return is_overlap; } bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide) { - if (v->e) { - BMEdge *e_other; - BMIter eiter; + if (v->e) { + BMEdge *e_other; + BMIter eiter; - BM_ITER_ELEM (e_other, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) { - if (!respect_hide || !BM_elem_flag_test(e_other, BM_ELEM_HIDDEN)) { - if (!BM_elem_flag_test(e_other, hflag)) { - return false; - } - } - } - } + BM_ITER_ELEM (e_other, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) { + if (!respect_hide || !BM_elem_flag_test(e_other, BM_ELEM_HIDDEN)) { + if (!BM_elem_flag_test(e_other, hflag)) { + return false; + } + } + } + } - return true; + return true; } bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide) { - if (v->e) { - BMEdge *f_other; - BMIter fiter; + if (v->e) { + BMEdge *f_other; + BMIter fiter; - BM_ITER_ELEM (f_other, &fiter, (BMVert *)v, BM_FACES_OF_VERT) { - if (!respect_hide || !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) { - if (!BM_elem_flag_test(f_other, hflag)) { - return false; - } - } - } - } + BM_ITER_ELEM (f_other, &fiter, (BMVert *)v, BM_FACES_OF_VERT) { + if (!respect_hide || !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) { + if (!BM_elem_flag_test(f_other, hflag)) { + return false; + } + } + } + } - return true; + return true; } - bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide) { - if (e->l) { - BMLoop *l_iter, *l_first; + if (e->l) { + BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - if (!respect_hide || !BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) { - if (!BM_elem_flag_test(l_iter->f, hflag)) { - return false; - } - } - } while ((l_iter = l_iter->radial_next) != l_first); - } + l_iter = l_first = e->l; + do { + if (!respect_hide || !BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) { + if (!BM_elem_flag_test(l_iter->f, hflag)) { + return false; + } + } + } while ((l_iter = l_iter->radial_next) != l_first); + } - return true; + return true; } /* convenience functions for checking flags */ bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag) { - return (BM_elem_flag_test(e->v1, hflag) || - BM_elem_flag_test(e->v2, hflag)); + return (BM_elem_flag_test(e->v1, hflag) || BM_elem_flag_test(e->v2, hflag)); } bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag) { - BMLoop *l_iter; - BMLoop *l_first; + BMLoop *l_iter; + BMLoop *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (BM_elem_flag_test(l_iter->v, hflag)) { - return true; - } - } while ((l_iter = l_iter->next) != l_first); - return false; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->v, hflag)) { + return true; + } + } while ((l_iter = l_iter->next) != l_first); + return false; } bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag) { - BMLoop *l_iter; - BMLoop *l_first; + BMLoop *l_iter; + BMLoop *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (BM_elem_flag_test(l_iter->e, hflag)) { - return true; - } - } while ((l_iter = l_iter->next) != l_first); - return false; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->e, hflag)) { + return true; + } + } while ((l_iter = l_iter->next) != l_first); + return false; } /** @@ -2476,49 +2437,49 @@ bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag) */ bool BM_face_is_normal_valid(const BMFace *f) { - const float eps = 0.0001f; - float no[3]; + const float eps = 0.0001f; + float no[3]; - BM_face_calc_normal(f, no); - return len_squared_v3v3(no, f->no) < (eps * eps); + BM_face_calc_normal(f, no); + return len_squared_v3v3(no, f->no) < (eps * eps); } static void bm_mesh_calc_volume_face(const BMFace *f, float *r_vol) { - const int tottri = f->len - 2; - BMLoop **loops = BLI_array_alloca(loops, f->len); - uint (*index)[3] = BLI_array_alloca(index, tottri); - int j; + const int tottri = f->len - 2; + BMLoop **loops = BLI_array_alloca(loops, f->len); + uint(*index)[3] = BLI_array_alloca(index, tottri); + int j; - BM_face_calc_tessellation(f, false, loops, index); + BM_face_calc_tessellation(f, false, loops, index); - for (j = 0; j < tottri; j++) { - const float *p1 = loops[index[j][0]]->v->co; - const float *p2 = loops[index[j][1]]->v->co; - const float *p3 = loops[index[j][2]]->v->co; + for (j = 0; j < tottri; j++) { + const float *p1 = loops[index[j][0]]->v->co; + const float *p2 = loops[index[j][1]]->v->co; + const float *p3 = loops[index[j][2]]->v->co; - /* co1.dot(co2.cross(co3)) / 6.0 */ - float cross[3]; - cross_v3_v3v3(cross, p2, p3); - *r_vol += (1.0f / 6.0f) * dot_v3v3(p1, cross); - } + /* co1.dot(co2.cross(co3)) / 6.0 */ + float cross[3]; + cross_v3_v3v3(cross, p2, p3); + *r_vol += (1.0f / 6.0f) * dot_v3v3(p1, cross); + } } float BM_mesh_calc_volume(BMesh *bm, bool is_signed) { - /* warning, calls own tessellation function, may be slow */ - float vol = 0.0f; - BMFace *f; - BMIter fiter; + /* warning, calls own tessellation function, may be slow */ + float vol = 0.0f; + BMFace *f; + BMIter fiter; - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - bm_mesh_calc_volume_face(f, &vol); - } + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + bm_mesh_calc_volume_face(f, &vol); + } - if (is_signed == false) { - vol = fabsf(vol); - } + if (is_signed == false) { + vol = fabsf(vol); + } - return vol; + return vol; } /* note, almost duplicate of BM_mesh_calc_edge_groups, keep in sync */ @@ -2538,143 +2499,144 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed) * (having both set is supported too). * \return The number of groups found. */ -int BM_mesh_calc_face_groups( - BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMLoopFilterFunc filter_fn, void *user_data, - const char hflag_test, const char htype_step) +int BM_mesh_calc_face_groups(BMesh *bm, + int *r_groups_array, + int (**r_group_index)[2], + BMLoopFilterFunc filter_fn, + void *user_data, + const char hflag_test, + const char htype_step) { #ifdef DEBUG - int group_index_len = 1; + int group_index_len = 1; #else - int group_index_len = 32; + int group_index_len = 32; #endif - int (*group_index)[2] = MEM_mallocN(sizeof(*group_index) * group_index_len, __func__); - - int *group_array = r_groups_array; - STACK_DECLARE(group_array); - - int group_curr = 0; - - uint tot_faces = 0; - uint tot_touch = 0; - - BMFace **stack; - STACK_DECLARE(stack); - - BMIter iter; - BMFace *f; - int i; - - STACK_INIT(group_array, bm->totface); - - BLI_assert(((htype_step & ~(BM_VERT | BM_EDGE)) == 0) && (htype_step != 0)); - - /* init the array */ - BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { - if ((hflag_test == 0) || BM_elem_flag_test(f, hflag_test)) { - tot_faces++; - BM_elem_flag_disable(f, BM_ELEM_TAG); - } - else { - /* never walk over tagged */ - BM_elem_flag_enable(f, BM_ELEM_TAG); - } - - BM_elem_index_set(f, i); /* set_inline */ - } - bm->elem_index_dirty &= ~BM_FACE; - - /* detect groups */ - stack = MEM_mallocN(sizeof(*stack) * tot_faces, __func__); - - while (tot_touch != tot_faces) { - int *group_item; - bool ok = false; - - BLI_assert(tot_touch < tot_faces); - - STACK_INIT(stack, tot_faces); - - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_TAG) == false) { - BM_elem_flag_enable(f, BM_ELEM_TAG); - STACK_PUSH(stack, f); - ok = true; - break; - } - } - - BLI_assert(ok == true); - UNUSED_VARS_NDEBUG(ok); - - /* manage arrays */ - if (group_index_len == group_curr) { - group_index_len *= 2; - group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len); - } - - group_item = group_index[group_curr]; - group_item[0] = STACK_SIZE(group_array); - group_item[1] = 0; - - while ((f = STACK_POP(stack))) { - BMLoop *l_iter, *l_first; - - /* add face */ - STACK_PUSH(group_array, BM_elem_index_get(f)); - tot_touch++; - group_item[1]++; - /* done */ - - if (htype_step & BM_EDGE) { - /* search for other faces */ - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BMLoop *l_radial_iter = l_iter->radial_next; - if ((l_radial_iter != l_iter) && - ((filter_fn == NULL) || filter_fn(l_iter, user_data))) - { - do { - BMFace *f_other = l_radial_iter->f; - if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) { - BM_elem_flag_enable(f_other, BM_ELEM_TAG); - STACK_PUSH(stack, f_other); - } - } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter); - } - } while ((l_iter = l_iter->next) != l_first); - } - - if (htype_step & BM_VERT) { - BMIter liter; - /* search for other faces */ - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if ((filter_fn == NULL) || filter_fn(l_iter, user_data)) { - BMLoop *l_other; - BM_ITER_ELEM (l_other, &liter, l_iter, BM_LOOPS_OF_LOOP) { - BMFace *f_other = l_other->f; - if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) { - BM_elem_flag_enable(f_other, BM_ELEM_TAG); - STACK_PUSH(stack, f_other); - } - } - } - } while ((l_iter = l_iter->next) != l_first); - } - } - - group_curr++; - } - - MEM_freeN(stack); - - /* reduce alloc to required size */ - group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr); - *r_group_index = group_index; - - return group_curr; + int(*group_index)[2] = MEM_mallocN(sizeof(*group_index) * group_index_len, __func__); + + int *group_array = r_groups_array; + STACK_DECLARE(group_array); + + int group_curr = 0; + + uint tot_faces = 0; + uint tot_touch = 0; + + BMFace **stack; + STACK_DECLARE(stack); + + BMIter iter; + BMFace *f; + int i; + + STACK_INIT(group_array, bm->totface); + + BLI_assert(((htype_step & ~(BM_VERT | BM_EDGE)) == 0) && (htype_step != 0)); + + /* init the array */ + BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { + if ((hflag_test == 0) || BM_elem_flag_test(f, hflag_test)) { + tot_faces++; + BM_elem_flag_disable(f, BM_ELEM_TAG); + } + else { + /* never walk over tagged */ + BM_elem_flag_enable(f, BM_ELEM_TAG); + } + + BM_elem_index_set(f, i); /* set_inline */ + } + bm->elem_index_dirty &= ~BM_FACE; + + /* detect groups */ + stack = MEM_mallocN(sizeof(*stack) * tot_faces, __func__); + + while (tot_touch != tot_faces) { + int *group_item; + bool ok = false; + + BLI_assert(tot_touch < tot_faces); + + STACK_INIT(stack, tot_faces); + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_TAG) == false) { + BM_elem_flag_enable(f, BM_ELEM_TAG); + STACK_PUSH(stack, f); + ok = true; + break; + } + } + + BLI_assert(ok == true); + UNUSED_VARS_NDEBUG(ok); + + /* manage arrays */ + if (group_index_len == group_curr) { + group_index_len *= 2; + group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len); + } + + group_item = group_index[group_curr]; + group_item[0] = STACK_SIZE(group_array); + group_item[1] = 0; + + while ((f = STACK_POP(stack))) { + BMLoop *l_iter, *l_first; + + /* add face */ + STACK_PUSH(group_array, BM_elem_index_get(f)); + tot_touch++; + group_item[1]++; + /* done */ + + if (htype_step & BM_EDGE) { + /* search for other faces */ + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BMLoop *l_radial_iter = l_iter->radial_next; + if ((l_radial_iter != l_iter) && ((filter_fn == NULL) || filter_fn(l_iter, user_data))) { + do { + BMFace *f_other = l_radial_iter->f; + if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) { + BM_elem_flag_enable(f_other, BM_ELEM_TAG); + STACK_PUSH(stack, f_other); + } + } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter); + } + } while ((l_iter = l_iter->next) != l_first); + } + + if (htype_step & BM_VERT) { + BMIter liter; + /* search for other faces */ + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if ((filter_fn == NULL) || filter_fn(l_iter, user_data)) { + BMLoop *l_other; + BM_ITER_ELEM (l_other, &liter, l_iter, BM_LOOPS_OF_LOOP) { + BMFace *f_other = l_other->f; + if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) { + BM_elem_flag_enable(f_other, BM_ELEM_TAG); + STACK_PUSH(stack, f_other); + } + } + } + } while ((l_iter = l_iter->next) != l_first); + } + } + + group_curr++; + } + + MEM_freeN(stack); + + /* reduce alloc to required size */ + group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr); + *r_group_index = group_index; + + return group_curr; } /* note, almost duplicate of BM_mesh_calc_face_groups, keep in sync */ @@ -2696,145 +2658,147 @@ int BM_mesh_calc_face_groups( * \note Unlike #BM_mesh_calc_face_groups there is no 'htype_step' argument, * since we always walk over verts. */ -int BM_mesh_calc_edge_groups( - BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMVertFilterFunc filter_fn, void *user_data, - const char hflag_test) +int BM_mesh_calc_edge_groups(BMesh *bm, + int *r_groups_array, + int (**r_group_index)[2], + BMVertFilterFunc filter_fn, + void *user_data, + const char hflag_test) { #ifdef DEBUG - int group_index_len = 1; + int group_index_len = 1; #else - int group_index_len = 32; + int group_index_len = 32; #endif - int (*group_index)[2] = MEM_mallocN(sizeof(*group_index) * group_index_len, __func__); - - int *group_array = r_groups_array; - STACK_DECLARE(group_array); + int(*group_index)[2] = MEM_mallocN(sizeof(*group_index) * group_index_len, __func__); + + int *group_array = r_groups_array; + STACK_DECLARE(group_array); - int group_curr = 0; + int group_curr = 0; - uint tot_edges = 0; - uint tot_touch = 0; + uint tot_edges = 0; + uint tot_touch = 0; - BMEdge **stack; - STACK_DECLARE(stack); + BMEdge **stack; + STACK_DECLARE(stack); - BMIter iter; - BMEdge *e; - int i; + BMIter iter; + BMEdge *e; + int i; - STACK_INIT(group_array, bm->totedge); + STACK_INIT(group_array, bm->totedge); - /* init the array */ - BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { - if ((hflag_test == 0) || BM_elem_flag_test(e, hflag_test)) { - tot_edges++; - BM_elem_flag_disable(e, BM_ELEM_TAG); - } - else { - /* never walk over tagged */ - BM_elem_flag_enable(e, BM_ELEM_TAG); - } + /* init the array */ + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + if ((hflag_test == 0) || BM_elem_flag_test(e, hflag_test)) { + tot_edges++; + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + else { + /* never walk over tagged */ + BM_elem_flag_enable(e, BM_ELEM_TAG); + } - BM_elem_index_set(e, i); /* set_inline */ - } - bm->elem_index_dirty &= ~BM_EDGE; + BM_elem_index_set(e, i); /* set_inline */ + } + bm->elem_index_dirty &= ~BM_EDGE; - /* detect groups */ - stack = MEM_mallocN(sizeof(*stack) * tot_edges, __func__); + /* detect groups */ + stack = MEM_mallocN(sizeof(*stack) * tot_edges, __func__); - while (tot_touch != tot_edges) { - int *group_item; - bool ok = false; + while (tot_touch != tot_edges) { + int *group_item; + bool ok = false; - BLI_assert(tot_touch < tot_edges); + BLI_assert(tot_touch < tot_edges); - STACK_INIT(stack, tot_edges); + STACK_INIT(stack, tot_edges); - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) { - BM_elem_flag_enable(e, BM_ELEM_TAG); - STACK_PUSH(stack, e); - ok = true; - break; - } - } + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + STACK_PUSH(stack, e); + ok = true; + break; + } + } - BLI_assert(ok == true); - UNUSED_VARS_NDEBUG(ok); + BLI_assert(ok == true); + UNUSED_VARS_NDEBUG(ok); - /* manage arrays */ - if (group_index_len == group_curr) { - group_index_len *= 2; - group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len); - } + /* manage arrays */ + if (group_index_len == group_curr) { + group_index_len *= 2; + group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len); + } - group_item = group_index[group_curr]; - group_item[0] = STACK_SIZE(group_array); - group_item[1] = 0; + group_item = group_index[group_curr]; + group_item[0] = STACK_SIZE(group_array); + group_item[1] = 0; - while ((e = STACK_POP(stack))) { - BMIter viter; - BMIter eiter; - BMVert *v; + while ((e = STACK_POP(stack))) { + BMIter viter; + BMIter eiter; + BMVert *v; - /* add edge */ - STACK_PUSH(group_array, BM_elem_index_get(e)); - tot_touch++; - group_item[1]++; - /* done */ + /* add edge */ + STACK_PUSH(group_array, BM_elem_index_get(e)); + tot_touch++; + group_item[1]++; + /* done */ - /* search for other edges */ - BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) { - if ((filter_fn == NULL) || filter_fn(v, user_data)) { - BMEdge *e_other; - BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) { - if (BM_elem_flag_test(e_other, BM_ELEM_TAG) == false) { - BM_elem_flag_enable(e_other, BM_ELEM_TAG); - STACK_PUSH(stack, e_other); - } - } - } - } - } + /* search for other edges */ + BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) { + if ((filter_fn == NULL) || filter_fn(v, user_data)) { + BMEdge *e_other; + BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e_other, BM_ELEM_TAG) == false) { + BM_elem_flag_enable(e_other, BM_ELEM_TAG); + STACK_PUSH(stack, e_other); + } + } + } + } + } - group_curr++; - } + group_curr++; + } - MEM_freeN(stack); + MEM_freeN(stack); - /* reduce alloc to required size */ - group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr); - *r_group_index = group_index; - - return group_curr; + /* reduce alloc to required size */ + group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr); + *r_group_index = group_index; + + return group_curr; } float bmesh_subd_falloff_calc(const int falloff, float val) { - switch (falloff) { - case SUBD_FALLOFF_SMOOTH: - val = 3.0f * val * val - 2.0f * val * val * val; - break; - case SUBD_FALLOFF_SPHERE: - val = sqrtf(2.0f * val - val * val); - break; - case SUBD_FALLOFF_ROOT: - val = sqrtf(val); - break; - case SUBD_FALLOFF_SHARP: - val = val * val; - break; - case SUBD_FALLOFF_LIN: - break; - case SUBD_FALLOFF_INVSQUARE: - val = val * (2.0f - val); - break; - default: - BLI_assert(0); - break; - } - - return val; + switch (falloff) { + case SUBD_FALLOFF_SMOOTH: + val = 3.0f * val * val - 2.0f * val * val * val; + break; + case SUBD_FALLOFF_SPHERE: + val = sqrtf(2.0f * val - val * val); + break; + case SUBD_FALLOFF_ROOT: + val = sqrtf(val); + break; + case SUBD_FALLOFF_SHARP: + val = val * val; + break; + case SUBD_FALLOFF_LIN: + break; + case SUBD_FALLOFF_INVSQUARE: + val = val * (2.0f - val); + break; + default: + BLI_assert(0); + break; + } + + return val; } diff --git a/source/blender/bmesh/intern/bmesh_query.h b/source/blender/bmesh/intern/bmesh_query.h index c04c7f5e97d..e96984490c0 100644 --- a/source/blender/bmesh/intern/bmesh_query.h +++ b/source/blender/bmesh/intern/bmesh_query.h @@ -21,25 +21,33 @@ * \ingroup bmesh */ -bool BM_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); - -bool BM_edge_in_face(const BMEdge *e, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); - -BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); - -float BM_edge_calc_length(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_edge_calc_length_squared(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) ATTR_NONNULL(); -bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) ATTR_NONNULL(); -BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); + +bool BM_edge_in_face(const BMEdge *e, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); + +BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, + const BMVert *v2, + const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); + +float BM_edge_calc_length(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_edge_calc_length_squared(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) ATTR_NONNULL(); +bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) ATTR_NONNULL(); +BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -47,89 +55,115 @@ BMLoop *BM_vert_find_first_loop(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL( BMLoop *BM_vert_find_first_loop_visible(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *BM_edge_find_first_loop_visible(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_vert_pair_share_face_check( - BMVert *v_a, BMVert *v_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_vert_pair_share_face_check_cb( - BMVert *v_a, BMVert *v_b, - bool (*test_fn)(BMFace *f, void *user_data), void *user_data) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); -BMFace *BM_vert_pair_share_face_by_len( - BMVert *v_a, BMVert *v_b, - BMLoop **r_l_a, BMLoop **r_l_b, - const bool allow_adjacent) ATTR_NONNULL(); -BMFace *BM_vert_pair_share_face_by_angle( - BMVert *v_a, BMVert *v_b, - BMLoop **r_l_a, BMLoop **r_l_b, - const bool allow_adjacent) ATTR_NONNULL(); - -BMFace *BM_edge_pair_share_face_by_len( - BMEdge *e_a, BMEdge *e_b, - BMLoop **r_l_a, BMLoop **r_l_b, - const bool allow_adjacent) ATTR_NONNULL(); - -int BM_vert_edge_count_nonwire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +bool BM_vert_pair_share_face_check_cb(BMVert *v_a, + BMVert *v_b, + bool (*test_fn)(BMFace *f, void *user_data), + void *user_data) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(1, 2, 3); +BMFace *BM_vert_pair_share_face_by_len(BMVert *v_a, + BMVert *v_b, + BMLoop **r_l_a, + BMLoop **r_l_b, + const bool allow_adjacent) ATTR_NONNULL(); +BMFace *BM_vert_pair_share_face_by_angle(BMVert *v_a, + BMVert *v_b, + BMLoop **r_l_a, + BMLoop **r_l_b, + const bool allow_adjacent) ATTR_NONNULL(); + +BMFace *BM_edge_pair_share_face_by_len(BMEdge *e_a, + BMEdge *e_b, + BMLoop **r_l_a, + BMLoop **r_l_b, + const bool allow_adjacent) ATTR_NONNULL(); + +int BM_vert_edge_count_nonwire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); #define BM_vert_edge_count_is_equal(v, n) (BM_vert_edge_count_at_most(v, (n) + 1) == n) #define BM_vert_edge_count_is_over(v, n) (BM_vert_edge_count_at_most(v, (n) + 1) == (n) + 1) -int BM_vert_edge_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int BM_vert_edge_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BM_vert_edge_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +int BM_vert_edge_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); #define BM_edge_face_count_is_equal(e, n) (BM_edge_face_count_at_most(e, (n) + 1) == n) #define BM_edge_face_count_is_over(e, n) (BM_edge_face_count_at_most(e, (n) + 1) == (n) + 1) -int BM_edge_face_count_at_most(const BMEdge *e, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int BM_edge_face_count(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BM_edge_face_count_at_most(const BMEdge *e, const int count_max) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +int BM_edge_face_count(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); #define BM_vert_face_count_is_equal(v, n) (BM_vert_face_count_at_most(v, (n) + 1) == n) #define BM_vert_face_count_is_over(v, n) (BM_vert_face_count_at_most(v, (n) + 1) == (n) + 1) -int BM_vert_face_count_at_most(const BMVert *v, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int BM_vert_face_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BM_vert_face_count_at_most(const BMVert *v, int count_max) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +int BM_vert_face_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_vert_is_edge_pair(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_vert_is_edge_pair_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b); -bool BM_vert_face_check(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_vert_is_wire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); - -bool BM_vert_is_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_vert_is_manifold_region(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_edge_is_contiguous_loop_cd( - const BMEdge *e, - const int cd_loop_type, const int cd_loop_offset) - ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); - -int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); -int BM_loop_region_loops_count(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); -bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_is_edge_pair(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_is_edge_pair_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b); +bool BM_vert_face_check(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_is_wire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); + +bool BM_vert_is_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_is_manifold_region(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_edge_is_contiguous_loop_cd(const BMEdge *e, + const int cd_loop_type, + const int cd_loop_offset) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); + +int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(1); +int BM_loop_region_loops_count(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq); BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq); -float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); -float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); -float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3]) ATTR_NONNULL(); -void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]); -void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]); - -float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e, const float imat3[3][3], const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) ATTR_NONNULL(); - -float BM_vert_calc_edge_angle(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_shell_factor(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_median_tagged_edge_length(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); +float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); +float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3]) + ATTR_NONNULL(); +void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]); +void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]); + +float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, + const float fallback) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e, + const float imat3[3][3], + const float fallback) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, + const float imat3[3][3]) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) + ATTR_NONNULL(); + +float BM_vert_calc_edge_angle(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +float BM_vert_calc_shell_factor(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_shell_factor_ex(const BMVert *v, + const float no[3], + const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_median_tagged_edge_length(const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); BMLoop *BM_face_find_shortest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *BM_face_find_longest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -140,58 +174,73 @@ BMEdge *BM_edge_find_double(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMFace *BM_face_exists(BMVert **varr, int len) ATTR_NONNULL(1); BMFace *BM_face_find_double(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_face_exists_multi_edge(BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +bool BM_face_exists_multi_edge(BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMFace *BM_face_exists_overlap(BMVert **varr, const int len) ATTR_WARN_UNUSED_RESULT; -bool BM_face_exists_overlap_subset(BMVert **varr, const int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_face_exists_overlap_subset(BMVert **varr, const int len) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); -int BM_face_share_face_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BM_face_share_face_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_face_share_face_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_face_share_edge_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_face_share_face_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_face_share_edge_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) ATTR_NONNULL(); -void BM_edge_ordered_verts_ex( - const BMEdge *edge, BMVert **r_v1, BMVert **r_v2, - const BMLoop *edge_loop) ATTR_NONNULL(); - -bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); - -bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) ATTR_NONNULL(); +void BM_edge_ordered_verts_ex(const BMEdge *edge, + BMVert **r_v1, + BMVert **r_v2, + const BMLoop *edge_loop) ATTR_NONNULL(); + +bool BM_vert_is_all_edge_flag_test(const BMVert *v, + const char hflag, + const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_vert_is_all_face_flag_test(const BMVert *v, + const char hflag, + const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_edge_is_all_face_flag_test(const BMEdge *e, + const char hflag, + const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); + +bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); bool BM_face_is_normal_valid(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); float BM_mesh_calc_volume(BMesh *bm, bool is_signed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int BM_mesh_calc_face_groups( - BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMLoopFilterFunc filter_fn, void *user_data, - const char hflag_test, const char htype_step) - ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); -int BM_mesh_calc_edge_groups( - BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMVertFilterFunc filter_fn, void *user_data, - const char hflag_test) - ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); +int BM_mesh_calc_face_groups(BMesh *bm, + int *r_groups_array, + int (**r_group_index)[2], + BMLoopFilterFunc filter_fn, + void *user_data, + const char hflag_test, + const char htype_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); +int BM_mesh_calc_edge_groups(BMesh *bm, + int *r_groups_array, + int (**r_group_index)[2], + BMVertFilterFunc filter_fn, + void *user_data, + const char hflag_test) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); /* not really any good place to put this */ float bmesh_subd_falloff_calc(const int falloff, float val) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/bmesh/intern/bmesh_query_inline.h b/source/blender/bmesh/intern/bmesh_query_inline.h index 582aa55b600..90919cc361b 100644 --- a/source/blender/bmesh/intern/bmesh_query_inline.h +++ b/source/blender/bmesh/intern/bmesh_query_inline.h @@ -18,7 +18,6 @@ * \ingroup bmesh */ - #ifndef __BMESH_QUERY_INLINE_H__ #define __BMESH_QUERY_INLINE_H__ @@ -26,56 +25,54 @@ * Returns whether or not a given vertex is * is part of a given edge. */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE + bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) { - return (ELEM(v, e->v1, e->v2)); + return (ELEM(v, e->v1, e->v2)); } /** * Returns whether or not a given edge is part of a given loop. */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) -BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE + bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) { - return (l->e == e || l->prev->e == e); + return (l->e == e || l->prev->e == e); } /** * Returns whether or not two vertices are in * a given edge */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3) -BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3) BLI_INLINE + bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e) { - return ((e->v1 == v1 && e->v2 == v2) || - (e->v1 == v2 && e->v2 == v1)); + return ((e->v1 == v1 && e->v2 == v2) || (e->v1 == v2 && e->v2 == v1)); } /** * Given a edge and one of its vertices, returns * the other vertex. */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) -BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, + const BMVert *v) { - if (e->v1 == v) { - return e->v2; - } - else if (e->v2 == v) { - return e->v1; - } - return NULL; + if (e->v1 == v) { + return e->v2; + } + else if (e->v2 == v) { + return e->v1; + } + return NULL; } /** * Tests whether or not the edge is part of a wire. * (ie: has no faces attached to it) */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) { - return (e->l == NULL); + return (e->l == NULL); } /** @@ -84,17 +81,16 @@ BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) */ #if 1 /* fast path for checking manifold */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) { - const BMLoop *l = e->l; - return (l && (l->radial_next != l) && /* not 0 or 1 face users */ - (l->radial_next->radial_next == l)); /* 2 face users */ + const BMLoop *l = e->l; + return (l && (l->radial_next != l) && /* not 0 or 1 face users */ + (l->radial_next->radial_next == l)); /* 2 face users */ } #else BLI_INLINE int BM_edge_is_manifold(BMEdge *e) { - return (BM_edge_face_count(e) == 2); + return (BM_edge_face_count(e) == 2); } #endif @@ -102,14 +98,13 @@ BLI_INLINE int BM_edge_is_manifold(BMEdge *e) * Tests that the edge is manifold and * that both its faces point the same way. */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) { - const BMLoop *l = e->l; - const BMLoop *l_other; - return (l && ((l_other = l->radial_next) != l) && /* not 0 or 1 face users */ - (l_other->radial_next == l) && /* 2 face users */ - (l_other->v != l->v)); + const BMLoop *l = e->l; + const BMLoop *l_other; + return (l && ((l_other = l->radial_next) != l) && /* not 0 or 1 face users */ + (l_other->radial_next == l) && /* 2 face users */ + (l_other->v != l->v)); } /** @@ -118,48 +113,44 @@ BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) */ #if 1 /* fast path for checking boundary */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) { - const BMLoop *l = e->l; - return (l && (l->radial_next == l)); + const BMLoop *l = e->l; + return (l && (l->radial_next == l)); } #else BLI_INLINE int BM_edge_is_boundary(BMEdge *e) { - return (BM_edge_face_count(e) == 1); + return (BM_edge_face_count(e) == 1); } #endif /** * Tests whether one loop is next to another within the same face. */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) -BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE + bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) { - BLI_assert(l_a->f == l_b->f); - BLI_assert(l_a != l_b); - return (ELEM(l_b, l_a->next, l_a->prev)); + BLI_assert(l_a->f == l_b->f); + BLI_assert(l_a != l_b); + return (ELEM(l_b, l_a->next, l_a->prev)); } -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE bool BM_loop_is_manifold(const BMLoop *l) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_loop_is_manifold(const BMLoop *l) { - return ((l != l->radial_next) && - (l == l->radial_next->radial_next)); + return ((l != l->radial_next) && (l == l->radial_next->radial_next)); } /** * Check if we have a single wire edge user. */ -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE bool BM_vert_is_wire_endpoint(const BMVert *v) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_vert_is_wire_endpoint(const BMVert *v) { - const BMEdge *e = v->e; - if (e && e->l == NULL) { - return (BM_DISK_EDGE_NEXT(e, v) == e); - } - return false; + const BMEdge *e = v->e; + if (e && e->l == NULL) { + return (BM_DISK_EDGE_NEXT(e, v) == e); + } + return false; } #endif /* __BMESH_QUERY_INLINE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index a90d0d245d0..d9f68f8aa62 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -34,17 +34,17 @@ void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) { - if (e->v1 == v_src) { - e->v1 = v_dst; - e->v1_disk_link.next = e->v1_disk_link.prev = NULL; - } - else if (e->v2 == v_src) { - e->v2 = v_dst; - e->v2_disk_link.next = e->v2_disk_link.prev = NULL; - } - else { - BLI_assert(0); - } + if (e->v1 == v_src) { + e->v1 = v_dst; + e->v1_disk_link.next = e->v1_disk_link.prev = NULL; + } + else if (e->v2 == v_src) { + e->v2 = v_dst; + e->v2_disk_link.next = e->v2_disk_link.prev = NULL; + } + else { + BLI_assert(0); + } } /** @@ -54,34 +54,34 @@ void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) */ void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) { - /* swap out loops */ - if (e->l) { - BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - if (l_iter->v == v_src) { - l_iter->v = v_dst; - } - else if (l_iter->next->v == v_src) { - l_iter->next->v = v_dst; - } - else { - BLI_assert(l_iter->prev->v != v_src); - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - - /* swap out edges */ - bmesh_disk_vert_replace(e, v_dst, v_src); + /* swap out loops */ + if (e->l) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + if (l_iter->v == v_src) { + l_iter->v = v_dst; + } + else if (l_iter->next->v == v_src) { + l_iter->next->v = v_dst; + } + else { + BLI_assert(l_iter->prev->v != v_src); + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + + /* swap out edges */ + bmesh_disk_vert_replace(e, v_dst, v_src); } void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) { - BLI_assert(e->v1 == v_src || e->v2 == v_src); - bmesh_disk_edge_remove(e, v_src); /* remove e from tv's disk cycle */ - bmesh_disk_vert_swap(e, v_dst, v_src); /* swap out tv for v_new in e */ - bmesh_disk_edge_append(e, v_dst); /* add e to v_dst's disk cycle */ - BLI_assert(e->v1 != e->v2); + BLI_assert(e->v1 == v_src || e->v2 == v_src); + bmesh_disk_edge_remove(e, v_src); /* remove e from tv's disk cycle */ + bmesh_disk_vert_swap(e, v_dst, v_src); /* swap out tv for v_new in e */ + bmesh_disk_edge_append(e, v_dst); /* add e to v_dst's disk cycle */ + BLI_assert(e->v1 != e->v2); } /** @@ -155,116 +155,116 @@ void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) void bmesh_disk_edge_append(BMEdge *e, BMVert *v) { - if (!v->e) { - BMDiskLink *dl1 = bmesh_disk_edge_link_from_vert(e, v); - - v->e = e; - dl1->next = dl1->prev = e; - } - else { - BMDiskLink *dl1, *dl2, *dl3; - - dl1 = bmesh_disk_edge_link_from_vert(e, v); - dl2 = bmesh_disk_edge_link_from_vert(v->e, v); - dl3 = dl2->prev ? bmesh_disk_edge_link_from_vert(dl2->prev, v) : NULL; - - dl1->next = v->e; - dl1->prev = dl2->prev; - - dl2->prev = e; - if (dl3) { - dl3->next = e; - } - } + if (!v->e) { + BMDiskLink *dl1 = bmesh_disk_edge_link_from_vert(e, v); + + v->e = e; + dl1->next = dl1->prev = e; + } + else { + BMDiskLink *dl1, *dl2, *dl3; + + dl1 = bmesh_disk_edge_link_from_vert(e, v); + dl2 = bmesh_disk_edge_link_from_vert(v->e, v); + dl3 = dl2->prev ? bmesh_disk_edge_link_from_vert(dl2->prev, v) : NULL; + + dl1->next = v->e; + dl1->prev = dl2->prev; + + dl2->prev = e; + if (dl3) { + dl3->next = e; + } + } } void bmesh_disk_edge_remove(BMEdge *e, BMVert *v) { - BMDiskLink *dl1, *dl2; + BMDiskLink *dl1, *dl2; - dl1 = bmesh_disk_edge_link_from_vert(e, v); - if (dl1->prev) { - dl2 = bmesh_disk_edge_link_from_vert(dl1->prev, v); - dl2->next = dl1->next; - } + dl1 = bmesh_disk_edge_link_from_vert(e, v); + if (dl1->prev) { + dl2 = bmesh_disk_edge_link_from_vert(dl1->prev, v); + dl2->next = dl1->next; + } - if (dl1->next) { - dl2 = bmesh_disk_edge_link_from_vert(dl1->next, v); - dl2->prev = dl1->prev; - } + if (dl1->next) { + dl2 = bmesh_disk_edge_link_from_vert(dl1->next, v); + dl2->prev = dl1->prev; + } - if (v->e == e) { - v->e = (e != dl1->next) ? dl1->next : NULL; - } + if (v->e == e) { + v->e = (e != dl1->next) ? dl1->next : NULL; + } - dl1->next = dl1->prev = NULL; + dl1->next = dl1->prev = NULL; } BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) { - BMEdge *e_iter, *e_first; + BMEdge *e_iter, *e_first; - if (v1->e) { - e_first = e_iter = v1->e; + if (v1->e) { + e_first = e_iter = v1->e; - do { - if (BM_verts_in_edge(v1, v2, e_iter)) { - return e_iter; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v1)) != e_first); - } + do { + if (BM_verts_in_edge(v1, v2, e_iter)) { + return e_iter; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v1)) != e_first); + } - return NULL; + return NULL; } int bmesh_disk_count(const BMVert *v) { - int count = 0; - if (v->e) { - BMEdge *e_first, *e_iter; - e_iter = e_first = v->e; - do { - count++; - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - } - return count; + int count = 0; + if (v->e) { + BMEdge *e_first, *e_iter; + e_iter = e_first = v->e; + do { + count++; + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } + return count; } int bmesh_disk_count_at_most(const BMVert *v, const int count_max) { - int count = 0; - if (v->e) { - BMEdge *e_first, *e_iter; - e_iter = e_first = v->e; - do { - count++; - if (count == count_max) { - break; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - } - return count; + int count = 0; + if (v->e) { + BMEdge *e_first, *e_iter; + e_iter = e_first = v->e; + do { + count++; + if (count == count_max) { + break; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } + return count; } bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) { - BMEdge *e_iter; - - if (!BM_vert_in_edge(e, v)) { - return false; - } - if (len == 0 || bmesh_disk_count_at_most(v, len + 1) != len) { - return false; - } - - e_iter = e; - do { - if (len != 1 && bmesh_disk_edge_prev(e_iter, v) == e_iter) { - return false; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e); - - return true; + BMEdge *e_iter; + + if (!BM_vert_in_edge(e, v)) { + return false; + } + if (len == 0 || bmesh_disk_count_at_most(v, len + 1) != len) { + return false; + } + + e_iter = e; + do { + if (len != 1 && bmesh_disk_edge_prev(e_iter, v) == e_iter) { + return false; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e); + + return true; } /** @@ -277,41 +277,41 @@ bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) */ int bmesh_disk_facevert_count(const BMVert *v) { - /* is there an edge on this vert at all */ - int count = 0; - if (v->e) { - BMEdge *e_first, *e_iter; - - /* first, loop around edge */ - e_first = e_iter = v->e; - do { - if (e_iter->l) { - count += bmesh_radial_facevert_count(e_iter->l, v); - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - } - return count; + /* is there an edge on this vert at all */ + int count = 0; + if (v->e) { + BMEdge *e_first, *e_iter; + + /* first, loop around edge */ + e_first = e_iter = v->e; + do { + if (e_iter->l) { + count += bmesh_radial_facevert_count(e_iter->l, v); + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } + return count; } int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max) { - /* is there an edge on this vert at all */ - int count = 0; - if (v->e) { - BMEdge *e_first, *e_iter; - - /* first, loop around edge */ - e_first = e_iter = v->e; - do { - if (e_iter->l) { - count += bmesh_radial_facevert_count_at_most(e_iter->l, v, count_max - count); - if (count == count_max) { - break; - } - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - } - return count; + /* is there an edge on this vert at all */ + int count = 0; + if (v->e) { + BMEdge *e_first, *e_iter; + + /* first, loop around edge */ + e_first = e_iter = v->e; + do { + if (e_iter->l) { + count += bmesh_radial_facevert_count_at_most(e_iter->l, v, count_max - count); + if (count == count_max) { + break; + } + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } + return count; } /** @@ -324,13 +324,13 @@ int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max) */ BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) { - const BMEdge *e_iter = e; - do { - if (e_iter->l != NULL) { - return (BMEdge *)((e_iter->l->v == v) ? e_iter : e_iter->l->next->e); - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e); - return NULL; + const BMEdge *e_iter = e; + do { + if (e_iter->l != NULL) { + return (BMEdge *)((e_iter->l->v == v) ? e_iter : e_iter->l->next->e); + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e); + return NULL; } /** @@ -340,13 +340,13 @@ BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) */ BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v) { - const BMEdge *e_iter = e; - do { - if (e_iter->l != NULL) { - return (e_iter->l->v == v) ? e_iter->l : e_iter->l->next; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e); - return NULL; + const BMEdge *e_iter = e; + do { + if (e_iter->l != NULL) { + return (e_iter->l->v == v) ? e_iter->l : e_iter->l->next; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e); + return NULL; } /** @@ -354,91 +354,91 @@ BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v) */ BMLoop *bmesh_disk_faceloop_find_first_visible(const BMEdge *e, const BMVert *v) { - const BMEdge *e_iter = e; - do { - if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) { - if (e_iter->l != NULL) { - BMLoop *l_iter, *l_first; - l_iter = l_first = e_iter->l; - do { - if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) { - return (l_iter->v == v) ? l_iter : l_iter->next; - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e); - return NULL; + const BMEdge *e_iter = e; + do { + if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) { + if (e_iter->l != NULL) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e_iter->l; + do { + if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) { + return (l_iter->v == v) ? l_iter : l_iter->next; + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e); + return NULL; } BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) { - BMEdge *e_find; - e_find = bmesh_disk_edge_next(e, v); - do { - if (e_find->l && bmesh_radial_facevert_check(e_find->l, v)) { - return e_find; - } - } while ((e_find = bmesh_disk_edge_next(e_find, v)) != e); - return (BMEdge *)e; + BMEdge *e_find; + e_find = bmesh_disk_edge_next(e, v); + do { + if (e_find->l && bmesh_radial_facevert_check(e_find->l, v)) { + return e_find; + } + } while ((e_find = bmesh_disk_edge_next(e_find, v)) != e); + return (BMEdge *)e; } /*****radial cycle functions, e.g. loops surrounding edges**** */ bool bmesh_radial_validate(int radlen, BMLoop *l) { - BMLoop *l_iter = l; - int i = 0; - - if (bmesh_radial_length(l) != radlen) { - return false; - } - - do { - if (UNLIKELY(!l_iter)) { - BMESH_ASSERT(0); - return false; - } - - if (l_iter->e != l->e) { - return false; - } - if (l_iter->v != l->e->v1 && l_iter->v != l->e->v2) { - return false; - } - - if (UNLIKELY(i > BM_LOOP_RADIAL_MAX)) { - BMESH_ASSERT(0); - return false; - } - - i++; - } while ((l_iter = l_iter->radial_next) != l); - - return true; + BMLoop *l_iter = l; + int i = 0; + + if (bmesh_radial_length(l) != radlen) { + return false; + } + + do { + if (UNLIKELY(!l_iter)) { + BMESH_ASSERT(0); + return false; + } + + if (l_iter->e != l->e) { + return false; + } + if (l_iter->v != l->e->v1 && l_iter->v != l->e->v2) { + return false; + } + + if (UNLIKELY(i > BM_LOOP_RADIAL_MAX)) { + BMESH_ASSERT(0); + return false; + } + + i++; + } while ((l_iter = l_iter->radial_next) != l); + + return true; } void bmesh_radial_loop_append(BMEdge *e, BMLoop *l) { - if (e->l == NULL) { - e->l = l; - l->radial_next = l->radial_prev = l; - } - else { - l->radial_prev = e->l; - l->radial_next = e->l->radial_next; - - e->l->radial_next->radial_prev = l; - e->l->radial_next = l; - - e->l = l; - } - - if (UNLIKELY(l->e && l->e != e)) { - /* l is already in a radial cycle for a different edge */ - BMESH_ASSERT(0); - } - - l->e = e; + if (e->l == NULL) { + e->l = l; + l->radial_next = l->radial_prev = l; + } + else { + l->radial_prev = e->l; + l->radial_next = e->l->radial_next; + + e->l->radial_next->radial_prev = l; + e->l->radial_next = l; + + e->l = l; + } + + if (UNLIKELY(l->e && l->e != e)) { + /* l is already in a radial cycle for a different edge */ + BMESH_ASSERT(0); + } + + l->e = e; } /** @@ -451,32 +451,32 @@ void bmesh_radial_loop_append(BMEdge *e, BMLoop *l) */ void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l) { - /* if e is non-NULL, l must be in the radial cycle of e */ - if (UNLIKELY(e != l->e)) { - BMESH_ASSERT(0); - } - - if (l->radial_next != l) { - if (l == e->l) { - e->l = l->radial_next; - } - - l->radial_next->radial_prev = l->radial_prev; - l->radial_prev->radial_next = l->radial_next; - } - else { - if (l == e->l) { - e->l = NULL; - } - else { - BMESH_ASSERT(0); - } - } - - /* l is no longer in a radial cycle; empty the links - * to the cycle and the link back to an edge */ - l->radial_next = l->radial_prev = NULL; - l->e = NULL; + /* if e is non-NULL, l must be in the radial cycle of e */ + if (UNLIKELY(e != l->e)) { + BMESH_ASSERT(0); + } + + if (l->radial_next != l) { + if (l == e->l) { + e->l = l->radial_next; + } + + l->radial_next->radial_prev = l->radial_prev; + l->radial_prev->radial_next = l->radial_next; + } + else { + if (l == e->l) { + e->l = NULL; + } + else { + BMESH_ASSERT(0); + } + } + + /* l is no longer in a radial cycle; empty the links + * to the cycle and the link back to an edge */ + l->radial_next = l->radial_prev = NULL; + l->e = NULL; } /** @@ -485,15 +485,15 @@ void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l) */ void bmesh_radial_loop_unlink(BMLoop *l) { - if (l->radial_next != l) { - l->radial_next->radial_prev = l->radial_prev; - l->radial_prev->radial_next = l->radial_next; - } - - /* l is no longer in a radial cycle; empty the links - * to the cycle and the link back to an edge */ - l->radial_next = l->radial_prev = NULL; - l->e = NULL; + if (l->radial_next != l) { + l->radial_next->radial_prev = l->radial_prev; + l->radial_prev->radial_next = l->radial_next; + } + + /* l is no longer in a radial cycle; empty the links + * to the cycle and the link back to an edge */ + l->radial_next = l->radial_prev = NULL; + l->e = NULL; } /** @@ -504,52 +504,52 @@ void bmesh_radial_loop_unlink(BMLoop *l) */ BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) { - const BMLoop *l_iter; - l_iter = l; - do { - if (l_iter->v == v) { - return (BMLoop *)l_iter; - } - } while ((l_iter = l_iter->radial_next) != l); - return NULL; + const BMLoop *l_iter; + l_iter = l; + do { + if (l_iter->v == v) { + return (BMLoop *)l_iter; + } + } while ((l_iter = l_iter->radial_next) != l); + return NULL; } BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v) { - BMLoop *l_iter; - l_iter = l->radial_next; - do { - if (l_iter->v == v) { - return l_iter; - } - } while ((l_iter = l_iter->radial_next) != l); - return (BMLoop *)l; + BMLoop *l_iter; + l_iter = l->radial_next; + do { + if (l_iter->v == v) { + return l_iter; + } + } while ((l_iter = l_iter->radial_next) != l); + return (BMLoop *)l; } int bmesh_radial_length(const BMLoop *l) { - const BMLoop *l_iter = l; - int i = 0; - - if (!l) { - return 0; - } - - do { - if (UNLIKELY(!l_iter)) { - /* radial cycle is broken (not a circulat loop) */ - BMESH_ASSERT(0); - return 0; - } - - i++; - if (UNLIKELY(i >= BM_LOOP_RADIAL_MAX)) { - BMESH_ASSERT(0); - return -1; - } - } while ((l_iter = l_iter->radial_next) != l); - - return i; + const BMLoop *l_iter = l; + int i = 0; + + if (!l) { + return 0; + } + + do { + if (UNLIKELY(!l_iter)) { + /* radial cycle is broken (not a circulat loop) */ + BMESH_ASSERT(0); + return 0; + } + + i++; + if (UNLIKELY(i >= BM_LOOP_RADIAL_MAX)) { + BMESH_ASSERT(0); + return -1; + } + } while ((l_iter = l_iter->radial_next) != l); + + return i; } /** @@ -560,33 +560,33 @@ int bmesh_radial_length(const BMLoop *l) */ int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) { - const BMLoop *l_iter; - int count = 0; - l_iter = l; - do { - if (l_iter->v == v) { - count++; - } - } while ((l_iter = l_iter->radial_next) != l); - - return count; + const BMLoop *l_iter; + int count = 0; + l_iter = l; + do { + if (l_iter->v == v) { + count++; + } + } while ((l_iter = l_iter->radial_next) != l); + + return count; } int bmesh_radial_facevert_count_at_most(const BMLoop *l, const BMVert *v, const int count_max) { - const BMLoop *l_iter; - int count = 0; - l_iter = l; - do { - if (l_iter->v == v) { - count++; - if (count == count_max) { - break; - } - } - } while ((l_iter = l_iter->radial_next) != l); - - return count; + const BMLoop *l_iter; + int count = 0; + l_iter = l; + do { + if (l_iter->v == v) { + count++; + if (count == count_max) { + break; + } + } + } while ((l_iter = l_iter->radial_next) != l); + + return count; } /** @@ -596,51 +596,49 @@ int bmesh_radial_facevert_count_at_most(const BMLoop *l, const BMVert *v, const */ bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) { - const BMLoop *l_iter; - l_iter = l; - do { - if (l_iter->v == v) { - return true; - } - } while ((l_iter = l_iter->radial_next) != l); - - return false; + const BMLoop *l_iter; + l_iter = l; + do { + if (l_iter->v == v) { + return true; + } + } while ((l_iter = l_iter->radial_next) != l); + + return false; } /*****loop cycle functions, e.g. loops surrounding a face**** */ bool bmesh_loop_validate(BMFace *f) { - int i; - int len = f->len; - BMLoop *l_iter, *l_first; - - l_first = BM_FACE_FIRST_LOOP(f); - - if (l_first == NULL) { - return false; - } - - /* Validate that the face loop cycle is the length specified by f->len */ - for (i = 1, l_iter = l_first->next; i < len; i++, l_iter = l_iter->next) { - if ((l_iter->f != f) || - (l_iter == l_first)) - { - return false; - } - } - if (l_iter != l_first) { - return false; - } - - /* Validate the loop->prev links also form a cycle of length f->len */ - for (i = 1, l_iter = l_first->prev; i < len; i++, l_iter = l_iter->prev) { - if (l_iter == l_first) { - return false; - } - } - if (l_iter != l_first) { - return false; - } - - return true; + int i; + int len = f->len; + BMLoop *l_iter, *l_first; + + l_first = BM_FACE_FIRST_LOOP(f); + + if (l_first == NULL) { + return false; + } + + /* Validate that the face loop cycle is the length specified by f->len */ + for (i = 1, l_iter = l_first->next; i < len; i++, l_iter = l_iter->next) { + if ((l_iter->f != f) || (l_iter == l_first)) { + return false; + } + } + if (l_iter != l_first) { + return false; + } + + /* Validate the loop->prev links also form a cycle of length f->len */ + for (i = 1, l_iter = l_first->prev; i < len; i++, l_iter = l_iter->prev) { + if (l_iter == l_first) { + return false; + } + } + if (l_iter != l_first) { + return false; + } + + return true; } diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h index 8e3ba7b46c0..7ae55a5fa6f 100644 --- a/source/blender/bmesh/intern/bmesh_structure.h +++ b/source/blender/bmesh/intern/bmesh_structure.h @@ -32,44 +32,65 @@ */ /* LOOP CYCLE MANAGEMENT */ -bool bmesh_loop_validate(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool bmesh_loop_validate(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /* DISK CYCLE MANAGMENT */ -void bmesh_disk_edge_append(BMEdge *e, BMVert *v) ATTR_NONNULL(); -void bmesh_disk_edge_remove(BMEdge *e, BMVert *v) ATTR_NONNULL(); -BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int bmesh_disk_facevert_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BMLoop *bmesh_disk_faceloop_find_first_visible(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void bmesh_disk_edge_append(BMEdge *e, BMVert *v) ATTR_NONNULL(); +void bmesh_disk_edge_remove(BMEdge *e, BMVert *v) ATTR_NONNULL(); +BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, + const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, + const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +int bmesh_disk_facevert_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +BMLoop *bmesh_disk_faceloop_find_first_visible(const BMEdge *e, + const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); /* RADIAL CYCLE MANAGMENT */ -void bmesh_radial_loop_append(BMEdge *e, BMLoop *l) ATTR_NONNULL(); -void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l) ATTR_NONNULL(); -void bmesh_radial_loop_unlink(BMLoop *l) ATTR_NONNULL(); +void bmesh_radial_loop_append(BMEdge *e, BMLoop *l) ATTR_NONNULL(); +void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l) ATTR_NONNULL(); +void bmesh_radial_loop_unlink(BMLoop *l) ATTR_NONNULL(); /* note: * bmesh_radial_loop_next(BMLoop *l) / prev. * just use member access l->radial_next, l->radial_prev now */ -int bmesh_radial_facevert_count_at_most(const BMLoop *l, const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int bmesh_radial_facevert_count_at_most(const BMLoop *l, + const BMVert *v, + const int count_max) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /* EDGE UTILITIES */ -void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); -void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); -void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); -BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); +void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); +void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); +BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(); +bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); #include "intern/bmesh_structure_inline.h" diff --git a/source/blender/bmesh/intern/bmesh_structure_inline.h b/source/blender/bmesh/intern/bmesh_structure_inline.h index 0998d9bd907..26d161693af 100644 --- a/source/blender/bmesh/intern/bmesh_structure_inline.h +++ b/source/blender/bmesh/intern/bmesh_structure_inline.h @@ -24,10 +24,10 @@ #define __BMESH_STRUCTURE_INLINE_H__ ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) -BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMVert *v) + BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMVert *v) { - BLI_assert(BM_vert_in_edge(e, v)); - return (BMDiskLink *)&(&e->v1_disk_link)[v == e->v2]; + BLI_assert(BM_vert_in_edge(e, v)); + return (BMDiskLink *)&(&e->v1_disk_link)[v == e->v2]; } /** @@ -38,39 +38,39 @@ BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMV * \return Pointer to the next edge in the disk cycle for the vertex v. */ ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) + BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) { - if (v == e->v1) { - return e->v1_disk_link.next; - } - if (v == e->v2) { - return e->v2_disk_link.next; - } - return NULL; + if (v == e->v1) { + return e->v1_disk_link.next; + } + if (v == e->v2) { + return e->v2_disk_link.next; + } + return NULL; } ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) -BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) + BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) { - if (v == e->v1) { - return e->v1_disk_link.prev; - } - if (v == e->v2) { - return e->v2_disk_link.prev; - } - return NULL; + if (v == e->v1) { + return e->v1_disk_link.prev; + } + if (v == e->v2) { + return e->v2_disk_link.prev; + } + return NULL; } -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) -BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, + const BMVert *v) { - return BM_DISK_EDGE_NEXT(e, v); + return BM_DISK_EDGE_NEXT(e, v); } -ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) -BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, + const BMVert *v) { - return BM_DISK_EDGE_PREV(e, v); + return BM_DISK_EDGE_PREV(e, v); } #endif /* __BMESH_STRUCTURE_INLINE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c index 011addc9220..b850c87d5aa 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.c +++ b/source/blender/bmesh/intern/bmesh_walkers.c @@ -54,11 +54,11 @@ void *BMW_begin(BMWalker *walker, void *start) { - BLI_assert(((BMHeader *)start)->htype & walker->begin_htype); + BLI_assert(((BMHeader *)start)->htype & walker->begin_htype); - walker->begin(walker, start); + walker->begin(walker, start); - return BMW_current_state(walker) ? walker->step(walker) : NULL; + return BMW_current_state(walker) ? walker->step(walker) : NULL; } /** @@ -68,53 +68,62 @@ void *BMW_begin(BMWalker *walker, void *start) * a given type. The elements visited are filtered * by the bitmask 'searchmask'. */ -void BMW_init( - BMWalker *walker, BMesh *bm, int type, - short mask_vert, short mask_edge, short mask_face, - BMWFlag flag, - int layer) +void BMW_init(BMWalker *walker, + BMesh *bm, + int type, + short mask_vert, + short mask_edge, + short mask_face, + BMWFlag flag, + int layer) { - memset(walker, 0, sizeof(BMWalker)); + memset(walker, 0, sizeof(BMWalker)); - walker->layer = layer; - walker->flag = flag; - walker->bm = bm; + walker->layer = layer; + walker->flag = flag; + walker->bm = bm; - walker->mask_vert = mask_vert; - walker->mask_edge = mask_edge; - walker->mask_face = mask_face; + walker->mask_vert = mask_vert; + walker->mask_edge = mask_edge; + walker->mask_face = mask_face; - walker->visit_set = BLI_gset_ptr_new("bmesh walkers"); - walker->visit_set_alt = BLI_gset_ptr_new("bmesh walkers sec"); + walker->visit_set = BLI_gset_ptr_new("bmesh walkers"); + walker->visit_set_alt = BLI_gset_ptr_new("bmesh walkers sec"); - if (UNLIKELY(type >= BMW_MAXWALKERS || type < 0)) { - fprintf(stderr, - "%s: Invalid walker type in BMW_init; type: %d, " - "searchmask: (v:%d, e:%d, f:%d), flag: %u, layer: %d\n", - __func__, type, mask_vert, mask_edge, mask_face, flag, layer); - BLI_assert(0); - return; - } + if (UNLIKELY(type >= BMW_MAXWALKERS || type < 0)) { + fprintf(stderr, + "%s: Invalid walker type in BMW_init; type: %d, " + "searchmask: (v:%d, e:%d, f:%d), flag: %u, layer: %d\n", + __func__, + type, + mask_vert, + mask_edge, + mask_face, + flag, + layer); + BLI_assert(0); + return; + } - if (type != BMW_CUSTOM) { - walker->begin_htype = bm_walker_types[type]->begin_htype; - walker->begin = bm_walker_types[type]->begin; - walker->yield = bm_walker_types[type]->yield; - walker->step = bm_walker_types[type]->step; - walker->structsize = bm_walker_types[type]->structsize; - walker->order = bm_walker_types[type]->order; - walker->valid_mask = bm_walker_types[type]->valid_mask; + if (type != BMW_CUSTOM) { + walker->begin_htype = bm_walker_types[type]->begin_htype; + walker->begin = bm_walker_types[type]->begin; + walker->yield = bm_walker_types[type]->yield; + walker->step = bm_walker_types[type]->step; + walker->structsize = bm_walker_types[type]->structsize; + walker->order = bm_walker_types[type]->order; + walker->valid_mask = bm_walker_types[type]->valid_mask; - /* safety checks */ - /* if this raises an error either the caller is wrong or - * 'bm_walker_types' needs updating */ - BLI_assert(mask_vert == 0 || (walker->valid_mask & BM_VERT)); - BLI_assert(mask_edge == 0 || (walker->valid_mask & BM_EDGE)); - BLI_assert(mask_face == 0 || (walker->valid_mask & BM_FACE)); - } + /* safety checks */ + /* if this raises an error either the caller is wrong or + * 'bm_walker_types' needs updating */ + BLI_assert(mask_vert == 0 || (walker->valid_mask & BM_VERT)); + BLI_assert(mask_edge == 0 || (walker->valid_mask & BM_EDGE)); + BLI_assert(mask_face == 0 || (walker->valid_mask & BM_FACE)); + } - walker->worklist = BLI_mempool_create(walker->structsize, 0, 128, BLI_MEMPOOL_NOP); - BLI_listbase_clear(&walker->states); + walker->worklist = BLI_mempool_create(walker->structsize, 0, 128, BLI_MEMPOOL_NOP); + BLI_listbase_clear(&walker->states); } /** @@ -124,22 +133,21 @@ void BMW_init( */ void BMW_end(BMWalker *walker) { - BLI_mempool_destroy(walker->worklist); - BLI_gset_free(walker->visit_set, NULL); - BLI_gset_free(walker->visit_set_alt, NULL); + BLI_mempool_destroy(walker->worklist); + BLI_gset_free(walker->visit_set, NULL); + BLI_gset_free(walker->visit_set_alt, NULL); } - /** * \brief Step Walker */ void *BMW_step(BMWalker *walker) { - BMHeader *head; + BMHeader *head; - head = BMW_walk(walker); + head = BMW_walk(walker); - return head; + return head; } /** @@ -150,7 +158,7 @@ void *BMW_step(BMWalker *walker) int BMW_current_depth(BMWalker *walker) { - return walker->depth; + return walker->depth; } /** @@ -160,15 +168,15 @@ int BMW_current_depth(BMWalker *walker) */ void *BMW_walk(BMWalker *walker) { - void *current = NULL; + void *current = NULL; - while (BMW_current_state(walker)) { - current = walker->step(walker); - if (current) { - return current; - } - } - return NULL; + while (BMW_current_state(walker)) { + current = walker->step(walker); + if (current) { + return current; + } + } + return NULL; } /** @@ -180,21 +188,21 @@ void *BMW_walk(BMWalker *walker) */ void *BMW_current_state(BMWalker *walker) { - BMwGenericWalker *currentstate = walker->states.first; - if (currentstate) { - /* Automatic update of depth. For most walkers that - * follow the standard "Step" pattern of: - * - read current state - * - remove current state - * - push new states - * - return walk result from just-removed current state - * this simple automatic update should keep track of depth - * just fine. Walkers that deviate from that pattern may - * need to manually update the depth if they care about - * keeping it correct. */ - walker->depth = currentstate->depth + 1; - } - return currentstate; + BMwGenericWalker *currentstate = walker->states.first; + if (currentstate) { + /* Automatic update of depth. For most walkers that + * follow the standard "Step" pattern of: + * - read current state + * - remove current state + * - push new states + * - return walk result from just-removed current state + * this simple automatic update should keep track of depth + * just fine. Walkers that deviate from that pattern may + * need to manually update the depth if they care about + * keeping it correct. */ + walker->depth = currentstate->depth + 1; + } + return currentstate; } /** @@ -205,10 +213,10 @@ void *BMW_current_state(BMWalker *walker) */ void BMW_state_remove(BMWalker *walker) { - void *oldstate; - oldstate = BMW_current_state(walker); - BLI_remlink(&walker->states, oldstate); - BLI_mempool_free(walker->worklist, oldstate); + void *oldstate; + oldstate = BMW_current_state(walker); + BLI_remlink(&walker->states, oldstate); + BLI_mempool_free(walker->worklist, oldstate); } /** @@ -222,21 +230,21 @@ void BMW_state_remove(BMWalker *walker) */ void *BMW_state_add(BMWalker *walker) { - BMwGenericWalker *newstate; - newstate = BLI_mempool_alloc(walker->worklist); - newstate->depth = walker->depth; - switch (walker->order) { - case BMW_DEPTH_FIRST: - BLI_addhead(&walker->states, newstate); - break; - case BMW_BREADTH_FIRST: - BLI_addtail(&walker->states, newstate); - break; - default: - BLI_assert(0); - break; - } - return newstate; + BMwGenericWalker *newstate; + newstate = BLI_mempool_alloc(walker->worklist); + newstate->depth = walker->depth; + switch (walker->order) { + case BMW_DEPTH_FIRST: + BLI_addhead(&walker->states, newstate); + break; + case BMW_BREADTH_FIRST: + BLI_addtail(&walker->states, newstate); + break; + default: + BLI_assert(0); + break; + } + return newstate; } /** @@ -247,10 +255,10 @@ void *BMW_state_add(BMWalker *walker) */ void BMW_reset(BMWalker *walker) { - while (BMW_current_state(walker)) { - BMW_state_remove(walker); - } - walker->depth = 0; - BLI_gset_clear(walker->visit_set, NULL); - BLI_gset_clear(walker->visit_set_alt, NULL); + while (BMW_current_state(walker)) { + BMW_state_remove(walker); + } + walker->depth = 0; + BLI_gset_clear(walker->visit_set, NULL); + BLI_gset_clear(walker->visit_set_alt, NULL); } diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h index 3de7d6d2c90..54cfccb9ed8 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.h +++ b/source/blender/bmesh/intern/bmesh_walkers.h @@ -26,43 +26,43 @@ */ typedef enum { - BMW_DEPTH_FIRST, - BMW_BREADTH_FIRST, + BMW_DEPTH_FIRST, + BMW_BREADTH_FIRST, } BMWOrder; typedef enum { - BMW_FLAG_NOP = 0, - BMW_FLAG_TEST_HIDDEN = (1 << 0), + BMW_FLAG_NOP = 0, + BMW_FLAG_TEST_HIDDEN = (1 << 0), } BMWFlag; /*Walkers*/ typedef struct BMWalker { - char begin_htype; /* only for validating input */ - void (*begin) (struct BMWalker *walker, void *start); - void *(*step) (struct BMWalker *walker); - void *(*yield) (struct BMWalker *walker); - int structsize; - BMWOrder order; - int valid_mask; - - /* runtime */ - int layer; - - BMesh *bm; - BLI_mempool *worklist; - ListBase states; - - /* these masks are to be tested against elements BMO_elem_flag_test(), - * should never be accessed directly only through BMW_init() and bmw_mask_check_*() functions */ - short mask_vert; - short mask_edge; - short mask_face; - - BMWFlag flag; - - struct GSet *visit_set; - struct GSet *visit_set_alt; - int depth; + char begin_htype; /* only for validating input */ + void (*begin)(struct BMWalker *walker, void *start); + void *(*step)(struct BMWalker *walker); + void *(*yield)(struct BMWalker *walker); + int structsize; + BMWOrder order; + int valid_mask; + + /* runtime */ + int layer; + + BMesh *bm; + BLI_mempool *worklist; + ListBase states; + + /* these masks are to be tested against elements BMO_elem_flag_test(), + * should never be accessed directly only through BMW_init() and bmw_mask_check_*() functions */ + short mask_vert; + short mask_edge; + short mask_face; + + BMWFlag flag; + + struct GSet *visit_set; + struct GSet *visit_set_alt; + int depth; } BMWalker; /* define to make BMW_init more clear */ @@ -70,27 +70,29 @@ typedef struct BMWalker { /* initialize a walker. searchmask restricts some (not all) walkers to * elements with a specific tool flag set. flags is specific to each walker.*/ -void BMW_init( - struct BMWalker *walker, BMesh *bm, int type, - short mask_vert, short mask_edge, short mask_face, - BMWFlag flag, - int layer); +void BMW_init(struct BMWalker *walker, + BMesh *bm, + int type, + short mask_vert, + short mask_edge, + short mask_face, + BMWFlag flag, + int layer); void *BMW_begin(BMWalker *walker, void *start); void *BMW_step(struct BMWalker *walker); -void BMW_end(struct BMWalker *walker); -int BMW_current_depth(BMWalker *walker); +void BMW_end(struct BMWalker *walker); +int BMW_current_depth(BMWalker *walker); /*these are used by custom walkers*/ void *BMW_current_state(BMWalker *walker); void *BMW_state_add(BMWalker *walker); -void BMW_state_remove(BMWalker *walker); +void BMW_state_remove(BMWalker *walker); void *BMW_walk(BMWalker *walker); -void BMW_reset(BMWalker *walker); +void BMW_reset(BMWalker *walker); #define BMW_ITER(ele, walker, data) \ - for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_begin(walker, (BM_CHECK_TYPE_ELEM(data), data)); \ - ele; \ - BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_step(walker)) + for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_begin(walker, (BM_CHECK_TYPE_ELEM(data), data)); ele; \ + BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_step(walker)) /* * example of usage, walking over an island of tool flagged faces: @@ -107,28 +109,28 @@ void BMW_reset(BMWalker *walker); */ enum { - BMW_VERT_SHELL, - BMW_LOOP_SHELL, - BMW_LOOP_SHELL_WIRE, - BMW_FACE_SHELL, - BMW_EDGELOOP, - BMW_FACELOOP, - BMW_EDGERING, - BMW_EDGEBOUNDARY, - /* BMW_RING, */ - BMW_LOOPDATA_ISLAND, - BMW_ISLANDBOUND, - BMW_ISLAND, - BMW_ISLAND_MANIFOLD, - BMW_CONNECTED_VERTEX, - /* end of array index enum vals */ - - /* do not intitialze function pointers and struct size in BMW_init */ - BMW_CUSTOM, - BMW_MAXWALKERS, + BMW_VERT_SHELL, + BMW_LOOP_SHELL, + BMW_LOOP_SHELL_WIRE, + BMW_FACE_SHELL, + BMW_EDGELOOP, + BMW_FACELOOP, + BMW_EDGERING, + BMW_EDGEBOUNDARY, + /* BMW_RING, */ + BMW_LOOPDATA_ISLAND, + BMW_ISLANDBOUND, + BMW_ISLAND, + BMW_ISLAND_MANIFOLD, + BMW_CONNECTED_VERTEX, + /* end of array index enum vals */ + + /* do not intitialze function pointers and struct size in BMW_init */ + BMW_CUSTOM, + BMW_MAXWALKERS, }; /* use with BMW_init, so as not to confuse with restrict flags */ -#define BMW_NIL_LAY 0 +#define BMW_NIL_LAY 0 #endif /* __BMESH_WALKERS_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index 0ac9b958c11..c327c10226f 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -30,56 +30,57 @@ #include "intern/bmesh_walkers_private.h" /* pop into stack memory (common operation) */ -#define BMW_state_remove_r(walker, owalk) { \ - memcpy(owalk, BMW_current_state(walker), sizeof(*(owalk))); \ - BMW_state_remove(walker); \ -} (void)0 +#define BMW_state_remove_r(walker, owalk) \ + { \ + memcpy(owalk, BMW_current_state(walker), sizeof(*(owalk))); \ + BMW_state_remove(walker); \ + } \ + (void)0 /** \name Mask Flag Checks * \{ */ static bool bmw_mask_check_vert(BMWalker *walker, BMVert *v) { - if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - return false; - } - else if (walker->mask_vert && !BMO_vert_flag_test(walker->bm, v, walker->mask_vert)) { - return false; - } - else { - return true; - } + if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + return false; + } + else if (walker->mask_vert && !BMO_vert_flag_test(walker->bm, v, walker->mask_vert)) { + return false; + } + else { + return true; + } } static bool bmw_mask_check_edge(BMWalker *walker, BMEdge *e) { - if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - return false; - } - else if (walker->mask_edge && !BMO_edge_flag_test(walker->bm, e, walker->mask_edge)) { - return false; - } - else { - return true; - } + if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + return false; + } + else if (walker->mask_edge && !BMO_edge_flag_test(walker->bm, e, walker->mask_edge)) { + return false; + } + else { + return true; + } } static bool bmw_mask_check_face(BMWalker *walker, BMFace *f) { - if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - return false; - } - else if (walker->mask_face && !BMO_face_flag_test(walker->bm, f, walker->mask_face)) { - return false; - } - else { - return true; - } + if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + return false; + } + else if (walker->mask_face && !BMO_face_flag_test(walker->bm, f, walker->mask_face)) { + return false; + } + else { + return true; + } } /** \} */ - /** \name BMesh Queries (modified to check walker flags) * \{ */ @@ -88,22 +89,21 @@ static bool bmw_mask_check_face(BMWalker *walker, BMFace *f) */ static bool bmw_edge_is_wire(const BMWalker *walker, const BMEdge *e) { - if (walker->flag & BMW_FLAG_TEST_HIDDEN) { - /* check if this is a wire edge, ignoring hidden faces */ - if (BM_edge_is_wire(e)) { - return true; - } - else { - return BM_edge_is_all_face_flag_test(e, BM_ELEM_HIDDEN, false); - } - } - else { - return BM_edge_is_wire(e); - } + if (walker->flag & BMW_FLAG_TEST_HIDDEN) { + /* check if this is a wire edge, ignoring hidden faces */ + if (BM_edge_is_wire(e)) { + return true; + } + else { + return BM_edge_is_all_face_flag_test(e, BM_ELEM_HIDDEN, false); + } + } + else { + return BM_edge_is_wire(e); + } } /** \} */ - /** \name Shell Walker * \{ * @@ -117,125 +117,123 @@ static bool bmw_edge_is_wire(const BMWalker *walker, const BMEdge *e) */ static void bmw_VertShellWalker_visitEdge(BMWalker *walker, BMEdge *e) { - BMwShellWalker *shellWalk = NULL; + BMwShellWalker *shellWalk = NULL; - if (BLI_gset_haskey(walker->visit_set, e)) { - return; - } + if (BLI_gset_haskey(walker->visit_set, e)) { + return; + } - if (!bmw_mask_check_edge(walker, e)) { - return; - } + if (!bmw_mask_check_edge(walker, e)) { + return; + } - shellWalk = BMW_state_add(walker); - shellWalk->curedge = e; - BLI_gset_insert(walker->visit_set, e); + shellWalk = BMW_state_add(walker); + shellWalk->curedge = e; + BLI_gset_insert(walker->visit_set, e); } static void bmw_VertShellWalker_begin(BMWalker *walker, void *data) { - BMIter eiter; - BMHeader *h = data; - BMEdge *e; - BMVert *v; - - if (UNLIKELY(h == NULL)) { - return; - } - - switch (h->htype) { - case BM_VERT: - { - /* starting the walk at a vert, add all the edges - * to the worklist */ - v = (BMVert *)h; - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - bmw_VertShellWalker_visitEdge(walker, e); - } - break; - } - - case BM_EDGE: - { - /* starting the walk at an edge, add the single edge - * to the worklist */ - e = (BMEdge *)h; - bmw_VertShellWalker_visitEdge(walker, e); - break; - } - default: - BLI_assert(0); - } + BMIter eiter; + BMHeader *h = data; + BMEdge *e; + BMVert *v; + + if (UNLIKELY(h == NULL)) { + return; + } + + switch (h->htype) { + case BM_VERT: { + /* starting the walk at a vert, add all the edges + * to the worklist */ + v = (BMVert *)h; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + bmw_VertShellWalker_visitEdge(walker, e); + } + break; + } + + case BM_EDGE: { + /* starting the walk at an edge, add the single edge + * to the worklist */ + e = (BMEdge *)h; + bmw_VertShellWalker_visitEdge(walker, e); + break; + } + default: + BLI_assert(0); + } } static void *bmw_VertShellWalker_yield(BMWalker *walker) { - BMwShellWalker *shellWalk = BMW_current_state(walker); - return shellWalk->curedge; + BMwShellWalker *shellWalk = BMW_current_state(walker); + return shellWalk->curedge; } static void *bmw_VertShellWalker_step(BMWalker *walker) { - BMwShellWalker *swalk, owalk; - BMEdge *e, *e2; - BMVert *v; - BMIter iter; - int i; + BMwShellWalker *swalk, owalk; + BMEdge *e, *e2; + BMVert *v; + BMIter iter; + int i; - BMW_state_remove_r(walker, &owalk); - swalk = &owalk; + BMW_state_remove_r(walker, &owalk); + swalk = &owalk; - e = swalk->curedge; + e = swalk->curedge; - for (i = 0; i < 2; i++) { - v = i ? e->v2 : e->v1; - BM_ITER_ELEM (e2, &iter, v, BM_EDGES_OF_VERT) { - bmw_VertShellWalker_visitEdge(walker, e2); - } - } + for (i = 0; i < 2; i++) { + v = i ? e->v2 : e->v1; + BM_ITER_ELEM (e2, &iter, v, BM_EDGES_OF_VERT) { + bmw_VertShellWalker_visitEdge(walker, e2); + } + } - return e; + return e; } #if 0 static void *bmw_VertShellWalker_step(BMWalker *walker) { - BMEdge *curedge, *next = NULL; - BMVert *v_old = NULL; - bool restrictpass = true; - BMwShellWalker shellWalk = *((BMwShellWalker *)BMW_current_state(walker)); + BMEdge *curedge, *next = NULL; + BMVert *v_old = NULL; + bool restrictpass = true; + BMwShellWalker shellWalk = *((BMwShellWalker *)BMW_current_state(walker)); - if (!BLI_gset_haskey(walker->visit_set, shellWalk.base)) { - BLI_gset_insert(walker->visit_set, shellWalk.base); - } + if (!BLI_gset_haskey(walker->visit_set, shellWalk.base)) { + BLI_gset_insert(walker->visit_set, shellWalk.base); + } - BMW_state_remove(walker); + BMW_state_remove(walker); - /* find the next edge whose other vertex has not been visite */ - curedge = shellWalk.curedge; - do { - if (!BLI_gset_haskey(walker->visit_set, curedge)) { - if (!walker->restrictflag || - (walker->restrictflag && BMO_edge_flag_test(walker->bm, curedge, walker->restrictflag))) - { - BMwShellWalker *newstate; + /* find the next edge whose other vertex has not been visite */ + curedge = shellWalk.curedge; + do { + if (!BLI_gset_haskey(walker->visit_set, curedge)) { + if (!walker->restrictflag || + (walker->restrictflag && BMO_edge_flag_test(walker->bm, curedge, walker->restrictflag))) + { + BMwShellWalker *newstate; - v_old = BM_edge_other_vert(curedge, shellWalk.base); + v_old = BM_edge_other_vert(curedge, shellWalk.base); - /* push a new state onto the stac */ - newState = BMW_state_add(walker); - BLI_gset_insert(walker->visit_set, curedge); + /* push a new state onto the stac */ + newState = BMW_state_add(walker); + BLI_gset_insert(walker->visit_set, curedge); - /* populate the new stat */ + /* populate the new stat */ - newState->base = v_old; - newState->curedge = curedge; - } - } - } while ((curedge = bmesh_disk_edge_next(curedge, shellWalk.base)) != shellWalk.curedge); + newState->base = v_old; + newState->curedge = curedge; + } + } + } while ((curedge = bmesh_disk_edge_next(curedge, shellWalk.base)) != shellWalk.curedge); - return shellWalk.curedge; + return shellWalk.curedge; } #endif @@ -251,120 +249,116 @@ static void *bmw_VertShellWalker_step(BMWalker *walker) */ static void bmw_LoopShellWalker_visitLoop(BMWalker *walker, BMLoop *l) { - BMwLoopShellWalker *shellWalk = NULL; + BMwLoopShellWalker *shellWalk = NULL; - if (BLI_gset_haskey(walker->visit_set, l)) { - return; - } + if (BLI_gset_haskey(walker->visit_set, l)) { + return; + } - if (!bmw_mask_check_face(walker, l->f)) { - return; - } + if (!bmw_mask_check_face(walker, l->f)) { + return; + } - shellWalk = BMW_state_add(walker); - shellWalk->curloop = l; - BLI_gset_insert(walker->visit_set, l); + shellWalk = BMW_state_add(walker); + shellWalk->curloop = l; + BLI_gset_insert(walker->visit_set, l); } static void bmw_LoopShellWalker_begin(BMWalker *walker, void *data) { - BMIter iter; - BMHeader *h = data; - - if (UNLIKELY(h == NULL)) { - return; - } - - switch (h->htype) { - case BM_LOOP: - { - /* starting the walk at a vert, add all the edges - * to the worklist */ - BMLoop *l = (BMLoop *)h; - bmw_LoopShellWalker_visitLoop(walker, l); - break; - } - - case BM_VERT: - { - BMVert *v = (BMVert *)h; - BMLoop *l; - BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { - bmw_LoopShellWalker_visitLoop(walker, l); - } - break; - } - case BM_EDGE: - { - BMEdge *e = (BMEdge *)h; - BMLoop *l; - BM_ITER_ELEM (l, &iter, e, BM_LOOPS_OF_EDGE) { - bmw_LoopShellWalker_visitLoop(walker, l); - } - break; - } - case BM_FACE: - { - BMFace *f = (BMFace *)h; - BMLoop *l = BM_FACE_FIRST_LOOP(f); - /* walker will handle other loops within the face */ - bmw_LoopShellWalker_visitLoop(walker, l); - break; - } - default: - BLI_assert(0); - } + BMIter iter; + BMHeader *h = data; + + if (UNLIKELY(h == NULL)) { + return; + } + + switch (h->htype) { + case BM_LOOP: { + /* starting the walk at a vert, add all the edges + * to the worklist */ + BMLoop *l = (BMLoop *)h; + bmw_LoopShellWalker_visitLoop(walker, l); + break; + } + + case BM_VERT: { + BMVert *v = (BMVert *)h; + BMLoop *l; + BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { + bmw_LoopShellWalker_visitLoop(walker, l); + } + break; + } + case BM_EDGE: { + BMEdge *e = (BMEdge *)h; + BMLoop *l; + BM_ITER_ELEM (l, &iter, e, BM_LOOPS_OF_EDGE) { + bmw_LoopShellWalker_visitLoop(walker, l); + } + break; + } + case BM_FACE: { + BMFace *f = (BMFace *)h; + BMLoop *l = BM_FACE_FIRST_LOOP(f); + /* walker will handle other loops within the face */ + bmw_LoopShellWalker_visitLoop(walker, l); + break; + } + default: + BLI_assert(0); + } } static void *bmw_LoopShellWalker_yield(BMWalker *walker) { - BMwLoopShellWalker *shellWalk = BMW_current_state(walker); - return shellWalk->curloop; + BMwLoopShellWalker *shellWalk = BMW_current_state(walker); + return shellWalk->curloop; } static void bmw_LoopShellWalker_step_impl(BMWalker *walker, BMLoop *l) { - BMEdge *e_edj_pair[2]; - int i; - - /* seems paranoid, but one caller also walks edges */ - BLI_assert(l->head.htype == BM_LOOP); - - bmw_LoopShellWalker_visitLoop(walker, l->next); - bmw_LoopShellWalker_visitLoop(walker, l->prev); - - e_edj_pair[0] = l->e; - e_edj_pair[1] = l->prev->e; - - for (i = 0; i < 2; i++) { - BMEdge *e = e_edj_pair[i]; - if (bmw_mask_check_edge(walker, e)) { - BMLoop *l_iter, *l_first; - - l_iter = l_first = e->l; - do { - BMLoop *l_radial = (l_iter->v == l->v) ? l_iter : l_iter->next; - BLI_assert(l_radial->v == l->v); - if (l != l_radial) { - bmw_LoopShellWalker_visitLoop(walker, l_radial); - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - } + BMEdge *e_edj_pair[2]; + int i; + + /* seems paranoid, but one caller also walks edges */ + BLI_assert(l->head.htype == BM_LOOP); + + bmw_LoopShellWalker_visitLoop(walker, l->next); + bmw_LoopShellWalker_visitLoop(walker, l->prev); + + e_edj_pair[0] = l->e; + e_edj_pair[1] = l->prev->e; + + for (i = 0; i < 2; i++) { + BMEdge *e = e_edj_pair[i]; + if (bmw_mask_check_edge(walker, e)) { + BMLoop *l_iter, *l_first; + + l_iter = l_first = e->l; + do { + BMLoop *l_radial = (l_iter->v == l->v) ? l_iter : l_iter->next; + BLI_assert(l_radial->v == l->v); + if (l != l_radial) { + bmw_LoopShellWalker_visitLoop(walker, l_radial); + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + } } static void *bmw_LoopShellWalker_step(BMWalker *walker) { - BMwLoopShellWalker *swalk, owalk; - BMLoop *l; + BMwLoopShellWalker *swalk, owalk; + BMLoop *l; - BMW_state_remove_r(walker, &owalk); - swalk = &owalk; + BMW_state_remove_r(walker, &owalk); + swalk = &owalk; - l = swalk->curloop; - bmw_LoopShellWalker_step_impl(walker, l); + l = swalk->curloop; + bmw_LoopShellWalker_step_impl(walker, l); - return l; + return l; } /** \} */ @@ -384,149 +378,144 @@ static void *bmw_LoopShellWalker_step(BMWalker *walker) static void bmw_LoopShellWalker_visitEdgeWire(BMWalker *walker, BMEdge *e) { - BMwLoopShellWireWalker *shellWalk = NULL; + BMwLoopShellWireWalker *shellWalk = NULL; - BLI_assert(bmw_edge_is_wire(walker, e)); + BLI_assert(bmw_edge_is_wire(walker, e)); - if (BLI_gset_haskey(walker->visit_set_alt, e)) { - return; - } + if (BLI_gset_haskey(walker->visit_set_alt, e)) { + return; + } - if (!bmw_mask_check_edge(walker, e)) { - return; - } + if (!bmw_mask_check_edge(walker, e)) { + return; + } - shellWalk = BMW_state_add(walker); - shellWalk->curelem = (BMElem *)e; - BLI_gset_insert(walker->visit_set_alt, e); + shellWalk = BMW_state_add(walker); + shellWalk->curelem = (BMElem *)e; + BLI_gset_insert(walker->visit_set_alt, e); } static void bmw_LoopShellWireWalker_visitVert(BMWalker *walker, BMVert *v, const BMEdge *e_from) { - BMEdge *e; + BMEdge *e; - BLI_assert(v->head.htype == BM_VERT); + BLI_assert(v->head.htype == BM_VERT); - if (BLI_gset_haskey(walker->visit_set_alt, v)) { - return; - } + if (BLI_gset_haskey(walker->visit_set_alt, v)) { + return; + } - if (!bmw_mask_check_vert(walker, v)) { - return; - } + if (!bmw_mask_check_vert(walker, v)) { + return; + } - e = v->e; - do { - if (bmw_edge_is_wire(walker, e) && (e != e_from)) { - BMVert *v_other; - BMIter iter; - BMLoop *l; + e = v->e; + do { + if (bmw_edge_is_wire(walker, e) && (e != e_from)) { + BMVert *v_other; + BMIter iter; + BMLoop *l; - bmw_LoopShellWalker_visitEdgeWire(walker, e); + bmw_LoopShellWalker_visitEdgeWire(walker, e); - /* check if we step onto a non-wire vertex */ - v_other = BM_edge_other_vert(e, v); - BM_ITER_ELEM (l, &iter, v_other, BM_LOOPS_OF_VERT) { + /* check if we step onto a non-wire vertex */ + v_other = BM_edge_other_vert(e, v); + BM_ITER_ELEM (l, &iter, v_other, BM_LOOPS_OF_VERT) { - bmw_LoopShellWalker_visitLoop(walker, l); - } - } - } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e); + bmw_LoopShellWalker_visitLoop(walker, l); + } + } + } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e); - BLI_gset_insert(walker->visit_set_alt, v); + BLI_gset_insert(walker->visit_set_alt, v); } static void bmw_LoopShellWireWalker_begin(BMWalker *walker, void *data) { - BMHeader *h = data; - - if (UNLIKELY(h == NULL)) { - return; - } - - bmw_LoopShellWalker_begin(walker, data); - - switch (h->htype) { - case BM_LOOP: - { - BMLoop *l = (BMLoop *)h; - bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL); - break; - } - - case BM_VERT: - { - BMVert *v = (BMVert *)h; - if (v->e) { - bmw_LoopShellWireWalker_visitVert(walker, v, NULL); - } - break; - } - case BM_EDGE: - { - BMEdge *e = (BMEdge *)h; - if (bmw_mask_check_edge(walker, e)) { - bmw_LoopShellWireWalker_visitVert(walker, e->v1, NULL); - bmw_LoopShellWireWalker_visitVert(walker, e->v2, NULL); - } - else if (e->l) { - BMLoop *l_iter, *l_first; - - l_iter = l_first = e->l; - do { - bmw_LoopShellWalker_visitLoop(walker, l_iter); - bmw_LoopShellWalker_visitLoop(walker, l_iter->next); - } while ((l_iter = l_iter->radial_next) != l_first); - } - break; - } - case BM_FACE: - { - /* wire verts will be walked over */ - break; - } - default: - BLI_assert(0); - } + BMHeader *h = data; + + if (UNLIKELY(h == NULL)) { + return; + } + + bmw_LoopShellWalker_begin(walker, data); + + switch (h->htype) { + case BM_LOOP: { + BMLoop *l = (BMLoop *)h; + bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL); + break; + } + + case BM_VERT: { + BMVert *v = (BMVert *)h; + if (v->e) { + bmw_LoopShellWireWalker_visitVert(walker, v, NULL); + } + break; + } + case BM_EDGE: { + BMEdge *e = (BMEdge *)h; + if (bmw_mask_check_edge(walker, e)) { + bmw_LoopShellWireWalker_visitVert(walker, e->v1, NULL); + bmw_LoopShellWireWalker_visitVert(walker, e->v2, NULL); + } + else if (e->l) { + BMLoop *l_iter, *l_first; + + l_iter = l_first = e->l; + do { + bmw_LoopShellWalker_visitLoop(walker, l_iter); + bmw_LoopShellWalker_visitLoop(walker, l_iter->next); + } while ((l_iter = l_iter->radial_next) != l_first); + } + break; + } + case BM_FACE: { + /* wire verts will be walked over */ + break; + } + default: + BLI_assert(0); + } } static void *bmw_LoopShellWireWalker_yield(BMWalker *walker) { - BMwLoopShellWireWalker *shellWalk = BMW_current_state(walker); - return shellWalk->curelem; + BMwLoopShellWireWalker *shellWalk = BMW_current_state(walker); + return shellWalk->curelem; } static void *bmw_LoopShellWireWalker_step(BMWalker *walker) { - BMwLoopShellWireWalker *swalk, owalk; + BMwLoopShellWireWalker *swalk, owalk; - BMW_state_remove_r(walker, &owalk); - swalk = &owalk; + BMW_state_remove_r(walker, &owalk); + swalk = &owalk; - if (swalk->curelem->head.htype == BM_LOOP) { - BMLoop *l = (BMLoop *)swalk->curelem; + if (swalk->curelem->head.htype == BM_LOOP) { + BMLoop *l = (BMLoop *)swalk->curelem; - bmw_LoopShellWalker_step_impl(walker, l); + bmw_LoopShellWalker_step_impl(walker, l); - bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL); + bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL); - return l; - } - else { - BMEdge *e = (BMEdge *)swalk->curelem; + return l; + } + else { + BMEdge *e = (BMEdge *)swalk->curelem; - BLI_assert(e->head.htype == BM_EDGE); + BLI_assert(e->head.htype == BM_EDGE); - bmw_LoopShellWireWalker_visitVert(walker, e->v1, e); - bmw_LoopShellWireWalker_visitVert(walker, e->v2, e); + bmw_LoopShellWireWalker_visitVert(walker, e->v1, e); + bmw_LoopShellWireWalker_visitVert(walker, e->v2, e); - return e; - } + return e; + } } /** \} */ - /** \name FaceShell Walker * \{ * @@ -535,62 +524,61 @@ static void *bmw_LoopShellWireWalker_step(BMWalker *walker) */ static void bmw_FaceShellWalker_visitEdge(BMWalker *walker, BMEdge *e) { - BMwShellWalker *shellWalk = NULL; + BMwShellWalker *shellWalk = NULL; - if (BLI_gset_haskey(walker->visit_set, e)) { - return; - } + if (BLI_gset_haskey(walker->visit_set, e)) { + return; + } - if (!bmw_mask_check_edge(walker, e)) { - return; - } + if (!bmw_mask_check_edge(walker, e)) { + return; + } - shellWalk = BMW_state_add(walker); - shellWalk->curedge = e; - BLI_gset_insert(walker->visit_set, e); + shellWalk = BMW_state_add(walker); + shellWalk->curedge = e; + BLI_gset_insert(walker->visit_set, e); } static void bmw_FaceShellWalker_begin(BMWalker *walker, void *data) { - BMEdge *e = data; - bmw_FaceShellWalker_visitEdge(walker, e); + BMEdge *e = data; + bmw_FaceShellWalker_visitEdge(walker, e); } static void *bmw_FaceShellWalker_yield(BMWalker *walker) { - BMwShellWalker *shellWalk = BMW_current_state(walker); - return shellWalk->curedge; + BMwShellWalker *shellWalk = BMW_current_state(walker); + return shellWalk->curedge; } static void *bmw_FaceShellWalker_step(BMWalker *walker) { - BMwShellWalker *swalk, owalk; - BMEdge *e, *e2; - BMIter iter; + BMwShellWalker *swalk, owalk; + BMEdge *e, *e2; + BMIter iter; - BMW_state_remove_r(walker, &owalk); - swalk = &owalk; + BMW_state_remove_r(walker, &owalk); + swalk = &owalk; - e = swalk->curedge; + e = swalk->curedge; - if (e->l) { - BMLoop *l_iter, *l_first; + if (e->l) { + BMLoop *l_iter, *l_first; - l_iter = l_first = e->l; - do { - BM_ITER_ELEM (e2, &iter, l_iter->f, BM_EDGES_OF_FACE) { - if (e2 != e) { - bmw_FaceShellWalker_visitEdge(walker, e2); - } - } - } while ((l_iter = l_iter->radial_next) != l_first); - } + l_iter = l_first = e->l; + do { + BM_ITER_ELEM (e2, &iter, l_iter->f, BM_EDGES_OF_FACE) { + if (e2 != e) { + bmw_FaceShellWalker_visitEdge(walker, e2); + } + } + } while ((l_iter = l_iter->radial_next) != l_first); + } - return e; + return e; } /** \} */ - /** \name Connected Vertex Walker * \{ * @@ -600,60 +588,59 @@ static void *bmw_FaceShellWalker_step(BMWalker *walker) */ static void bmw_ConnectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v) { - BMwConnectedVertexWalker *vwalk; + BMwConnectedVertexWalker *vwalk; - if (BLI_gset_haskey(walker->visit_set, v)) { - /* already visited */ - return; - } + if (BLI_gset_haskey(walker->visit_set, v)) { + /* already visited */ + return; + } - if (!bmw_mask_check_vert(walker, v)) { - /* not flagged for walk */ - return; - } + if (!bmw_mask_check_vert(walker, v)) { + /* not flagged for walk */ + return; + } - vwalk = BMW_state_add(walker); - vwalk->curvert = v; - BLI_gset_insert(walker->visit_set, v); + vwalk = BMW_state_add(walker); + vwalk->curvert = v; + BLI_gset_insert(walker->visit_set, v); } static void bmw_ConnectedVertexWalker_begin(BMWalker *walker, void *data) { - BMVert *v = data; - bmw_ConnectedVertexWalker_visitVertex(walker, v); + BMVert *v = data; + bmw_ConnectedVertexWalker_visitVertex(walker, v); } static void *bmw_ConnectedVertexWalker_yield(BMWalker *walker) { - BMwConnectedVertexWalker *vwalk = BMW_current_state(walker); - return vwalk->curvert; + BMwConnectedVertexWalker *vwalk = BMW_current_state(walker); + return vwalk->curvert; } static void *bmw_ConnectedVertexWalker_step(BMWalker *walker) { - BMwConnectedVertexWalker *vwalk, owalk; - BMVert *v, *v2; - BMEdge *e; - BMIter iter; + BMwConnectedVertexWalker *vwalk, owalk; + BMVert *v, *v2; + BMEdge *e; + BMIter iter; - BMW_state_remove_r(walker, &owalk); - vwalk = &owalk; + BMW_state_remove_r(walker, &owalk); + vwalk = &owalk; - v = vwalk->curvert; + v = vwalk->curvert; - BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - v2 = BM_edge_other_vert(e, v); - if (!BLI_gset_haskey(walker->visit_set, v2)) { - bmw_ConnectedVertexWalker_visitVertex(walker, v2); - } - } + BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + v2 = BM_edge_other_vert(e, v); + if (!BLI_gset_haskey(walker->visit_set, v2)) { + bmw_ConnectedVertexWalker_visitVertex(walker, v2); + } + } - return v; + return v; } /** \} */ - /** \name Island Boundary Walker * \{ * @@ -668,88 +655,86 @@ static void *bmw_ConnectedVertexWalker_step(BMWalker *walker) */ static void bmw_IslandboundWalker_begin(BMWalker *walker, void *data) { - BMLoop *l = data; - BMwIslandboundWalker *iwalk = NULL; - - iwalk = BMW_state_add(walker); + BMLoop *l = data; + BMwIslandboundWalker *iwalk = NULL; - iwalk->base = iwalk->curloop = l; - iwalk->lastv = l->v; + iwalk = BMW_state_add(walker); - BLI_gset_insert(walker->visit_set, data); + iwalk->base = iwalk->curloop = l; + iwalk->lastv = l->v; + BLI_gset_insert(walker->visit_set, data); } static void *bmw_IslandboundWalker_yield(BMWalker *walker) { - BMwIslandboundWalker *iwalk = BMW_current_state(walker); + BMwIslandboundWalker *iwalk = BMW_current_state(walker); - return iwalk->curloop; + return iwalk->curloop; } static void *bmw_IslandboundWalker_step(BMWalker *walker) { - BMwIslandboundWalker *iwalk, owalk; - BMVert *v; - BMEdge *e; - BMFace *f; - BMLoop *l; - /* int found = 0; */ - - memcpy(&owalk, BMW_current_state(walker), sizeof(owalk)); - /* normally we'd remove here, but delay until after error checking */ - iwalk = &owalk; - - l = iwalk->curloop; - e = l->e; - - v = BM_edge_other_vert(e, iwalk->lastv); - - /* pop off current state */ - BMW_state_remove(walker); - - f = l->f; - - while (1) { - l = BM_loop_other_edge_loop(l, v); - if (BM_loop_is_manifold(l)) { - l = l->radial_next; - f = l->f; - e = l->e; - - if (!bmw_mask_check_face(walker, f)) { - l = l->radial_next; - break; - } - } - else { - /* treat non-manifold edges as boundaries */ - f = l->f; - e = l->e; - break; - } - } - - if (l == owalk.curloop) { - return NULL; - } - else if (BLI_gset_haskey(walker->visit_set, l)) { - return owalk.curloop; - } - - BLI_gset_insert(walker->visit_set, l); - iwalk = BMW_state_add(walker); - iwalk->base = owalk.base; - - //if (!BMO_face_flag_test(walker->bm, l->f, walker->restrictflag)) - // iwalk->curloop = l->radial_next; - iwalk->curloop = l; //else iwalk->curloop = l; - iwalk->lastv = v; - - return owalk.curloop; + BMwIslandboundWalker *iwalk, owalk; + BMVert *v; + BMEdge *e; + BMFace *f; + BMLoop *l; + /* int found = 0; */ + + memcpy(&owalk, BMW_current_state(walker), sizeof(owalk)); + /* normally we'd remove here, but delay until after error checking */ + iwalk = &owalk; + + l = iwalk->curloop; + e = l->e; + + v = BM_edge_other_vert(e, iwalk->lastv); + + /* pop off current state */ + BMW_state_remove(walker); + + f = l->f; + + while (1) { + l = BM_loop_other_edge_loop(l, v); + if (BM_loop_is_manifold(l)) { + l = l->radial_next; + f = l->f; + e = l->e; + + if (!bmw_mask_check_face(walker, f)) { + l = l->radial_next; + break; + } + } + else { + /* treat non-manifold edges as boundaries */ + f = l->f; + e = l->e; + break; + } + } + + if (l == owalk.curloop) { + return NULL; + } + else if (BLI_gset_haskey(walker->visit_set, l)) { + return owalk.curloop; + } + + BLI_gset_insert(walker->visit_set, l); + iwalk = BMW_state_add(walker); + iwalk->base = owalk.base; + + //if (!BMO_face_flag_test(walker->bm, l->f, walker->restrictflag)) + // iwalk->curloop = l->radial_next; + iwalk->curloop = l; //else iwalk->curloop = l; + iwalk->lastv = v; + + return owalk.curloop; } - /** \name Island Walker * \{ * @@ -759,90 +744,90 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker) */ static void bmw_IslandWalker_begin(BMWalker *walker, void *data) { - BMwIslandWalker *iwalk = NULL; + BMwIslandWalker *iwalk = NULL; - if (!bmw_mask_check_face(walker, data)) { - return; - } + if (!bmw_mask_check_face(walker, data)) { + return; + } - iwalk = BMW_state_add(walker); - BLI_gset_insert(walker->visit_set, data); + iwalk = BMW_state_add(walker); + BLI_gset_insert(walker->visit_set, data); - iwalk->cur = data; + iwalk->cur = data; } static void *bmw_IslandWalker_yield(BMWalker *walker) { - BMwIslandWalker *iwalk = BMW_current_state(walker); + BMwIslandWalker *iwalk = BMW_current_state(walker); - return iwalk->cur; + return iwalk->cur; } static void *bmw_IslandWalker_step_ex(BMWalker *walker, bool only_manifold) { - BMwIslandWalker *iwalk, owalk; - BMLoop *l_iter, *l_first; - - BMW_state_remove_r(walker, &owalk); - iwalk = &owalk; - - l_iter = l_first = BM_FACE_FIRST_LOOP(iwalk->cur); - do { - /* could skip loop here too, but don't add unless we need it */ - if (!bmw_mask_check_edge(walker, l_iter->e)) { - continue; - } - - BMLoop *l_radial_iter; - - if (only_manifold && (l_iter->radial_next != l_iter)) { - int face_count = 1; - /* check other faces (not this one), ensure only one other can be walked onto. */ - l_radial_iter = l_iter->radial_next; - do { - if (bmw_mask_check_face(walker, l_radial_iter->f)) { - face_count++; - if (face_count == 3) { - break; - } - } - } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter); - - if (face_count != 2) { - continue; - } - } - - l_radial_iter = l_iter; - while ((l_radial_iter = l_radial_iter->radial_next) != l_iter) { - BMFace *f = l_radial_iter->f; - - if (!bmw_mask_check_face(walker, f)) { - continue; - } - - /* saves checking BLI_gset_haskey below (manifold edges theres a 50% chance) */ - if (f == iwalk->cur) { - continue; - } - - if (BLI_gset_haskey(walker->visit_set, f)) { - continue; - } - - iwalk = BMW_state_add(walker); - iwalk->cur = f; - BLI_gset_insert(walker->visit_set, f); - break; - } - } while ((l_iter = l_iter->next) != l_first); - - return owalk.cur; + BMwIslandWalker *iwalk, owalk; + BMLoop *l_iter, *l_first; + + BMW_state_remove_r(walker, &owalk); + iwalk = &owalk; + + l_iter = l_first = BM_FACE_FIRST_LOOP(iwalk->cur); + do { + /* could skip loop here too, but don't add unless we need it */ + if (!bmw_mask_check_edge(walker, l_iter->e)) { + continue; + } + + BMLoop *l_radial_iter; + + if (only_manifold && (l_iter->radial_next != l_iter)) { + int face_count = 1; + /* check other faces (not this one), ensure only one other can be walked onto. */ + l_radial_iter = l_iter->radial_next; + do { + if (bmw_mask_check_face(walker, l_radial_iter->f)) { + face_count++; + if (face_count == 3) { + break; + } + } + } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter); + + if (face_count != 2) { + continue; + } + } + + l_radial_iter = l_iter; + while ((l_radial_iter = l_radial_iter->radial_next) != l_iter) { + BMFace *f = l_radial_iter->f; + + if (!bmw_mask_check_face(walker, f)) { + continue; + } + + /* saves checking BLI_gset_haskey below (manifold edges theres a 50% chance) */ + if (f == iwalk->cur) { + continue; + } + + if (BLI_gset_haskey(walker->visit_set, f)) { + continue; + } + + iwalk = BMW_state_add(walker); + iwalk->cur = f; + BLI_gset_insert(walker->visit_set, f); + break; + } + } while ((l_iter = l_iter->next) != l_first); + + return owalk.cur; } static void *bmw_IslandWalker_step(BMWalker *walker) { - return bmw_IslandWalker_step_ex(walker, false); + return bmw_IslandWalker_step_ex(walker, false); } /** @@ -850,12 +835,11 @@ static void *bmw_IslandWalker_step(BMWalker *walker) */ static void *bmw_IslandManifoldWalker_step(BMWalker *walker) { - return bmw_IslandWalker_step_ex(walker, true); + return bmw_IslandWalker_step_ex(walker, true); } /** \} */ - /** \name Edge Loop Walker * \{ * @@ -865,251 +849,238 @@ static void *bmw_IslandManifoldWalker_step(BMWalker *walker) /* utility function to see if an edge is apart of an ngon boundary */ static bool bm_edge_is_single(BMEdge *e) { - return ((BM_edge_is_boundary(e)) && - (e->l->f->len > 4) && - (BM_edge_is_boundary(e->l->next->e) || BM_edge_is_boundary(e->l->prev->e))); + return ((BM_edge_is_boundary(e)) && (e->l->f->len > 4) && + (BM_edge_is_boundary(e->l->next->e) || BM_edge_is_boundary(e->l->prev->e))); } static void bmw_EdgeLoopWalker_begin(BMWalker *walker, void *data) { - BMwEdgeLoopWalker *lwalk = NULL, owalk, *owalk_pt; - BMEdge *e = data; - BMVert *v; - const int vert_edge_count[2] = { - BM_vert_edge_count_nonwire(e->v1), - BM_vert_edge_count_nonwire(e->v2), - }; - - v = e->v1; - - lwalk = BMW_state_add(walker); - BLI_gset_insert(walker->visit_set, e); - - lwalk->cur = lwalk->start = e; - lwalk->lastv = lwalk->startv = v; - lwalk->is_boundary = BM_edge_is_boundary(e); - lwalk->is_single = (lwalk->is_boundary && bm_edge_is_single(e)); - - /* could also check that vertex*/ - if ((lwalk->is_boundary == false) && - (vert_edge_count[0] == 3 || vert_edge_count[1] == 3)) - { - BMIter iter; - BMFace *f_iter; - BMFace *f_best = NULL; - - BM_ITER_ELEM (f_iter, &iter, e, BM_FACES_OF_EDGE) { - if (f_best == NULL || f_best->len < f_iter->len) { - f_best = f_iter; - } - } - - if (f_best) { - /* only use hub selection for 5+ sides else this could - * conflict with normal edge loop selection. */ - lwalk->f_hub = f_best->len > 4 ? f_best : NULL; - } - else { - /* edge doesn't have any faces connected to it */ - lwalk->f_hub = NULL; - } - } - else { - lwalk->f_hub = NULL; - } - - /* rewind */ - while ((owalk_pt = BMW_current_state(walker))) { - owalk = *((BMwEdgeLoopWalker *)owalk_pt); - BMW_walk(walker); - } - - lwalk = BMW_state_add(walker); - *lwalk = owalk; - - lwalk->lastv = lwalk->startv = BM_edge_other_vert(owalk.cur, lwalk->lastv); - - BLI_gset_clear(walker->visit_set, NULL); - BLI_gset_insert(walker->visit_set, owalk.cur); + BMwEdgeLoopWalker *lwalk = NULL, owalk, *owalk_pt; + BMEdge *e = data; + BMVert *v; + const int vert_edge_count[2] = { + BM_vert_edge_count_nonwire(e->v1), + BM_vert_edge_count_nonwire(e->v2), + }; + + v = e->v1; + + lwalk = BMW_state_add(walker); + BLI_gset_insert(walker->visit_set, e); + + lwalk->cur = lwalk->start = e; + lwalk->lastv = lwalk->startv = v; + lwalk->is_boundary = BM_edge_is_boundary(e); + lwalk->is_single = (lwalk->is_boundary && bm_edge_is_single(e)); + + /* could also check that vertex*/ + if ((lwalk->is_boundary == false) && (vert_edge_count[0] == 3 || vert_edge_count[1] == 3)) { + BMIter iter; + BMFace *f_iter; + BMFace *f_best = NULL; + + BM_ITER_ELEM (f_iter, &iter, e, BM_FACES_OF_EDGE) { + if (f_best == NULL || f_best->len < f_iter->len) { + f_best = f_iter; + } + } + + if (f_best) { + /* only use hub selection for 5+ sides else this could + * conflict with normal edge loop selection. */ + lwalk->f_hub = f_best->len > 4 ? f_best : NULL; + } + else { + /* edge doesn't have any faces connected to it */ + lwalk->f_hub = NULL; + } + } + else { + lwalk->f_hub = NULL; + } + + /* rewind */ + while ((owalk_pt = BMW_current_state(walker))) { + owalk = *((BMwEdgeLoopWalker *)owalk_pt); + BMW_walk(walker); + } + + lwalk = BMW_state_add(walker); + *lwalk = owalk; + + lwalk->lastv = lwalk->startv = BM_edge_other_vert(owalk.cur, lwalk->lastv); + + BLI_gset_clear(walker->visit_set, NULL); + BLI_gset_insert(walker->visit_set, owalk.cur); } static void *bmw_EdgeLoopWalker_yield(BMWalker *walker) { - BMwEdgeLoopWalker *lwalk = BMW_current_state(walker); + BMwEdgeLoopWalker *lwalk = BMW_current_state(walker); - return lwalk->cur; + return lwalk->cur; } static void *bmw_EdgeLoopWalker_step(BMWalker *walker) { - BMwEdgeLoopWalker *lwalk, owalk; - BMEdge *e, *nexte = NULL; - BMLoop *l; - BMVert *v; - - BMW_state_remove_r(walker, &owalk); - lwalk = &owalk; - - e = lwalk->cur; - l = e->l; - - if (owalk.f_hub) { /* NGON EDGE */ - int vert_edge_tot; - - v = BM_edge_other_vert(e, lwalk->lastv); - - vert_edge_tot = BM_vert_edge_count_nonwire(v); - - if (vert_edge_tot == 3) { - l = BM_face_other_vert_loop(owalk.f_hub, lwalk->lastv, v); - nexte = BM_edge_exists(v, l->v); - - if (bmw_mask_check_edge(walker, nexte) && - !BLI_gset_haskey(walker->visit_set, nexte) && - /* never step onto a boundary edge, this gives odd-results */ - (BM_edge_is_boundary(nexte) == false)) - { - lwalk = BMW_state_add(walker); - lwalk->cur = nexte; - lwalk->lastv = v; - - lwalk->is_boundary = owalk.is_boundary; - lwalk->is_single = owalk.is_single; - lwalk->f_hub = owalk.f_hub; - - BLI_gset_insert(walker->visit_set, nexte); - } - } - } - else if (l == NULL) { /* WIRE EDGE */ - BMIter eiter; - - /* match trunk: mark all connected wire edges */ - for (int i = 0; i < 2; i++) { - v = i ? e->v2 : e->v1; - - BM_ITER_ELEM (nexte, &eiter, v, BM_EDGES_OF_VERT) { - if ((nexte->l == NULL) && - bmw_mask_check_edge(walker, nexte) && - !BLI_gset_haskey(walker->visit_set, nexte)) - { - lwalk = BMW_state_add(walker); - lwalk->cur = nexte; - lwalk->lastv = v; - - lwalk->is_boundary = owalk.is_boundary; - lwalk->is_single = owalk.is_single; - lwalk->f_hub = owalk.f_hub; - - BLI_gset_insert(walker->visit_set, nexte); - } - } - } - } - else if (owalk.is_boundary == false) { /* NORMAL EDGE WITH FACES */ - int vert_edge_tot; - - v = BM_edge_other_vert(e, lwalk->lastv); - - vert_edge_tot = BM_vert_edge_count_nonwire(v); - - /* typical loopiong over edges in the middle of a mesh */ - /* however, why use 2 here at all? I guess for internal ngon loops it can be useful. Antony R. */ - if (vert_edge_tot == 4 || vert_edge_tot == 2) { - int i_opposite = vert_edge_tot / 2; - int i = 0; - do { - l = BM_loop_other_edge_loop(l, v); - if (BM_edge_is_manifold(l->e)) { - l = l->radial_next; - } - else { - l = NULL; - break; - } - } while ((++i != i_opposite)); - } - else { - l = NULL; - } - - if (l != NULL) { - if (l != e->l && - bmw_mask_check_edge(walker, l->e) && - !BLI_gset_haskey(walker->visit_set, l->e)) - { - lwalk = BMW_state_add(walker); - lwalk->cur = l->e; - lwalk->lastv = v; - - lwalk->is_boundary = owalk.is_boundary; - lwalk->is_single = owalk.is_single; - lwalk->f_hub = owalk.f_hub; - - BLI_gset_insert(walker->visit_set, l->e); - } - } - } - else if (owalk.is_boundary == true) { /* BOUNDARY EDGE WITH FACES */ - int vert_edge_tot; - - v = BM_edge_other_vert(e, lwalk->lastv); - - vert_edge_tot = BM_vert_edge_count_nonwire(v); - - /* check if we should step, this is fairly involved */ - if ( - /* walk over boundary of faces but stop at corners */ - (owalk.is_single == false && vert_edge_tot > 2) || - - /* initial edge was a boundary, so is this edge and vertex is only apart of this face - * this lets us walk over the boundary of an ngon which is handy */ - (owalk.is_single == true && vert_edge_tot == 2 && BM_edge_is_boundary(e))) - { - /* find next boundary edge in the fan */ - do { - l = BM_loop_other_edge_loop(l, v); - if (BM_edge_is_manifold(l->e)) { - l = l->radial_next; - } - else if (BM_edge_is_boundary(l->e)) { - break; - } - else { - l = NULL; - break; - } - } while (true); - } - - if (owalk.is_single == false && l && bm_edge_is_single(l->e)) { - l = NULL; - } - - if (l != NULL) { - if (l != e->l && - bmw_mask_check_edge(walker, l->e) && - !BLI_gset_haskey(walker->visit_set, l->e)) - { - lwalk = BMW_state_add(walker); - lwalk->cur = l->e; - lwalk->lastv = v; - - lwalk->is_boundary = owalk.is_boundary; - lwalk->is_single = owalk.is_single; - lwalk->f_hub = owalk.f_hub; - - BLI_gset_insert(walker->visit_set, l->e); - } - } - } - - return owalk.cur; + BMwEdgeLoopWalker *lwalk, owalk; + BMEdge *e, *nexte = NULL; + BMLoop *l; + BMVert *v; + + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; + + e = lwalk->cur; + l = e->l; + + if (owalk.f_hub) { /* NGON EDGE */ + int vert_edge_tot; + + v = BM_edge_other_vert(e, lwalk->lastv); + + vert_edge_tot = BM_vert_edge_count_nonwire(v); + + if (vert_edge_tot == 3) { + l = BM_face_other_vert_loop(owalk.f_hub, lwalk->lastv, v); + nexte = BM_edge_exists(v, l->v); + + if (bmw_mask_check_edge(walker, nexte) && !BLI_gset_haskey(walker->visit_set, nexte) && + /* never step onto a boundary edge, this gives odd-results */ + (BM_edge_is_boundary(nexte) == false)) { + lwalk = BMW_state_add(walker); + lwalk->cur = nexte; + lwalk->lastv = v; + + lwalk->is_boundary = owalk.is_boundary; + lwalk->is_single = owalk.is_single; + lwalk->f_hub = owalk.f_hub; + + BLI_gset_insert(walker->visit_set, nexte); + } + } + } + else if (l == NULL) { /* WIRE EDGE */ + BMIter eiter; + + /* match trunk: mark all connected wire edges */ + for (int i = 0; i < 2; i++) { + v = i ? e->v2 : e->v1; + + BM_ITER_ELEM (nexte, &eiter, v, BM_EDGES_OF_VERT) { + if ((nexte->l == NULL) && bmw_mask_check_edge(walker, nexte) && + !BLI_gset_haskey(walker->visit_set, nexte)) { + lwalk = BMW_state_add(walker); + lwalk->cur = nexte; + lwalk->lastv = v; + + lwalk->is_boundary = owalk.is_boundary; + lwalk->is_single = owalk.is_single; + lwalk->f_hub = owalk.f_hub; + + BLI_gset_insert(walker->visit_set, nexte); + } + } + } + } + else if (owalk.is_boundary == false) { /* NORMAL EDGE WITH FACES */ + int vert_edge_tot; + + v = BM_edge_other_vert(e, lwalk->lastv); + + vert_edge_tot = BM_vert_edge_count_nonwire(v); + + /* typical loopiong over edges in the middle of a mesh */ + /* however, why use 2 here at all? I guess for internal ngon loops it can be useful. Antony R. */ + if (vert_edge_tot == 4 || vert_edge_tot == 2) { + int i_opposite = vert_edge_tot / 2; + int i = 0; + do { + l = BM_loop_other_edge_loop(l, v); + if (BM_edge_is_manifold(l->e)) { + l = l->radial_next; + } + else { + l = NULL; + break; + } + } while ((++i != i_opposite)); + } + else { + l = NULL; + } + + if (l != NULL) { + if (l != e->l && bmw_mask_check_edge(walker, l->e) && + !BLI_gset_haskey(walker->visit_set, l->e)) { + lwalk = BMW_state_add(walker); + lwalk->cur = l->e; + lwalk->lastv = v; + + lwalk->is_boundary = owalk.is_boundary; + lwalk->is_single = owalk.is_single; + lwalk->f_hub = owalk.f_hub; + + BLI_gset_insert(walker->visit_set, l->e); + } + } + } + else if (owalk.is_boundary == true) { /* BOUNDARY EDGE WITH FACES */ + int vert_edge_tot; + + v = BM_edge_other_vert(e, lwalk->lastv); + + vert_edge_tot = BM_vert_edge_count_nonwire(v); + + /* check if we should step, this is fairly involved */ + if ( + /* walk over boundary of faces but stop at corners */ + (owalk.is_single == false && vert_edge_tot > 2) || + + /* initial edge was a boundary, so is this edge and vertex is only apart of this face + * this lets us walk over the boundary of an ngon which is handy */ + (owalk.is_single == true && vert_edge_tot == 2 && BM_edge_is_boundary(e))) { + /* find next boundary edge in the fan */ + do { + l = BM_loop_other_edge_loop(l, v); + if (BM_edge_is_manifold(l->e)) { + l = l->radial_next; + } + else if (BM_edge_is_boundary(l->e)) { + break; + } + else { + l = NULL; + break; + } + } while (true); + } + + if (owalk.is_single == false && l && bm_edge_is_single(l->e)) { + l = NULL; + } + + if (l != NULL) { + if (l != e->l && bmw_mask_check_edge(walker, l->e) && + !BLI_gset_haskey(walker->visit_set, l->e)) { + lwalk = BMW_state_add(walker); + lwalk->cur = l->e; + lwalk->lastv = v; + + lwalk->is_boundary = owalk.is_boundary; + lwalk->is_single = owalk.is_single; + lwalk->f_hub = owalk.f_hub; + + BLI_gset_insert(walker->visit_set, l->e); + } + } + } + + return owalk.cur; } /** \} */ - /** \name Face Loop Walker * \{ * @@ -1122,139 +1093,138 @@ static void *bmw_EdgeLoopWalker_step(BMWalker *walker) * by the given BMLoop */ static bool bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l) { - /* face must have degree 4 */ - if (l->f->len != 4) { - return false; - } + /* face must have degree 4 */ + if (l->f->len != 4) { + return false; + } - if (!bmw_mask_check_face(walker, l->f)) { - return false; - } + if (!bmw_mask_check_face(walker, l->f)) { + return false; + } - /* the face must not have been already visited */ - if (BLI_gset_haskey(walker->visit_set, l->f) && BLI_gset_haskey(walker->visit_set_alt, l->e)) { - return false; - } + /* the face must not have been already visited */ + if (BLI_gset_haskey(walker->visit_set, l->f) && BLI_gset_haskey(walker->visit_set_alt, l->e)) { + return false; + } - return true; + return true; } /* Check whether the face loop can start from the given edge */ static bool bmw_FaceLoopWalker_edge_begins_loop(BMWalker *walker, BMEdge *e) { - /* There is no face loop starting from a wire edge */ - if (BM_edge_is_wire(e)) { - return false; - } - - /* Don't start a loop from a boundary edge if it cannot - * be extended to cover any faces */ - if (BM_edge_is_boundary(e)) { - if (!bmw_FaceLoopWalker_include_face(walker, e->l)) { - return false; - } - } - - /* Don't start a face loop from non-manifold edges */ - if (!BM_edge_is_manifold(e)) { - return false; - } - - return true; + /* There is no face loop starting from a wire edge */ + if (BM_edge_is_wire(e)) { + return false; + } + + /* Don't start a loop from a boundary edge if it cannot + * be extended to cover any faces */ + if (BM_edge_is_boundary(e)) { + if (!bmw_FaceLoopWalker_include_face(walker, e->l)) { + return false; + } + } + + /* Don't start a face loop from non-manifold edges */ + if (!BM_edge_is_manifold(e)) { + return false; + } + + return true; } static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data) { - BMwFaceLoopWalker *lwalk, owalk, *owalk_pt; - BMEdge *e = data; - /* BMesh *bm = walker->bm; */ /* UNUSED */ - /* int fcount = BM_edge_face_count(e); */ /* UNUSED */ - - if (!bmw_FaceLoopWalker_edge_begins_loop(walker, e)) { - return; - } - - lwalk = BMW_state_add(walker); - lwalk->l = e->l; - lwalk->no_calc = false; - BLI_gset_insert(walker->visit_set, lwalk->l->f); - - /* rewind */ - while ((owalk_pt = BMW_current_state(walker))) { - owalk = *((BMwFaceLoopWalker *)owalk_pt); - BMW_walk(walker); - } - - lwalk = BMW_state_add(walker); - *lwalk = owalk; - lwalk->no_calc = false; - - BLI_gset_clear(walker->visit_set_alt, NULL); - BLI_gset_insert(walker->visit_set_alt, lwalk->l->e); - - BLI_gset_clear(walker->visit_set, NULL); - BLI_gset_insert(walker->visit_set, lwalk->l->f); + BMwFaceLoopWalker *lwalk, owalk, *owalk_pt; + BMEdge *e = data; + /* BMesh *bm = walker->bm; */ /* UNUSED */ + /* int fcount = BM_edge_face_count(e); */ /* UNUSED */ + + if (!bmw_FaceLoopWalker_edge_begins_loop(walker, e)) { + return; + } + + lwalk = BMW_state_add(walker); + lwalk->l = e->l; + lwalk->no_calc = false; + BLI_gset_insert(walker->visit_set, lwalk->l->f); + + /* rewind */ + while ((owalk_pt = BMW_current_state(walker))) { + owalk = *((BMwFaceLoopWalker *)owalk_pt); + BMW_walk(walker); + } + + lwalk = BMW_state_add(walker); + *lwalk = owalk; + lwalk->no_calc = false; + + BLI_gset_clear(walker->visit_set_alt, NULL); + BLI_gset_insert(walker->visit_set_alt, lwalk->l->e); + + BLI_gset_clear(walker->visit_set, NULL); + BLI_gset_insert(walker->visit_set, lwalk->l->f); } static void *bmw_FaceLoopWalker_yield(BMWalker *walker) { - BMwFaceLoopWalker *lwalk = BMW_current_state(walker); + BMwFaceLoopWalker *lwalk = BMW_current_state(walker); - if (!lwalk) { - return NULL; - } + if (!lwalk) { + return NULL; + } - return lwalk->l->f; + return lwalk->l->f; } static void *bmw_FaceLoopWalker_step(BMWalker *walker) { - BMwFaceLoopWalker *lwalk, owalk; - BMFace *f; - BMLoop *l; - - BMW_state_remove_r(walker, &owalk); - lwalk = &owalk; - - f = lwalk->l->f; - l = lwalk->l->radial_next; - - if (lwalk->no_calc) { - return f; - } - - if (!bmw_FaceLoopWalker_include_face(walker, l)) { - l = lwalk->l; - l = l->next->next; - if (!BM_edge_is_manifold(l->e)) { - l = l->prev->prev; - } - l = l->radial_next; - } - - if (bmw_FaceLoopWalker_include_face(walker, l)) { - lwalk = BMW_state_add(walker); - lwalk->l = l; - - if (l->f->len != 4) { - lwalk->no_calc = true; - lwalk->l = owalk.l; - } - else { - lwalk->no_calc = false; - } - - /* both may already exist */ - BLI_gset_add(walker->visit_set_alt, l->e); - BLI_gset_add(walker->visit_set, l->f); - } - - return f; + BMwFaceLoopWalker *lwalk, owalk; + BMFace *f; + BMLoop *l; + + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; + + f = lwalk->l->f; + l = lwalk->l->radial_next; + + if (lwalk->no_calc) { + return f; + } + + if (!bmw_FaceLoopWalker_include_face(walker, l)) { + l = lwalk->l; + l = l->next->next; + if (!BM_edge_is_manifold(l->e)) { + l = l->prev->prev; + } + l = l->radial_next; + } + + if (bmw_FaceLoopWalker_include_face(walker, l)) { + lwalk = BMW_state_add(walker); + lwalk->l = l; + + if (l->f->len != 4) { + lwalk->no_calc = true; + lwalk->l = owalk.l; + } + else { + lwalk->no_calc = false; + } + + /* both may already exist */ + BLI_gset_add(walker->visit_set_alt, l->e); + BLI_gset_add(walker->visit_set, l->f); + } + + return f; } /** \} */ - // #define BMW_EDGERING_NGON /** \name Edge Ring Walker @@ -1266,210 +1236,205 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker) */ static void bmw_EdgeringWalker_begin(BMWalker *walker, void *data) { - BMwEdgeringWalker *lwalk, owalk, *owalk_pt; - BMEdge *e = data; + BMwEdgeringWalker *lwalk, owalk, *owalk_pt; + BMEdge *e = data; - lwalk = BMW_state_add(walker); - lwalk->l = e->l; + lwalk = BMW_state_add(walker); + lwalk->l = e->l; - if (!lwalk->l) { - lwalk->wireedge = e; - return; - } - else { - lwalk->wireedge = NULL; - } + if (!lwalk->l) { + lwalk->wireedge = e; + return; + } + else { + lwalk->wireedge = NULL; + } - BLI_gset_insert(walker->visit_set, lwalk->l->e); + BLI_gset_insert(walker->visit_set, lwalk->l->e); - /* rewind */ - while ((owalk_pt = BMW_current_state(walker))) { - owalk = *((BMwEdgeringWalker *)owalk_pt); - BMW_walk(walker); - } + /* rewind */ + while ((owalk_pt = BMW_current_state(walker))) { + owalk = *((BMwEdgeringWalker *)owalk_pt); + BMW_walk(walker); + } - lwalk = BMW_state_add(walker); - *lwalk = owalk; + lwalk = BMW_state_add(walker); + *lwalk = owalk; #ifdef BMW_EDGERING_NGON - if (lwalk->l->f->len % 2 != 0) + if (lwalk->l->f->len % 2 != 0) #else - if (lwalk->l->f->len != 4) + if (lwalk->l->f->len != 4) #endif - { - lwalk->l = lwalk->l->radial_next; - } + { + lwalk->l = lwalk->l->radial_next; + } - BLI_gset_clear(walker->visit_set, NULL); - BLI_gset_insert(walker->visit_set, lwalk->l->e); + BLI_gset_clear(walker->visit_set, NULL); + BLI_gset_insert(walker->visit_set, lwalk->l->e); } static void *bmw_EdgeringWalker_yield(BMWalker *walker) { - BMwEdgeringWalker *lwalk = BMW_current_state(walker); - - if (!lwalk) { - return NULL; - } - - if (lwalk->l) { - return lwalk->l->e; - } - else { - return lwalk->wireedge; - } + BMwEdgeringWalker *lwalk = BMW_current_state(walker); + + if (!lwalk) { + return NULL; + } + + if (lwalk->l) { + return lwalk->l->e; + } + else { + return lwalk->wireedge; + } } static void *bmw_EdgeringWalker_step(BMWalker *walker) { - BMwEdgeringWalker *lwalk, owalk; - BMEdge *e; - BMLoop *l; + BMwEdgeringWalker *lwalk, owalk; + BMEdge *e; + BMLoop *l; #ifdef BMW_EDGERING_NGON - int i, len; + int i, len; #endif -#define EDGE_CHECK(e) (bmw_mask_check_edge(walker, e) && (BM_edge_is_boundary(e) || BM_edge_is_manifold(e))) +#define EDGE_CHECK(e) \ + (bmw_mask_check_edge(walker, e) && (BM_edge_is_boundary(e) || BM_edge_is_manifold(e))) - BMW_state_remove_r(walker, &owalk); - lwalk = &owalk; + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; - l = lwalk->l; - if (!l) { - return lwalk->wireedge; - } + l = lwalk->l; + if (!l) { + return lwalk->wireedge; + } - e = l->e; - if (!EDGE_CHECK(e)) { - /* walker won't traverse to a non-manifold edge, but may - * be started on one, and should not traverse *away* from - * a non-manifold edge (non-manifold edges are never in an - * edge ring with manifold edges */ - return e; - } + e = l->e; + if (!EDGE_CHECK(e)) { + /* walker won't traverse to a non-manifold edge, but may + * be started on one, and should not traverse *away* from + * a non-manifold edge (non-manifold edges are never in an + * edge ring with manifold edges */ + return e; + } #ifdef BMW_EDGERING_NGON - l = l->radial_next; - - i = len = l->f->len; - while (i > 0) { - l = l->next; - i -= 2; - } - - if ((len <= 0) || (len % 2 != 0) || !EDGE_CHECK(l->e) || - !bmw_mask_check_face(walker, l->f)) - { - l = owalk.l; - i = len; - while (i > 0) { - l = l->next; - i -= 2; - } - } - /* only walk to manifold edge */ - if ((l->f->len % 2 == 0) && EDGE_CHECK(l->e) && - !BLI_gset_haskey(walker->visit_set, l->e)) + l = l->radial_next; + + i = len = l->f->len; + while (i > 0) { + l = l->next; + i -= 2; + } + + if ((len <= 0) || (len % 2 != 0) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) { + l = owalk.l; + i = len; + while (i > 0) { + l = l->next; + i -= 2; + } + } + /* only walk to manifold edge */ + if ((l->f->len % 2 == 0) && EDGE_CHECK(l->e) && !BLI_gset_haskey(walker->visit_set, l->e)) #else - l = l->radial_next; - l = l->next->next; + l = l->radial_next; + l = l->next->next; - if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) { - l = owalk.l->next->next; - } - /* only walk to manifold edge */ - if ((l->f->len == 4) && EDGE_CHECK(l->e) && - !BLI_gset_haskey(walker->visit_set, l->e)) + if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) { + l = owalk.l->next->next; + } + /* only walk to manifold edge */ + if ((l->f->len == 4) && EDGE_CHECK(l->e) && !BLI_gset_haskey(walker->visit_set, l->e)) #endif - { - lwalk = BMW_state_add(walker); - lwalk->l = l; - lwalk->wireedge = NULL; + { + lwalk = BMW_state_add(walker); + lwalk->l = l; + lwalk->wireedge = NULL; - BLI_gset_insert(walker->visit_set, l->e); - } + BLI_gset_insert(walker->visit_set, l->e); + } - return e; + return e; #undef EDGE_CHECK } /** \} */ - /** \name Boundary Edge Walker * \{ */ static void bmw_EdgeboundaryWalker_begin(BMWalker *walker, void *data) { - BMwEdgeboundaryWalker *lwalk; - BMEdge *e = data; + BMwEdgeboundaryWalker *lwalk; + BMEdge *e = data; - BLI_assert(BM_edge_is_boundary(e)); + BLI_assert(BM_edge_is_boundary(e)); - if (BLI_gset_haskey(walker->visit_set, e)) { - return; - } + if (BLI_gset_haskey(walker->visit_set, e)) { + return; + } - lwalk = BMW_state_add(walker); - lwalk->e = e; - BLI_gset_insert(walker->visit_set, e); + lwalk = BMW_state_add(walker); + lwalk->e = e; + BLI_gset_insert(walker->visit_set, e); } static void *bmw_EdgeboundaryWalker_yield(BMWalker *walker) { - BMwEdgeboundaryWalker *lwalk = BMW_current_state(walker); + BMwEdgeboundaryWalker *lwalk = BMW_current_state(walker); - if (!lwalk) { - return NULL; - } + if (!lwalk) { + return NULL; + } - return lwalk->e; + return lwalk->e; } static void *bmw_EdgeboundaryWalker_step(BMWalker *walker) { - BMwEdgeboundaryWalker *lwalk, owalk; - BMEdge *e, *e_other; - BMVert *v; - BMIter eiter; - BMIter viter; + BMwEdgeboundaryWalker *lwalk, owalk; + BMEdge *e, *e_other; + BMVert *v; + BMIter eiter; + BMIter viter; - BMW_state_remove_r(walker, &owalk); - lwalk = &owalk; + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; - e = lwalk->e; + e = lwalk->e; - if (!bmw_mask_check_edge(walker, e)) { - return e; - } + if (!bmw_mask_check_edge(walker, e)) { + return e; + } - BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) { - BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) { - if (e != e_other && BM_edge_is_boundary(e_other)) { - if (BLI_gset_haskey(walker->visit_set, e_other)) { - continue; - } + BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) { + BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) { + if (e != e_other && BM_edge_is_boundary(e_other)) { + if (BLI_gset_haskey(walker->visit_set, e_other)) { + continue; + } - if (!bmw_mask_check_edge(walker, e_other)) { - continue; - } + if (!bmw_mask_check_edge(walker, e_other)) { + continue; + } - lwalk = BMW_state_add(walker); - BLI_gset_insert(walker->visit_set, e_other); + lwalk = BMW_state_add(walker); + BLI_gset_insert(walker->visit_set, e_other); - lwalk->e = e_other; - } - } - } + lwalk->e = e_other; + } + } + } - return e; + return e; } /** \} */ - /** \name UV Edge Walker * * walk over uv islands; takes a loop as input. restrict flag @@ -1482,238 +1447,239 @@ static void *bmw_EdgeboundaryWalker_step(BMWalker *walker) static void bmw_UVEdgeWalker_begin(BMWalker *walker, void *data) { - BMwUVEdgeWalker *lwalk; - BMLoop *l = data; + BMwUVEdgeWalker *lwalk; + BMLoop *l = data; - if (BLI_gset_haskey(walker->visit_set, l)) { - return; - } + if (BLI_gset_haskey(walker->visit_set, l)) { + return; + } - lwalk = BMW_state_add(walker); - lwalk->l = l; - BLI_gset_insert(walker->visit_set, l); + lwalk = BMW_state_add(walker); + lwalk->l = l; + BLI_gset_insert(walker->visit_set, l); } static void *bmw_UVEdgeWalker_yield(BMWalker *walker) { - BMwUVEdgeWalker *lwalk = BMW_current_state(walker); + BMwUVEdgeWalker *lwalk = BMW_current_state(walker); - if (!lwalk) { - return NULL; - } + if (!lwalk) { + return NULL; + } - return lwalk->l; + return lwalk->l; } static void *bmw_UVEdgeWalker_step(BMWalker *walker) { - const int type = walker->bm->ldata.layers[walker->layer].type; - const int offset = walker->bm->ldata.layers[walker->layer].offset; + const int type = walker->bm->ldata.layers[walker->layer].type; + const int offset = walker->bm->ldata.layers[walker->layer].offset; - BMwUVEdgeWalker *lwalk, owalk; - BMLoop *l; - int i; + BMwUVEdgeWalker *lwalk, owalk; + BMLoop *l; + int i; - BMW_state_remove_r(walker, &owalk); - lwalk = &owalk; + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; - l = lwalk->l; + l = lwalk->l; - if (!bmw_mask_check_edge(walker, l->e)) { - return l; - } + if (!bmw_mask_check_edge(walker, l->e)) { + return l; + } - /* go over loops around l->v and nl->v and see which ones share l and nl's - * mloopuv's coordinates. in addition, push on l->next if necessary */ - for (i = 0; i < 2; i++) { - BMIter liter; - BMLoop *l_pivot, *l_radial; + /* go over loops around l->v and nl->v and see which ones share l and nl's + * mloopuv's coordinates. in addition, push on l->next if necessary */ + for (i = 0; i < 2; i++) { + BMIter liter; + BMLoop *l_pivot, *l_radial; - l_pivot = i ? l->next : l; - BM_ITER_ELEM (l_radial, &liter, l_pivot->v, BM_LOOPS_OF_VERT) { - BMLoop *l_radial_first = l_radial; - void *data_pivot = BM_ELEM_CD_GET_VOID_P(l_pivot, offset); + l_pivot = i ? l->next : l; + BM_ITER_ELEM (l_radial, &liter, l_pivot->v, BM_LOOPS_OF_VERT) { + BMLoop *l_radial_first = l_radial; + void *data_pivot = BM_ELEM_CD_GET_VOID_P(l_pivot, offset); - do { - BMLoop *l_other; - void *data_other; + do { + BMLoop *l_other; + void *data_other; - if (BLI_gset_haskey(walker->visit_set, l_radial)) { - continue; - } + if (BLI_gset_haskey(walker->visit_set, l_radial)) { + continue; + } - if (l_radial->v != l_pivot->v) { - if (!bmw_mask_check_edge(walker, l_radial->e)) { - continue; - } - } + if (l_radial->v != l_pivot->v) { + if (!bmw_mask_check_edge(walker, l_radial->e)) { + continue; + } + } - l_other = (l_radial->v != l_pivot->v) ? l_radial->next : l_radial; - data_other = BM_ELEM_CD_GET_VOID_P(l_other, offset); + l_other = (l_radial->v != l_pivot->v) ? l_radial->next : l_radial; + data_other = BM_ELEM_CD_GET_VOID_P(l_other, offset); - if (!CustomData_data_equals(type, data_pivot, data_other)) { - continue; - } + if (!CustomData_data_equals(type, data_pivot, data_other)) { + continue; + } - lwalk = BMW_state_add(walker); - BLI_gset_insert(walker->visit_set, l_radial); + lwalk = BMW_state_add(walker); + BLI_gset_insert(walker->visit_set, l_radial); - lwalk->l = l_radial; + lwalk->l = l_radial; - } while ((l_radial = l_radial->radial_next) != l_radial_first); - } - } + } while ((l_radial = l_radial->radial_next) != l_radial_first); + } + } - return l; + return l; } /** \} */ - static BMWalker bmw_VertShellWalker_Type = { - BM_VERT | BM_EDGE, - bmw_VertShellWalker_begin, - bmw_VertShellWalker_step, - bmw_VertShellWalker_yield, - sizeof(BMwShellWalker), - BMW_BREADTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_VERT | BM_EDGE, + bmw_VertShellWalker_begin, + bmw_VertShellWalker_step, + bmw_VertShellWalker_yield, + sizeof(BMwShellWalker), + BMW_BREADTH_FIRST, + BM_EDGE, /* valid restrict masks */ }; static BMWalker bmw_LoopShellWalker_Type = { - BM_FACE | BM_LOOP | BM_EDGE | BM_VERT, - bmw_LoopShellWalker_begin, - bmw_LoopShellWalker_step, - bmw_LoopShellWalker_yield, - sizeof(BMwLoopShellWalker), - BMW_BREADTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_FACE | BM_LOOP | BM_EDGE | BM_VERT, + bmw_LoopShellWalker_begin, + bmw_LoopShellWalker_step, + bmw_LoopShellWalker_yield, + sizeof(BMwLoopShellWalker), + BMW_BREADTH_FIRST, + BM_EDGE, /* valid restrict masks */ }; static BMWalker bmw_LoopShellWireWalker_Type = { - BM_FACE | BM_LOOP | BM_EDGE | BM_VERT, - bmw_LoopShellWireWalker_begin, - bmw_LoopShellWireWalker_step, - bmw_LoopShellWireWalker_yield, - sizeof(BMwLoopShellWireWalker), - BMW_BREADTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_FACE | BM_LOOP | BM_EDGE | BM_VERT, + bmw_LoopShellWireWalker_begin, + bmw_LoopShellWireWalker_step, + bmw_LoopShellWireWalker_yield, + sizeof(BMwLoopShellWireWalker), + BMW_BREADTH_FIRST, + BM_EDGE, /* valid restrict masks */ }; static BMWalker bmw_FaceShellWalker_Type = { - BM_EDGE, - bmw_FaceShellWalker_begin, - bmw_FaceShellWalker_step, - bmw_FaceShellWalker_yield, - sizeof(BMwShellWalker), - BMW_BREADTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_EDGE, + bmw_FaceShellWalker_begin, + bmw_FaceShellWalker_step, + bmw_FaceShellWalker_yield, + sizeof(BMwShellWalker), + BMW_BREADTH_FIRST, + BM_EDGE, /* valid restrict masks */ }; static BMWalker bmw_IslandboundWalker_Type = { - BM_LOOP, - bmw_IslandboundWalker_begin, - bmw_IslandboundWalker_step, - bmw_IslandboundWalker_yield, - sizeof(BMwIslandboundWalker), - BMW_DEPTH_FIRST, - BM_FACE, /* valid restrict masks */ + BM_LOOP, + bmw_IslandboundWalker_begin, + bmw_IslandboundWalker_step, + bmw_IslandboundWalker_yield, + sizeof(BMwIslandboundWalker), + BMW_DEPTH_FIRST, + BM_FACE, /* valid restrict masks */ }; static BMWalker bmw_IslandWalker_Type = { - BM_FACE, - bmw_IslandWalker_begin, - bmw_IslandWalker_step, - bmw_IslandWalker_yield, - sizeof(BMwIslandWalker), - BMW_BREADTH_FIRST, - BM_EDGE | BM_FACE, /* valid restrict masks */ + BM_FACE, + bmw_IslandWalker_begin, + bmw_IslandWalker_step, + bmw_IslandWalker_yield, + sizeof(BMwIslandWalker), + BMW_BREADTH_FIRST, + BM_EDGE | BM_FACE, /* valid restrict masks */ }; static BMWalker bmw_IslandManifoldWalker_Type = { - BM_FACE, - bmw_IslandWalker_begin, - bmw_IslandManifoldWalker_step, /* only difference with BMW_ISLAND */ - bmw_IslandWalker_yield, - sizeof(BMwIslandWalker), - BMW_BREADTH_FIRST, - BM_EDGE | BM_FACE, /* valid restrict masks */ + BM_FACE, + bmw_IslandWalker_begin, + bmw_IslandManifoldWalker_step, /* only difference with BMW_ISLAND */ + bmw_IslandWalker_yield, + sizeof(BMwIslandWalker), + BMW_BREADTH_FIRST, + BM_EDGE | BM_FACE, /* valid restrict masks */ }; static BMWalker bmw_EdgeLoopWalker_Type = { - BM_EDGE, - bmw_EdgeLoopWalker_begin, - bmw_EdgeLoopWalker_step, - bmw_EdgeLoopWalker_yield, - sizeof(BMwEdgeLoopWalker), - BMW_DEPTH_FIRST, - 0, /* valid restrict masks */ /* could add flags here but so far none are used */ + BM_EDGE, + bmw_EdgeLoopWalker_begin, + bmw_EdgeLoopWalker_step, + bmw_EdgeLoopWalker_yield, + sizeof(BMwEdgeLoopWalker), + BMW_DEPTH_FIRST, + 0, + /* valid restrict masks */ /* could add flags here but so far none are used */ }; static BMWalker bmw_FaceLoopWalker_Type = { - BM_EDGE, - bmw_FaceLoopWalker_begin, - bmw_FaceLoopWalker_step, - bmw_FaceLoopWalker_yield, - sizeof(BMwFaceLoopWalker), - BMW_DEPTH_FIRST, - 0, /* valid restrict masks */ /* could add flags here but so far none are used */ + BM_EDGE, + bmw_FaceLoopWalker_begin, + bmw_FaceLoopWalker_step, + bmw_FaceLoopWalker_yield, + sizeof(BMwFaceLoopWalker), + BMW_DEPTH_FIRST, + 0, + /* valid restrict masks */ /* could add flags here but so far none are used */ }; static BMWalker bmw_EdgeringWalker_Type = { - BM_EDGE, - bmw_EdgeringWalker_begin, - bmw_EdgeringWalker_step, - bmw_EdgeringWalker_yield, - sizeof(BMwEdgeringWalker), - BMW_DEPTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_EDGE, + bmw_EdgeringWalker_begin, + bmw_EdgeringWalker_step, + bmw_EdgeringWalker_yield, + sizeof(BMwEdgeringWalker), + BMW_DEPTH_FIRST, + BM_EDGE, /* valid restrict masks */ }; static BMWalker bmw_EdgeboundaryWalker_Type = { - BM_EDGE, - bmw_EdgeboundaryWalker_begin, - bmw_EdgeboundaryWalker_step, - bmw_EdgeboundaryWalker_yield, - sizeof(BMwEdgeboundaryWalker), - BMW_DEPTH_FIRST, - 0, + BM_EDGE, + bmw_EdgeboundaryWalker_begin, + bmw_EdgeboundaryWalker_step, + bmw_EdgeboundaryWalker_yield, + sizeof(BMwEdgeboundaryWalker), + BMW_DEPTH_FIRST, + 0, }; static BMWalker bmw_UVEdgeWalker_Type = { - BM_LOOP, - bmw_UVEdgeWalker_begin, - bmw_UVEdgeWalker_step, - bmw_UVEdgeWalker_yield, - sizeof(BMwUVEdgeWalker), - BMW_DEPTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_LOOP, + bmw_UVEdgeWalker_begin, + bmw_UVEdgeWalker_step, + bmw_UVEdgeWalker_yield, + sizeof(BMwUVEdgeWalker), + BMW_DEPTH_FIRST, + BM_EDGE, /* valid restrict masks */ }; static BMWalker bmw_ConnectedVertexWalker_Type = { - BM_VERT, - bmw_ConnectedVertexWalker_begin, - bmw_ConnectedVertexWalker_step, - bmw_ConnectedVertexWalker_yield, - sizeof(BMwConnectedVertexWalker), - BMW_BREADTH_FIRST, - BM_VERT, /* valid restrict masks */ + BM_VERT, + bmw_ConnectedVertexWalker_begin, + bmw_ConnectedVertexWalker_step, + bmw_ConnectedVertexWalker_yield, + sizeof(BMwConnectedVertexWalker), + BMW_BREADTH_FIRST, + BM_VERT, /* valid restrict masks */ }; BMWalker *bm_walker_types[] = { - &bmw_VertShellWalker_Type, /* BMW_VERT_SHELL */ - &bmw_LoopShellWalker_Type, /* BMW_LOOP_SHELL */ - &bmw_LoopShellWireWalker_Type, /* BMW_LOOP_SHELL_WIRE */ - &bmw_FaceShellWalker_Type, /* BMW_FACE_SHELL */ - &bmw_EdgeLoopWalker_Type, /* BMW_EDGELOOP */ - &bmw_FaceLoopWalker_Type, /* BMW_FACELOOP */ - &bmw_EdgeringWalker_Type, /* BMW_EDGERING */ - &bmw_EdgeboundaryWalker_Type, /* BMW_EDGEBOUNDARY */ - &bmw_UVEdgeWalker_Type, /* BMW_LOOPDATA_ISLAND */ - &bmw_IslandboundWalker_Type, /* BMW_ISLANDBOUND */ - &bmw_IslandWalker_Type, /* BMW_ISLAND */ - &bmw_IslandManifoldWalker_Type, /* BMW_ISLAND_MANIFOLD */ - &bmw_ConnectedVertexWalker_Type, /* BMW_CONNECTED_VERTEX */ + &bmw_VertShellWalker_Type, /* BMW_VERT_SHELL */ + &bmw_LoopShellWalker_Type, /* BMW_LOOP_SHELL */ + &bmw_LoopShellWireWalker_Type, /* BMW_LOOP_SHELL_WIRE */ + &bmw_FaceShellWalker_Type, /* BMW_FACE_SHELL */ + &bmw_EdgeLoopWalker_Type, /* BMW_EDGELOOP */ + &bmw_FaceLoopWalker_Type, /* BMW_FACELOOP */ + &bmw_EdgeringWalker_Type, /* BMW_EDGERING */ + &bmw_EdgeboundaryWalker_Type, /* BMW_EDGEBOUNDARY */ + &bmw_UVEdgeWalker_Type, /* BMW_LOOPDATA_ISLAND */ + &bmw_IslandboundWalker_Type, /* BMW_ISLANDBOUND */ + &bmw_IslandWalker_Type, /* BMW_ISLAND */ + &bmw_IslandManifoldWalker_Type, /* BMW_ISLAND_MANIFOLD */ + &bmw_ConnectedVertexWalker_Type, /* BMW_CONNECTED_VERTEX */ }; const int bm_totwalkers = ARRAY_SIZE(bm_walker_types); diff --git a/source/blender/bmesh/intern/bmesh_walkers_private.h b/source/blender/bmesh/intern/bmesh_walkers_private.h index 185c18d6777..3457a2b9187 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_private.h +++ b/source/blender/bmesh/intern/bmesh_walkers_private.h @@ -26,75 +26,73 @@ extern BMWalker *bm_walker_types[]; extern const int bm_totwalkers; - /* Pointer hiding */ typedef struct BMwGenericWalker { - Link link; - int depth; + Link link; + int depth; } BMwGenericWalker; - typedef struct BMwShellWalker { - BMwGenericWalker header; - BMEdge *curedge; + BMwGenericWalker header; + BMEdge *curedge; } BMwShellWalker; typedef struct BMwLoopShellWalker { - BMwGenericWalker header; - BMLoop *curloop; + BMwGenericWalker header; + BMLoop *curloop; } BMwLoopShellWalker; typedef struct BMwLoopShellWireWalker { - BMwGenericWalker header; - BMElem *curelem; + BMwGenericWalker header; + BMElem *curelem; } BMwLoopShellWireWalker; typedef struct BMwIslandboundWalker { - BMwGenericWalker header; - BMLoop *base; - BMVert *lastv; - BMLoop *curloop; + BMwGenericWalker header; + BMLoop *base; + BMVert *lastv; + BMLoop *curloop; } BMwIslandboundWalker; typedef struct BMwIslandWalker { - BMwGenericWalker header; - BMFace *cur; + BMwGenericWalker header; + BMFace *cur; } BMwIslandWalker; typedef struct BMwEdgeLoopWalker { - BMwGenericWalker header; - BMEdge *cur, *start; - BMVert *lastv, *startv; - BMFace *f_hub; - bool is_boundary; /* boundary looping changes behavior */ - bool is_single; /* single means the edge verts are only connected to 1 face */ + BMwGenericWalker header; + BMEdge *cur, *start; + BMVert *lastv, *startv; + BMFace *f_hub; + bool is_boundary; /* boundary looping changes behavior */ + bool is_single; /* single means the edge verts are only connected to 1 face */ } BMwEdgeLoopWalker; typedef struct BMwFaceLoopWalker { - BMwGenericWalker header; - BMLoop *l; - bool no_calc; + BMwGenericWalker header; + BMLoop *l; + bool no_calc; } BMwFaceLoopWalker; typedef struct BMwEdgeringWalker { - BMwGenericWalker header; - BMLoop *l; - BMEdge *wireedge; + BMwGenericWalker header; + BMLoop *l; + BMEdge *wireedge; } BMwEdgeringWalker; typedef struct BMwEdgeboundaryWalker { - BMwGenericWalker header; - BMEdge *e; + BMwGenericWalker header; + BMEdge *e; } BMwEdgeboundaryWalker; typedef struct BMwUVEdgeWalker { - BMwGenericWalker header; - BMLoop *l; + BMwGenericWalker header; + BMLoop *l; } BMwUVEdgeWalker; typedef struct BMwConnectedVertexWalker { - BMwGenericWalker header; - BMVert *curvert; + BMwGenericWalker header; + BMVert *curvert; } BMwConnectedVertexWalker; #endif /* __BMESH_WALKERS_PRIVATE_H__ */ |