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:
authorSergej Reich <sergej.reich@googlemail.com>2013-10-13 15:41:41 +0400
committerSergej Reich <sergej.reich@googlemail.com>2013-10-13 15:41:41 +0400
commit5d5176095e82b34499e15d74f1fb76d56f4d9508 (patch)
treedd8c61741160804873601f6b6350661132ac1b2f /source/blender/bmesh
parentbcbf976b48762c2f25df470c6d13a124bc868a66 (diff)
parent42ac7164e30dcca565253aa265201aad497e5360 (diff)
svn merge -r60422:60726 ^/trunk/blender
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c12
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c25
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c56
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h15
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c31
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c329
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c96
-rw-r--r--source/blender/bmesh/operators/bmo_bridge.c2
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c2
-rw-r--r--source/blender/bmesh/operators/bmo_connect_nonplanar.c2
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c68
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c2
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c8
-rw-r--r--source/blender/bmesh/operators/bmo_fill_attribute.c2
-rw-r--r--source/blender/bmesh/operators/bmo_fill_holes.c2
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c1
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c12
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c12
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c28
-rw-r--r--source/blender/bmesh/operators/bmo_symmetrize.c5
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c1
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c1
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c14
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.c6
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.c16
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);
}