diff options
author | Sergej Reich <sergej.reich@googlemail.com> | 2013-10-13 15:41:41 +0400 |
---|---|---|
committer | Sergej Reich <sergej.reich@googlemail.com> | 2013-10-13 15:41:41 +0400 |
commit | 5d5176095e82b34499e15d74f1fb76d56f4d9508 (patch) | |
tree | dd8c61741160804873601f6b6350661132ac1b2f /source/blender/bmesh | |
parent | bcbf976b48762c2f25df470c6d13a124bc868a66 (diff) | |
parent | 42ac7164e30dcca565253aa265201aad497e5360 (diff) |
svn merge -r60422:60726 ^/trunk/blender
Diffstat (limited to 'source/blender/bmesh')
28 files changed, 390 insertions, 365 deletions
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index 930964667e9..1a7464ce340 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -500,10 +500,10 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, */ 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); } @@ -512,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); } @@ -524,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); } diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 164a92125cd..8441a6ec75f 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2279,3 +2279,28 @@ BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep) BMLoop *l = BM_face_vert_share_loop(f_sep, v_sep); return bmesh_urmv_loop(bm, l); } + +/** + * Avoid calling this where possible, + * low level function so both face pointers remain intact but point to swapped data. + * \note must be from the same bmesh. + */ +void bmesh_face_swap_data(BMesh *bm, BMFace *f_a, BMFace *f_b) +{ + BMLoop *l_iter, *l_first; + + 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_b); + do { + l_iter->f = f_a; + } while ((l_iter = l_iter->next) != l_first); + + SWAP(BMFace, (*f_a), (*f_b)); + bm->elem_index_dirty |= BM_FACE; +} diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index a18c2ebd32c..9e33509c2c8 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -87,4 +87,6 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e); BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep); BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep); +void bmesh_face_swap_data(BMesh *bm, BMFace *f_a, BMFace *f_b); + #endif /* __BMESH_CORE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 4555de7b13d..91b9774634d 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -54,6 +54,32 @@ const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = { }; /** + * Utility function. + */ +int BM_iter_mesh_count(BMesh *bm, const char itype) +{ + 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; + } + + return count; +} + +/** * \note Use #BM_vert_at_index / #BM_edge_at_index / #BM_face_at_index for mesh arrays. */ void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) @@ -304,36 +330,66 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const * VERT OF MESH CALLBACKS */ +/* see bug [#36923] for why we need this, + * allow adding but not removing, this isnt _totally_ safe since + * you could add/remove within the same loop, but catches common cases + */ +#ifdef DEBUG +# define USE_IMMUTABLE_ASSERT +#endif + void bmiter__vert_of_mesh_begin(struct BMIter__vert_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + ((BMIter *)iter)->count = iter->bm->totvert; +#endif BLI_mempool_iternew(iter->bm->vpool, &iter->pooliter); } void *bmiter__vert_of_mesh_step(struct BMIter__vert_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + BLI_assert(((BMIter *)iter)->count <= iter->bm->totvert); +#endif return BLI_mempool_iterstep(&iter->pooliter); } void bmiter__edge_of_mesh_begin(struct BMIter__edge_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + ((BMIter *)iter)->count = iter->bm->totedge; +#endif BLI_mempool_iternew(iter->bm->epool, &iter->pooliter); } void *bmiter__edge_of_mesh_step(struct BMIter__edge_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + BLI_assert(((BMIter *)iter)->count <= iter->bm->totedge); +#endif return BLI_mempool_iterstep(&iter->pooliter); } void bmiter__face_of_mesh_begin(struct BMIter__face_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + ((BMIter *)iter)->count = iter->bm->totface; +#endif BLI_mempool_iternew(iter->bm->fpool, &iter->pooliter); } void *bmiter__face_of_mesh_step(struct BMIter__face_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + BLI_assert(((BMIter *)iter)->count <= iter->bm->totface); +#endif return BLI_mempool_iterstep(&iter->pooliter); } +#ifdef USE_IMMUTABLE_ASSERT +# undef USE_IMMUTABLE_ASSERT +#endif + /* * EDGE OF VERT CALLBACKS */ diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index bb25d3fabd1..fdf0f27f05f 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -89,6 +89,20 @@ extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX]; #define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar) \ for (ele = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; ele; 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 (ele = BM_iter_new(iter, bm, itype, NULL); \ + ele ? ((void)((iter)->count = BM_iter_mesh_count(bm, itype)), \ + (void)(ele_next = BM_iter_step(iter)), 1) : 0; \ + ele = ele_next) +#else +# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \ + for (ele = BM_iter_new(iter, bm, itype, NULL); ele ? ((ele_next = BM_iter_step(iter)), 1) : 0; ele = ele_next) +#endif + + #define BM_ITER_ELEM(ele, iter, data, itype) \ for (ele = BM_iter_new(iter, NULL, itype, data); ele; ele = BM_iter_step(iter)) @@ -182,6 +196,7 @@ typedef struct BMIter { char itype; } BMIter; +int BM_iter_mesh_count(BMesh *bm, const char itype); 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, diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 284ff3e759c..611ee4d03b8 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -1639,9 +1639,9 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, // BMOpDefine *def; char *opname, *ofmt, *fmt; char slot_name[64] = {0}; - int i /*, n = strlen(fmt) */, stop /*, slot_code = -1 */, type, state; + int i, type; + bool noslot, state; char htype; - int noslot = 0; /* basic useful info to help find where bmop formatting strings fail */ @@ -1662,7 +1662,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, i = strcspn(fmt, " "); opname = fmt; - if (!opname[i]) noslot = 1; + noslot = (opname[i] == '\0'); opname[i] = '\0'; fmt += i + (noslot ? 0 : 1); @@ -1679,7 +1679,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, // def = bmo_opdefines[i]; i = 0; - state = 1; /* 0: not inside slot_code name, 1: inside slot_code name */ + state = true; /* false: not inside slot_code name, true: inside slot_code name */ while (*fmt) { if (state) { @@ -1705,7 +1705,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, BLI_strncpy(slot_name, fmt, sizeof(slot_name)); - state = 0; + state = false; fmt += i; } else { @@ -1726,13 +1726,13 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, 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 = 1; + state = true; break; } case 'v': { BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *)); - state = 1; + state = true; break; } case 'e': /* single vert/edge/face */ @@ -1742,7 +1742,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, BMO_slot_buffer_from_single(op, slot, ele); - state = 1; + state = true; break; } case 's': @@ -1761,20 +1761,20 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, BMO_slot_copy(op_other, slots_out, slot_name_other, op, slots_in, slot_name); } - state = 1; + state = true; break; } case 'i': BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int)); - state = 1; + state = true; break; case 'b': BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int)); - state = 1; + state = true; break; case 'p': BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *)); - state = 1; + state = true; break; case 'f': case 'F': @@ -1787,15 +1787,16 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double)); } else { + bool stop = false; + htype = 0; - stop = 0; while (1) { switch (NEXT_CHAR(fmt)) { case 'f': htype |= BM_FACE; break; case 'e': htype |= BM_EDGE; break; case 'v': htype |= BM_VERT; break; default: - stop = 1; + stop = true; break; } if (stop) { @@ -1822,7 +1823,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, } } - state = 1; + state = true; break; default: fprintf(stderr, diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 2492dce05c7..e4c1180d433 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -30,10 +30,9 @@ #include "DNA_listBase.h" -#include "MEM_guardedalloc.h" - #include "BLI_alloca.h" #include "BLI_math.h" +#include "BLI_memarena.h" #include "BLI_scanfill.h" #include "BLI_listbase.h" @@ -801,195 +800,6 @@ bool BM_face_point_inside_test(BMFace *f, const float co[3]) return crosses % 2 != 0; } -static bool bm_face_goodline(float const (*projectverts)[2], BMFace *f, int v1i, int v2i, int v3i) -{ - BMLoop *l_iter; - BMLoop *l_first; - - float pv1[2]; - const float *v1 = projectverts[v1i]; - const float *v2 = projectverts[v2i]; - const float *v3 = projectverts[v3i]; - int i; - - /* v3 must be on the left side of [v1, v2] line, else we know [v1, v3] is outside of f! */ - if (testedgesidef(v1, v2, v3)) { - return false; - } - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - i = BM_elem_index_get(l_iter->v); - copy_v2_v2(pv1, projectverts[i]); - - if (ELEM3(i, v1i, v2i, v3i)) { -#if 0 - printf("%d in (%d, %d, %d) tri (from indices!), continuing\n", i, v1i, v2i, v3i); -#endif - continue; - } - - if (isect_point_tri_v2(pv1, v1, v2, v3) || - isect_point_tri_v2(pv1, v3, v2, v1)) - { -#if 0 - if (isect_point_tri_v2(pv1, v1, v2, v3)) - printf("%d in (%d, %d, %d)\n", v3i, i, v1i, v2i); - else - printf("%d in (%d, %d, %d)\n", v1i, i, v3i, v2i); -#endif - return false; - } - } while ((l_iter = l_iter->next) != l_first); - return true; -} - -/** - * \brief Find Ear - * - * Used by tessellator to find the next triangle to 'clip off' of a polygon while tessellating. - * - * \param f The face to search. - * \param projectverts an array of face vert coords. - * \param use_beauty Currently only applies to quads, can be extended later on. - * \param abscoss Must be allocated by caller, and at least f->len length - * (allow to avoid allocating a new one for each tri!). - */ -static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use_beauty, float *abscoss) -{ - BMLoop *bestear = NULL; - - BMLoop *l_iter; - BMLoop *l_first; - - const float cos_threshold = 0.9f; - const float bias = 1.0f + 1e-6f; - - BLI_assert(BM_face_is_normal_valid(f)); - /* just triangulate degenerate faces */ - if (UNLIKELY(is_zero_v3(f->no))) { - return BM_FACE_FIRST_LOOP(f); - } - - if (f->len == 4) { - BMLoop *larr[4]; - int i = 0, i4; - float cos1, cos2; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - larr[i] = l_iter; - i++; - } while ((l_iter = l_iter->next) != l_first); - - /* pick 0/1 based on best length */ - /* XXX Can't only rely on such test, also must check we do not get (too much) degenerated triangles!!! */ - i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) > - len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty); - i4 = (i + 3) % 4; - /* Check produced tris aren't too flat/narrow... - * Probably not the best test, but is quite efficient and should at least avoid null-area faces! */ - cos1 = fabsf(cos_v3v3v3(larr[i4]->v->co, larr[i]->v->co, larr[i + 1]->v->co)); - cos2 = fabsf(cos_v3v3v3(larr[i4]->v->co, larr[i + 2]->v->co, larr[i + 1]->v->co)); -#if 0 - printf("%d, (%f, %f), (%f, %f)\n", i, cos1, cos2, - fabsf(cos_v3v3v3(larr[i]->v->co, larr[i4]->v->co, larr[i + 2]->v->co)), - fabsf(cos_v3v3v3(larr[i]->v->co, larr[i + 1]->v->co, larr[i + 2]->v->co))); -#endif - if (cos1 < cos2) - cos1 = cos2; - - if (cos1 > cos_threshold) { - if (cos1 > fabsf(cos_v3v3v3(larr[i]->v->co, larr[i4]->v->co, larr[i + 2]->v->co)) && - cos1 > fabsf(cos_v3v3v3(larr[i]->v->co, larr[i + 1]->v->co, larr[i + 2]->v->co))) - { - i = !i; - } - } - /* Last check we do not get overlapping triangles - * (as much as possible, there are some cases with no good solution!) */ - i4 = (i + 3) % 4; - if (!bm_face_goodline((float const (*)[2])projectverts, f, - BM_elem_index_get(larr[i4]->v), - BM_elem_index_get(larr[i]->v), - BM_elem_index_get(larr[i + 1]->v))) - { - i = !i; - } -/* printf("%d\n", i);*/ - bestear = larr[i]; - - } - else { - /* float angle, bestangle = 180.0f; */ - const int len = f->len; - float cos, cos_best = 1.0f; - int i, j; - - /* Compute cos of all corners! */ - i = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const BMVert *v1 = l_iter->prev->v; - const BMVert *v2 = l_iter->v; - const BMVert *v3 = l_iter->next->v; - - abscoss[i] = fabsf(cos_v3v3v3(v1->co, v2->co, v3->co)); -/* printf("tcoss: %f\n", *tcoss);*/ - i++; - } while ((l_iter = l_iter->next) != l_first); - - i = 0; - l_iter = l_first; - do { - const BMVert *v1 = l_iter->prev->v; - const BMVert *v2 = l_iter->v; - const BMVert *v3 = l_iter->next->v; - - /* Compute highest cos (i.e. narrowest angle) of this tri. */ - cos = max_fff(abscoss[i], - fabsf(cos_v3v3v3(v2->co, v3->co, v1->co)), - fabsf(cos_v3v3v3(v3->co, v1->co, v2->co))); - - /* Compare to prev best (i.e. lowest) cos. */ - if (cos < cos_best) { - if (bm_face_goodline((float const (*)[2])projectverts, f, - BM_elem_index_get(v1), - BM_elem_index_get(v2), - BM_elem_index_get(v3))) - { - /* We must check this tri would not leave a (too much) degenerated remaining face! */ - /* For now just assume if the average of cos of all - * "remaining face"'s corners is below a given threshold, it's OK. */ - float cos_mean = fabsf(cos_v3v3v3(v1->co, v3->co, l_iter->next->next->v->co)); - const int i_limit = (i - 1 + len) % len; - cos_mean += fabsf(cos_v3v3v3(l_iter->prev->prev->v->co, v1->co, v3->co)); - j = (i + 2) % len; - do { - cos_mean += abscoss[j]; - } while ((j = (j + 1) % len) != i_limit); - cos_mean /= len - 1; - - /* We need a best ear in any case... */ - if (cos_mean < cos_threshold || (!bestear && cos_mean < 1.0f)) { - /* OKI, keep this ear (corner...) as a potential best one! */ - bestear = l_iter; - cos_best = cos; - } -#if 0 - else - printf("Had a nice tri (higest cos of %f, current cos_best is %f), " - "but average cos of all \"remaining face\"'s corners is too high (%f)!\n", - cos, cos_best, cos_mean); -#endif - } - } - i++; - } while ((l_iter = l_iter->next) != l_first); - } - - return bestear; -} - /** * \brief BMESH TRIANGULATE FACE * @@ -1003,63 +813,126 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use * * \note use_tag tags new flags and edges. */ +#define SF_EDGE_IS_BOUNDARY 0xff void BM_face_triangulate(BMesh *bm, BMFace *f, BMFace **r_faces_new, - const bool use_beauty, const bool use_tag) + MemArena *sf_arena, + const bool UNUSED(use_beauty), const bool use_tag) { - const float f_len_orig = f->len; - int i, nf_i = 0; - BMLoop *l_new; - BMLoop *l_iter; - BMLoop *l_first; - /* BM_face_triangulate: temp absolute cosines of face corners */ - float (*projectverts)[2] = BLI_array_alloca(projectverts, f_len_orig); - float *abscoss = BLI_array_alloca(abscoss, f_len_orig); - float mat[3][3]; + int nf_i = 0; + BMLoop *l_iter, *l_first, *l_new; + BMFace *f_new; BLI_assert(BM_face_is_normal_valid(f)); - axis_dominant_v3_to_m3(mat, f->no); - /* copy vertex coordinates to vertspace area */ - i = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - mul_v2_m3v3(projectverts[i], mat, l_iter->v->co); - BM_elem_index_set(l_iter->v, i++); /* set dirty! */ - } while ((l_iter = l_iter->next) != l_first); + if (f->len == 4) { + l_first = BM_FACE_FIRST_LOOP(f); - bm->elem_index_dirty |= BM_VERT; /* see above */ + f_new = BM_face_split(bm, f, l_first->v, l_first->next->next->v, &l_new, NULL, false); + copy_v3_v3(f_new->no, f->no); - while (f->len > 3) { - l_iter = poly_find_ear(f, projectverts, use_beauty, abscoss); + if (use_tag) { + BM_elem_flag_enable(l_new->e, BM_ELEM_TAG); + BM_elem_flag_enable(f_new, BM_ELEM_TAG); + } - /* force triangulation - if we can't find an ear the face is degenerate */ - if (l_iter == NULL) { - l_iter = BM_FACE_FIRST_LOOP(f); + if (r_faces_new) { + r_faces_new[nf_i++] = f_new; } + } + else if (f->len > 4) { + /* scanfill */ + ScanFillContext sf_ctx; + ScanFillVert *sf_vert, *sf_vert_prev = NULL; + ScanFillEdge *sf_edge; + ScanFillFace *sf_tri; + int totfilltri; -/* printf("Subdividing face...\n");*/ - f = BM_face_split(bm, l_iter->f, l_iter->prev->v, l_iter->next->v, &l_new, NULL, true); + /* populate scanfill */ + BLI_scanfill_begin_arena(&sf_ctx, sf_arena); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); - if (UNLIKELY(!f)) { - fprintf(stderr, "%s: triangulator failed to split face! (bmesh internal error)\n", __func__); - break; - } + /* step once before entering the loop */ + sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co); + sf_vert->tmp.p = l_iter; + sf_vert_prev = sf_vert; + l_iter = l_iter->next; + + do { + sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co); + sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_prev, sf_vert); + sf_edge->tmp.c = SF_EDGE_IS_BOUNDARY; + + sf_vert->tmp.p = l_iter; + sf_vert_prev = sf_vert; + } while ((l_iter = l_iter->next) != l_first); + + sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_prev, sf_ctx.fillvertbase.first); + sf_edge->tmp.c = SF_EDGE_IS_BOUNDARY; + + /* calculate filled triangles */ + totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, f->no); + BLI_assert(totfilltri <= f->len - 2); - copy_v3_v3(f->no, l_iter->f->no); + + /* loop over calculated triangles and create new geometry */ + for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { + /* the order is reverse, otherwise the normal is flipped */ + BMLoop *l_tri[3] = { + sf_tri->v3->tmp.p, + sf_tri->v2->tmp.p, + sf_tri->v1->tmp.p}; + + 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, false, true); + l_new = BM_FACE_FIRST_LOOP(f_new); + + BLI_assert(v_tri[0] == l_new->v); + + /* 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 (sf_tri->next) { + if (use_tag) { + BM_elem_flag_enable(f_new, BM_ELEM_TAG); + } + if (r_faces_new && sf_tri->next) { + r_faces_new[nf_i++] = f_new; + } + } + } if (use_tag) { - BM_elem_flag_enable(l_new->e, BM_ELEM_TAG); - BM_elem_flag_enable(f, BM_ELEM_TAG); + ScanFillEdge *sf_edge; + for (sf_edge = sf_ctx.filledgebase.first; sf_edge; sf_edge = sf_edge->next) { + if (sf_edge->tmp.c != SF_EDGE_IS_BOUNDARY) { + BMLoop *l1 = sf_edge->v1->tmp.p; + BMLoop *l2 = sf_edge->v2->tmp.p; + + BMEdge *e = BM_edge_exists(l1->v, l2->v); + BM_elem_flag_enable(e, BM_ELEM_TAG); + } + } } - if (r_faces_new) { - r_faces_new[nf_i++] = f; + if (sf_ctx.fillfacebase.first) { + /* 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(bm, f, f_new); + BM_face_kill(bm, f_new); } - } - BLI_assert(f->len == 3); + /* garbage collection */ + BLI_scanfill_end_arena(&sf_ctx, sf_arena); + } } /** diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index 14fe1e76360..b7117621273 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -53,6 +53,7 @@ void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL(); bool BM_face_point_inside_test(BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BM_face_triangulate(BMesh *bm, BMFace *f, BMFace **newfaces, + struct MemArena *sf_arena, const bool use_beauty, const bool use_tag) ATTR_NONNULL(1, 2); void BM_face_legal_splits(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL(); diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index a68d9ccd2bc..238b7b4aaaa 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -26,6 +26,8 @@ * BMesh Walker Code. */ +#include <string.h> + #include "BLI_utildefines.h" #include "BKE_customdata.h" @@ -34,6 +36,12 @@ #include "intern/bmesh_private.h" #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 + 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)) { @@ -140,14 +148,16 @@ static void *bmw_ShellWalker_yield(BMWalker *walker) static void *bmw_ShellWalker_step(BMWalker *walker) { - BMwShellWalker *swalk = BMW_current_state(walker); + BMwShellWalker *swalk, owalk; BMEdge *e, *e2; BMVert *v; BMIter iter; int i; + BMW_state_remove_r(walker, &owalk); + swalk = &owalk; + e = swalk->curedge; - BMW_state_remove(walker); for (i = 0; i < 2; i++) { v = i ? e->v2 : e->v1; @@ -240,14 +250,15 @@ static void *bmw_ConnectedVertexWalker_yield(BMWalker *walker) static void *bmw_ConnectedVertexWalker_step(BMWalker *walker) { - BMwConnectedVertexWalker *vwalk = BMW_current_state(walker); + BMwConnectedVertexWalker *vwalk, owalk; BMVert *v, *v2; BMEdge *e; BMIter iter; - v = vwalk->curvert; + BMW_state_remove_r(walker, &owalk); + vwalk = &owalk; - BMW_state_remove(walker); + v = vwalk->curvert; BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { v2 = BM_edge_other_vert(e, v); @@ -289,14 +300,19 @@ static void *bmw_IslandboundWalker_yield(BMWalker *walker) static void *bmw_IslandboundWalker_step(BMWalker *walker) { - BMwIslandboundWalker *iwalk = BMW_current_state(walker), owalk; + BMwIslandboundWalker *iwalk, owalk; BMVert *v; - BMEdge *e = iwalk->curloop->e; + BMEdge *e; BMFace *f; - BMLoop *l = iwalk->curloop; + BMLoop *l; /* int found = 0; */ - owalk = *iwalk; + 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); @@ -307,7 +323,7 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker) return NULL; } - /* pop off current stat */ + /* pop off current state */ BMW_state_remove(walker); f = l->f; @@ -381,13 +397,13 @@ static void *bmw_IslandWalker_yield(BMWalker *walker) static void *bmw_IslandWalker_step(BMWalker *walker) { - BMwIslandWalker *iwalk = BMW_current_state(walker); - /* BMwIslandWalker *owalk = iwalk; */ /* UNUSED */ + BMwIslandWalker *iwalk, owalk; BMIter iter, liter; - BMFace *f, *curf = iwalk->cur; + BMFace *f; BMLoop *l; - BMW_state_remove(walker); + BMW_state_remove_r(walker, &owalk); + iwalk = &owalk; l = BM_iter_new(&liter, walker->bm, BM_LOOPS_OF_FACE, iwalk->cur); for ( ; l; l = BM_iter_step(&liter)) { @@ -419,7 +435,7 @@ static void *bmw_IslandWalker_step(BMWalker *walker) } } - return curf; + return owalk.cur; } @@ -507,15 +523,16 @@ static void *bmw_LoopWalker_yield(BMWalker *walker) static void *bmw_LoopWalker_step(BMWalker *walker) { - BMwLoopWalker *lwalk = BMW_current_state(walker), owalk; - BMEdge *e = lwalk->cur, *nexte = NULL; + BMwLoopWalker *lwalk, owalk; + BMEdge *e, *nexte = NULL; BMLoop *l; BMVert *v; int i = 0; - owalk = *lwalk; - BMW_state_remove(walker); + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; + e = lwalk->cur; l = e->l; if (owalk.f_hub) { /* NGON EDGE */ @@ -770,13 +787,15 @@ static void *bmw_FaceLoopWalker_yield(BMWalker *walker) static void *bmw_FaceLoopWalker_step(BMWalker *walker) { - BMwFaceLoopWalker *lwalk = BMW_current_state(walker); - BMFace *f = lwalk->l->f; - BMLoop *l = lwalk->l, *origl = lwalk->l; + BMwFaceLoopWalker *lwalk, owalk; + BMFace *f; + BMLoop *l; - BMW_state_remove(walker); + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; - l = l->radial_next; + f = lwalk->l->f; + l = lwalk->l->radial_next; if (lwalk->no_calc) { return f; @@ -797,7 +816,7 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker) if (l->f->len != 4) { lwalk->no_calc = true; - lwalk->l = origl; + lwalk->l = owalk.l; } else { lwalk->no_calc = false; @@ -878,19 +897,21 @@ static void *bmw_EdgeringWalker_yield(BMWalker *walker) static void *bmw_EdgeringWalker_step(BMWalker *walker) { - BMwEdgeringWalker *lwalk = BMW_current_state(walker); - BMEdge *e, *wireedge = lwalk->wireedge; - BMLoop *l = lwalk->l, *origl = lwalk->l; + BMwEdgeringWalker *lwalk, owalk; + BMEdge *e; + BMLoop *l; #ifdef BMW_EDGERING_NGON int i, len; #endif #define EDGE_CHECK(e) (bmw_mask_check_edge(walker, e) && (BM_edge_is_boundary(e) || BM_edge_is_manifold(e))) - BMW_state_remove(walker); + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; + l = lwalk->l; if (!l) - return wireedge; + return lwalk->wireedge; e = l->e; if (!EDGE_CHECK(e)) { @@ -913,7 +934,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker) if ((len <= 0) || (len % 2 != 0) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) { - l = origl; + l = owalk.l; i = len; while (i > 0) { l = l->next; @@ -930,7 +951,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker) l = l->next->next; if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) { - l = origl->next->next; + l = owalk.l->next->next; } /* only walk to manifold edge */ if ((l->f->len == 4) && EDGE_CHECK(l->e) && @@ -975,17 +996,18 @@ static void *bmw_UVEdgeWalker_yield(BMWalker *walker) static void *bmw_UVEdgeWalker_step(BMWalker *walker) { - BMwUVEdgeWalker *lwalk = BMW_current_state(walker); + const int type = walker->bm->ldata.layers[walker->layer].type; + BMwUVEdgeWalker *lwalk, owalk; BMLoop *l, *l2, *l3, *nl, *cl; BMIter liter; void *d1, *d2; - int i, j, rlen, type; + int i, j, rlen; + + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; l = lwalk->l; nl = l->next; - type = walker->bm->ldata.layers[walker->layer].type; - - BMW_state_remove(walker); if (!bmw_mask_check_edge(walker, l->e)) { return l; diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c index 9dfbf951fc0..10d15d93995 100644 --- a/source/blender/bmesh/operators/bmo_bridge.c +++ b/source/blender/bmesh/operators/bmo_bridge.c @@ -26,8 +26,6 @@ * Connect verts across faces (splits faces) and bridge tool. */ -#include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_listbase.h" diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index b3a42ba533e..d0f64eb2892 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -26,8 +26,6 @@ * Connect verts across faces (splits faces). */ -#include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_alloca.h" diff --git a/source/blender/bmesh/operators/bmo_connect_nonplanar.c b/source/blender/bmesh/operators/bmo_connect_nonplanar.c index 61085596acc..bd7a625406c 100644 --- a/source/blender/bmesh/operators/bmo_connect_nonplanar.c +++ b/source/blender/bmesh/operators/bmo_connect_nonplanar.c @@ -26,8 +26,6 @@ * Connect verts non-planer faces iteratively (splits faces). */ -#include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_alloca.h" diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index d3c7a6864c3..cf36e88ea98 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -37,14 +37,21 @@ #include "intern/bmesh_operators_private.h" +/* ***_ISGC: mark for garbage-collection */ + #define FACE_MARK 1 #define FACE_ORIG 2 #define FACE_NEW 4 + #define EDGE_MARK 1 #define EDGE_TAG 2 +#define EDGE_ISGC 8 #define VERT_MARK 1 #define VERT_TAG 2 +#define VERT_ISGC 8 + + static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f) { @@ -232,14 +239,12 @@ cleanup: void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) { - /* might want to make this an option or mode - campbell */ - /* BMOperator fop; */ BMFace *act_face = bm->act_face; BMOIter eiter; - BMEdge *e; - BMIter viter; - BMVert *v; + BMIter iter; + BMEdge *e, *e_next; + BMVert *v, *v_next; const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split"); @@ -247,10 +252,10 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) if (use_face_split) { BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_TAG); - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - BMIter iter; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BMIter itersub; int untag_count = 0; - BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) { if (!BMO_elem_flag_test(bm, e, EDGE_TAG)) { untag_count++; } @@ -266,22 +271,34 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) } if (use_verts) { - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { BMO_elem_flag_set(bm, v, VERT_MARK, (BM_vert_edge_count(v) != 2)); } } + /* tag all verts/edges connected to faces */ BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) { - BMFace *fa, *fb; + BMFace *f_pair[2]; + if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) { + unsigned int j; + for (j = 0; j < 2; j++) { + BMLoop *l_first, *l_iter; + l_iter = l_first = BM_FACE_FIRST_LOOP(f_pair[j]); + do { + BMO_elem_flag_enable(bm, l_iter->v, VERT_ISGC); + BMO_elem_flag_enable(bm, l_iter->e, EDGE_ISGC); + } while ((l_iter = l_iter->next) != l_first); + } + } + } + BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) { + BMFace *fa, *fb; if (BM_edge_face_pair(e, &fa, &fb)) { BMFace *f_new; /* join faces */ - - /* BMESH_TODO - check on delaying edge removal since we may end up removing more than - * one edge, and later reference a removed edge */ - f_new = BM_faces_join_pair(bm, fa, fb, e, true); + f_new = BM_faces_join_pair(bm, fa, fb, e, false); if (f_new) { /* maintain active face */ @@ -292,8 +309,23 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) } } + /* Cleanup geometry (#BM_faces_join_pair, but it removes geometry we're looping on) + * so do this in a separate pass instead. */ + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { + if ((e->l == NULL) && BMO_elem_flag_test(bm, e, EDGE_ISGC)) { + BM_edge_kill(bm, e); + } + } + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { + if ((v->e == NULL) && BMO_elem_flag_test(bm, v, VERT_ISGC)) { + BM_vert_kill(bm, v); + } + } + /* done with cleanup */ + + if (use_verts) { - BM_ITER_MESH (v, &viter, 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, VERT_MARK)) { if (BM_vert_edge_count(v) == 2) { BM_vert_collapse_edge(bm, v->e, v, true); @@ -349,7 +381,7 @@ static bool test_extra_verts(BMesh *bm, BMVert *v) void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) { BMIter iter, fiter; - BMVert *v; + BMVert *v, *v_next; BMFace *f; const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split"); @@ -361,7 +393,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) bm_face_split(bm, VERT_MARK); } - 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, VERT_MARK)) { /* check if it's a two-valence ver */ if (BM_vert_edge_count(v) == 2) { @@ -409,7 +441,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) } /* clean up any remainin */ - 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, VERT_MARK)) { if (!BM_vert_dissolve(bm, v)) { BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, NULL); diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index bd2485b92fb..a5c34f7623b 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -26,8 +26,6 @@ * Duplicate, Split, Split operators. */ -#include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "BLI_alloca.h" diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c index c58a11f21ec..de41bc7937d 100644 --- a/source/blender/bmesh/operators/bmo_edgenet.c +++ b/source/blender/bmesh/operators/bmo_edgenet.c @@ -28,13 +28,8 @@ #include "MEM_guardedalloc.h" -#include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_array.h" -#include "BLI_alloca.h" -#include "BLI_smallhash.h" -#include "BLI_rand.h" -#include "BLI_heap.h" #include "bmesh.h" #include "bmesh_tools.h" @@ -44,10 +39,7 @@ #define EDGE_MARK 1 #define EDGE_VIS 2 -#define FACE_NEW 1 - #define ELE_NEW 1 -#define ELE_ORIG 4 void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) { diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c index f53b4536e44..fa77e6b509c 100644 --- a/source/blender/bmesh/operators/bmo_fill_attribute.c +++ b/source/blender/bmesh/operators/bmo_fill_attribute.c @@ -27,8 +27,6 @@ * Fill in geometry with the attributes of their adjacent data. */ -#include "MEM_guardedalloc.h" - #include "BLI_utildefines.h" #include "BLI_linklist_stack.h" diff --git a/source/blender/bmesh/operators/bmo_fill_holes.c b/source/blender/bmesh/operators/bmo_fill_holes.c index 8160d28d7a7..eadfbdb1aa8 100644 --- a/source/blender/bmesh/operators/bmo_fill_holes.c +++ b/source/blender/bmesh/operators/bmo_fill_holes.c @@ -26,8 +26,6 @@ * Fill boundary edge loop(s) with faces. */ -#include "MEM_guardedalloc.h" - #include "BLI_utildefines.h" #include "bmesh.h" diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 20cd828af1e..e20556a830d 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -31,7 +31,6 @@ #include "MEM_guardedalloc.h" #include "BLI_math.h" -#include "BLI_array.h" #include "BLI_alloca.h" #include "BLI_memarena.h" #include "BKE_customdata.h" diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 6d4f257909c..6562f26062f 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -203,7 +203,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) BMIter iter; BMOIter siter; BMFace *f; - BMEdge *e; + BMEdge *e, *e_next; /* data: edge-to-join, sort_value: error weight */ struct SortPointerByFloat *jedges; unsigned i, totedge; @@ -291,7 +291,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) MEM_freeN(jedges); /* join best weighted */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { BMFace *f_new; BMFace *f_a, *f_b; @@ -308,7 +308,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) } /* join 2-tri islands */ - 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, EDGE_MARK)) { BMLoop *l_a, *l_b; BMFace *f_a, *f_b; @@ -326,7 +326,11 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) (BMO_elem_flag_test(bm, l_a->next->e, EDGE_MARK) == false) && (BMO_elem_flag_test(bm, l_a->prev->e, EDGE_MARK) == false) && (BMO_elem_flag_test(bm, l_b->next->e, EDGE_MARK) == false) && - (BMO_elem_flag_test(bm, l_b->prev->e, EDGE_MARK) == false)) + (BMO_elem_flag_test(bm, l_b->prev->e, EDGE_MARK) == false) && + /* check for faces that use same verts, this is supported but raises an error + * and cancels the operation when performed from editmode, since this is only + * two triangles we only need to compare a single vertex */ + (LIKELY(l_a->prev->v != l_b->prev->v))) { BMFace *f_new; f_new = BM_faces_join_pair(bm, f_a, f_b, e, true); diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index 45653f3411f..6a540928d43 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -36,7 +36,7 @@ /* ************************ primitives ******************* */ -static float icovert[12][3] = { +static const float icovert[12][3] = { {0.0f, 0.0f, -200.0f}, {144.72f, -105.144f, -89.443f}, {-55.277f, -170.128, -89.443f}, @@ -51,7 +51,7 @@ static float icovert[12][3] = { {0.0f, 0.0f, 200.0f} }; -static short icoface[20][3] = { +static const short icoface[20][3] = { {0, 1, 2}, {1, 0, 5}, {0, 2, 3}, @@ -78,10 +78,10 @@ static short icoface[20][3] = { * this hack is only used so that scons & mingw + split-sources hack works * ------------------------------- start copied code */ /* these are not the monkeys you are looking for */ -static int monkeyo = 4; -static int monkeynv = 271; -static int monkeynf = 250; -static signed char monkeyv[271][3] = { +static const int monkeyo = 4; +static const int monkeynv = 271; +static const int monkeynf = 250; +static const signed char monkeyv[271][3] = { {-71, 21, 98}, {-63, 12, 88}, {-57, 7, 74}, {-82, -3, 79}, {-82, 4, 92}, {-82, 17, 100}, {-92, 21, 102}, {-101, 12, 95}, {-107, 7, 83}, {-117, 31, 84}, {-109, 31, 95}, {-96, 31, 102}, {-92, 42, 102}, diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 5ab909ffb0c..cc5a635092a 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -354,7 +354,7 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) BMEdge *e, **edges = NULL; BLI_array_declare(edges); float min[3], max[3], center[3]; - int i, tot; + unsigned int i, tot; BMOpSlot *slot_targetmap; BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); @@ -369,6 +369,8 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) BMW_NIL_LAY); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BMVert *v_tar; + if (!BMO_elem_flag_test(bm, e, EDGE_MARK)) continue; @@ -381,19 +383,29 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) minmax_v3v3_v3(min, max, e->v1->co); minmax_v3v3_v3(min, max, e->v2->co); + + /* prevent adding to slot_targetmap multiple times */ + BM_elem_flag_disable(e->v1, BM_ELEM_TAG); + BM_elem_flag_disable(e->v2, BM_ELEM_TAG); } mid_v3_v3v3(center, min, max); /* snap edges to a point. for initial testing purposes anyway */ + v_tar = edges[0]->v1; + for (i = 0; i < tot; i++) { - copy_v3_v3(edges[i]->v1->co, center); - copy_v3_v3(edges[i]->v2->co, center); - - if (edges[i]->v1 != edges[0]->v1) - BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v1, edges[0]->v1); - if (edges[i]->v2 != edges[0]->v1) - BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v2, edges[0]->v1); + unsigned int j; + + for (j = 0; j < 2; j++) { + BMVert *v_src = *((&edges[i]->v1) + j); + + copy_v3_v3(v_src->co, center); + if ((v_src != v_tar) && !BM_elem_flag_test(v_src, BM_ELEM_TAG)) { + BM_elem_flag_enable(v_src, BM_ELEM_TAG); + BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_src, v_tar); + } + } } } diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c index 4b538dccb4e..5c1b4287c2f 100644 --- a/source/blender/bmesh/operators/bmo_symmetrize.c +++ b/source/blender/bmesh/operators/bmo_symmetrize.c @@ -26,9 +26,6 @@ * Makes the mesh symmetrical by splitting along an axis and duplicating the geometry. */ - -#include "MEM_guardedalloc.h" - #include "BLI_utildefines.h" #include "BLI_math.h" @@ -59,7 +56,7 @@ void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) copy_v3_fl(plane_no, 0.0f); copy_v3_fl(scale, 1.0f); - plane_no[axis] = direction > 2 ? 1.0f : -1.0f; + plane_no[axis] = direction > 2 ? -1.0f : 1.0f; scale[axis] *= -1.0f; /* Cut in half */ diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c index 590b5ea97c4..ca45289520b 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -26,7 +26,6 @@ * Triangulate faces, also defines triangle fill. */ -#include "MEM_guardedalloc.h" #include "DNA_listBase.h" #include "BLI_math.h" diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index e23358bf4ff..c89fee71cbc 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -32,7 +32,6 @@ #include "DNA_meshdata_types.h" #include "BLI_math.h" -#include "BLI_heap.h" #include "BLI_alloca.h" #include "BKE_customdata.h" diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 1463b3155c0..bb3fe129e0b 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -1207,8 +1207,12 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) f = boundvert_rep_face(v); f2 = boundvert_rep_face(v->next); if (!v->any_seam) { - for (ring = 1; ring < ns2; ring++) - bev_merge_uvs(bm, mesh_vert(vm, i, ring, ns2)->v); + for (ring = 1; ring < ns2; ring++) { + BMVert *v_uv = mesh_vert(vm, i, ring, ns2)->v; + if (v_uv) { + bev_merge_uvs(bm, v_uv); + } + } } } while ((v = v->next) != vm->boundstart); if (!bv->any_seam) @@ -2371,7 +2375,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, const struct MDeformVert *dvert, const int vertex_group) { BMIter iter; - BMVert *v; + BMVert *v, *v_next; BMEdge *e; BevelParams bp = {NULL}; @@ -2385,7 +2389,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, if (bp.offset > 0) { /* primary alloc */ bp.vert_hash = BLI_ghash_ptr_new(__func__); - bp.mem_arena = BLI_memarena_new((1 << 16), __func__); + bp.mem_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), __func__); BLI_memarena_use_calloc(bp.mem_arena); if (limit_offset) @@ -2414,7 +2418,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, } } - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { BLI_assert(find_bevvert(&bp, v) != NULL); BM_vert_kill(bm, v); diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c index 3baf8675a0d..9cfe17d6413 100644 --- a/source/blender/bmesh/tools/bmesh_bisect_plane.c +++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c @@ -39,7 +39,6 @@ #include "BLI_utildefines.h" #include "BLI_alloca.h" -#include "BLI_mempool.h" #include "BLI_linklist.h" #include "BLI_linklist_stack.h" #include "BLI_math.h" @@ -122,9 +121,6 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con l_first = BM_FACE_FIRST_LOOP(f); - (void)bm; - (void)plane; - /* add plane-aligned verts to the stack * and check we have verts from both sides in this face, * ... that the face doesn't only have boundry verts on the plane for eg. */ @@ -238,7 +234,7 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con face_verts_proj_2d[BM_VERT_LOOPINDEX(v_a)], face_verts_proj_2d[BM_VERT_LOOPINDEX(v_b)]); - if (isect_point_poly_v2(co_mid, (const float (*)[2])face_verts_proj_2d, f_len_orig)) { + if (isect_point_poly_v2(co_mid, (const float (*)[2])face_verts_proj_2d, f_len_orig, false)) { BMLoop *l_a, *l_b; bool found = false; unsigned int j; diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index bc9288f98f6..868caa49ec7 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -197,7 +197,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool } for (iter_step = 0; iter_step < iterations; iter_step++) { - BMVert *v; + BMVert *v, *v_next; bool iter_done; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -318,7 +318,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool /* now we tagged all verts -1 for removal, lets loop over and rebuild faces */ iter_done = false; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) { if (bm_vert_dissolve_fan(bm, v)) { iter_done = true; diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c index 2eacf62d68a..34ff493a026 100644 --- a/source/blender/bmesh/tools/bmesh_triangulate.c +++ b/source/blender/bmesh/tools/bmesh_triangulate.c @@ -31,6 +31,9 @@ #include "BLI_utildefines.h" #include "BLI_alloca.h" +#include "BLI_memarena.h" +#include "BLI_listbase.h" +#include "BLI_scanfill.h" #include "bmesh.h" @@ -39,14 +42,14 @@ /** * a version of #BM_face_triangulate that maps to #BMOpSlot */ -static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, const bool use_beauty, const bool use_tag, +static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, MemArena *sf_arena, const bool use_beauty, const bool use_tag, BMOperator *op, BMOpSlot *slot_facemap_out) { const int faces_array_tot = face->len - 3; BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot); BLI_assert(face->len > 3); - BM_face_triangulate(bm, face, faces_array, use_beauty, use_tag); + BM_face_triangulate(bm, face, faces_array, sf_arena, use_beauty, use_tag); if (faces_array) { int i; @@ -63,13 +66,16 @@ void BM_mesh_triangulate(BMesh *bm, const bool use_beauty, const bool tag_only, { BMIter iter; BMFace *face; + MemArena *sf_arena; + + sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__); if (slot_facemap_out) { /* same as below but call: bm_face_triangulate_mapping() */ BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) { if (face->len > 3) { if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) { - bm_face_triangulate_mapping(bm, face, use_beauty, tag_only, + bm_face_triangulate_mapping(bm, face, sf_arena, use_beauty, tag_only, op, slot_facemap_out); } } @@ -79,9 +85,11 @@ void BM_mesh_triangulate(BMesh *bm, const bool use_beauty, const bool tag_only, BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) { if (face->len > 3) { if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) { - BM_face_triangulate(bm, face, NULL, use_beauty, tag_only); + BM_face_triangulate(bm, face, NULL, sf_arena, use_beauty, tag_only); } } } } + + BLI_memarena_free(sf_arena); } |