diff options
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_construct.c')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_construct.c | 177 |
1 files changed, 66 insertions, 111 deletions
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index f5856ee94b3..1a7464ce340 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -35,6 +35,7 @@ #include "BLI_alloca.h" #include "BLI_math.h" +#include "BLI_sort_utils.h" #include "BKE_customdata.h" @@ -65,95 +66,69 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - const BMFace *example, const bool no_double) + const BMFace *f_example, const eBMCreateFlag create_flag) { BMVert *vtar[4] = {v1, v2, v3, v4}; - return BM_face_create_quad_tri_v(bm, vtar, v4 ? 4 : 3, example, no_double); -} - -BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFace *example, const bool no_double) -{ - BMFace *f = NULL; - bool is_overlap = false; - - /* sanity check - debug mode only */ - if (len == 3) { - BLI_assert(verts[0] != verts[1]); - BLI_assert(verts[0] != verts[2]); - BLI_assert(verts[1] != verts[2]); - } - else if (len == 4) { - BLI_assert(verts[0] != verts[1]); - BLI_assert(verts[0] != verts[2]); - BLI_assert(verts[0] != verts[3]); - - BLI_assert(verts[1] != verts[2]); - BLI_assert(verts[1] != verts[3]); - - BLI_assert(verts[2] != verts[3]); - } - else { - BLI_assert(0); - } - - - if (no_double) { - /* check if face exists or overlaps */ - is_overlap = BM_face_exists(verts, len, &f); - } - - /* make new face */ - if ((f == NULL) && (!is_overlap)) { - BMEdge *edar[4] = {NULL}; - edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE); - edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, BM_CREATE_NO_DOUBLE); - if (len == 4) { - edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, BM_CREATE_NO_DOUBLE); - edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, BM_CREATE_NO_DOUBLE); - } - else { - edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, BM_CREATE_NO_DOUBLE); - } - - f = BM_face_create(bm, verts, edar, len, 0); - - if (example && f) { - BM_elem_attrs_copy(bm, bm, example, f); - } - } - - return f; + return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true); } /** * \brief copies face loop data from shared adjacent faces. + * + * \param filter_fn A function that filters the source loops before copying (don't always want to copy all) + * * \note when a matching edge is found, both loops of that edge are copied * 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) + * 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, + BMElemFilterFunc filter_fn, void *user_data) { 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); +#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}; + unsigned int j; + if (l_other->v == l_iter->v) { - bm_loop_attrs_copy(bm, bm, l_other, l_iter); - bm_loop_attrs_copy(bm, bm, l_other->next, l_iter->next); + l_src[0] = l_other; + l_src[1] = l_other->next; } else { - bm_loop_attrs_copy(bm, bm, l_other->next, l_iter); - bm_loop_attrs_copy(bm, bm, l_other, l_iter->next); + l_src[0] = l_other->next; + l_src[1] = l_other; } - /* since we copy both loops of the shared edge, step over the next loop here */ - if ((l_iter = l_iter->next) == l_first) { - break; + + 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((BMElem *)l_src[j], user_data)) { + bm_loop_attrs_copy(bm, bm, l_src[j], l_dst[j]); + 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); } /** @@ -171,7 +146,8 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f) * #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 int 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 + 1); @@ -290,7 +266,7 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, c BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV); } - f = BM_face_create(bm, verts_sort, edges_sort, len, create_flag); + f = BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag); /* clean up flags */ for (i = 0; i < len; i++) { @@ -318,7 +294,8 @@ err: * - 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 int 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) { BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); @@ -378,21 +355,8 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, c bm, v_winding[winding[0]], v_winding[winding[1]], - edge_arr, len, create_flag); -} - - -typedef struct AngleIndexPair { - float angle; - int index; -} AngleIndexPair; - -static int angle_index_pair_cmp(const void *e1, const void *e2) -{ - const AngleIndexPair *p1 = e1, *p2 = e2; - if (p1->angle > p2->angle) return 1; - else if (p1->angle < p2->angle) return -1; - else return 0; + edge_arr, len, + f_example, create_flag); } /** @@ -411,8 +375,12 @@ static int angle_index_pair_cmp(const void *e1, const void *e2) * * \note Since this is a vcloud there is no direction. */ -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const int create_flag) +BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, + const BMFace *f_example, const eBMCreateFlag create_flag) { + struct SortIntByFloat *vang = BLI_array_alloca(vang, len); + BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len); + BMFace *f; float totv_inv = 1.0f / (float)len; @@ -429,10 +397,6 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const float far_dist, far_best; float far_cross_dist, far_cross_best = 0.0f; - AngleIndexPair *vang; - - BMVert **vert_arr_map; - /* get the center point and collect vector array since we loop over these a lot */ zero_v3(cent); for (i = 0; i < len; i++) { @@ -492,8 +456,6 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const /* --- */ /* now calculate every points angle around the normal (signed) */ - vang = MEM_mallocN(sizeof(AngleIndexPair) * len, __func__); - for (i = 0; i < len; i++) { float co[3]; float proj_vec[3]; @@ -513,26 +475,21 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const angle = -angle; } - vang[i].angle = angle; - vang[i].index = i; + vang[i].sort_value = angle; + vang[i].data = i; } /* sort by angle and magic! - we have our ngon */ - qsort(vang, len, sizeof(AngleIndexPair), angle_index_pair_cmp); + qsort(vang, len, sizeof(*vang), BLI_sortutil_cmp_float); /* --- */ /* create edges and find the winding (if faces are attached to any existing edges) */ - vert_arr_map = MEM_mallocN(sizeof(BMVert *) * len, __func__); - for (i = 0; i < len; i++) { - vert_arr_map[i] = vert_arr[vang[i].index]; + vert_arr_map[i] = vert_arr[vang[i].data]; } - MEM_freeN(vang); - - f = BM_face_create_ngon_verts(bm, vert_arr_map, len, create_flag, true, true); - MEM_freeN(vert_arr_map); + f = BM_face_create_ngon_verts(bm, vert_arr_map, len, f_example, create_flag, true, true); return f; } @@ -543,10 +500,10 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const */ void BMO_remove_tagged_faces(BMesh *bm, const short oflag) { - BMFace *f; + BMFace *f, *f_next; BMIter iter; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) { if (BMO_elem_flag_test(bm, f, oflag)) { BM_face_kill(bm, f); } @@ -555,10 +512,10 @@ void BMO_remove_tagged_faces(BMesh *bm, const short oflag) void BMO_remove_tagged_edges(BMesh *bm, const short oflag) { - BMEdge *e; + BMEdge *e, *e_next; BMIter iter; - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { if (BMO_elem_flag_test(bm, e, oflag)) { BM_edge_kill(bm, e); } @@ -567,10 +524,10 @@ void BMO_remove_tagged_edges(BMesh *bm, const short oflag) void BMO_remove_tagged_verts(BMesh *bm, const short oflag) { - BMVert *v; + BMVert *v, *v_next; BMIter iter; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BMO_elem_flag_test(bm, v, oflag)) { BM_vert_kill(bm, v); } @@ -824,6 +781,7 @@ void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, BMHeader *ele_dst = ele_dst_v; BLI_assert(ele_src->htype == ele_dst->htype); + BLI_assert(ele_src != ele_dst); if ((hflag_mask & BM_ELEM_SELECT) == 0) { /* First we copy select */ @@ -903,7 +861,7 @@ static BMFace *bm_mesh_copy_new_face(BMesh *bm_new, BMesh *bm_old, j++; } while ((l_iter = l_iter->next) != l_first); - f_new = BM_face_create(bm_new, verts, edges, f->len, BM_CREATE_SKIP_CD); + f_new = BM_face_create(bm_new, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD); if (UNLIKELY(f_new == NULL)) { return NULL; @@ -953,10 +911,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old) BMEditSelection *ese; BMIter iter; int i; - const BMAllocTemplate allocsize = {bm_old->totvert, - bm_old->totedge, - bm_old->totloop, - bm_old->totface}; + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm_old); /* allocate a bmesh */ bm_new = BM_mesh_create(&allocsize); |