Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_construct.c')
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c177
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);