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:
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2013-04-01 17:47:19 +0400
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2013-04-01 17:47:19 +0400
commit5524ed9ba2d60331abed47c9df0bc2fcf330b36b (patch)
treee8380010f140f022b77236af171d97083a294006 /source/blender/bmesh/operators
parent1360bb6fb0bf0c5c14235c47bf1399accbcecc6f (diff)
parent689f3aa174ff795044a4dab719edf60b7b1f5bd3 (diff)
Merged changes in the trunk up to revision 55700.
Conflicts resolved: source/blender/editors/mesh/mesh_intern.h
Diffstat (limited to 'source/blender/bmesh/operators')
-rw-r--r--source/blender/bmesh/operators/bmo_beautify.c347
-rw-r--r--source/blender/bmesh/operators/bmo_bevel.c2
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c2
-rw-r--r--source/blender/bmesh/operators/bmo_create.c194
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c2
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c13
-rw-r--r--source/blender/bmesh/operators/bmo_edgeloop_fill.c5
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c3
-rw-r--r--source/blender/bmesh/operators/bmo_extrude.c2
-rw-r--r--source/blender/bmesh/operators/bmo_hull.c2
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c5
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c5
-rw-r--r--source/blender/bmesh/operators/bmo_mirror.c2
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c2
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c28
-rw-r--r--source/blender/bmesh/operators/bmo_smooth_laplacian.c2
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c2
-rw-r--r--source/blender/bmesh/operators/bmo_symmetrize.c7
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c2
-rw-r--r--source/blender/bmesh/operators/bmo_unsubdivide.c3
-rw-r--r--source/blender/bmesh/operators/bmo_wireframe.c2
21 files changed, 370 insertions, 262 deletions
diff --git a/source/blender/bmesh/operators/bmo_beautify.c b/source/blender/bmesh/operators/bmo_beautify.c
index adf8ed4df67..68d0c662b2c 100644
--- a/source/blender/bmesh/operators/bmo_beautify.c
+++ b/source/blender/bmesh/operators/bmo_beautify.c
@@ -22,9 +22,21 @@
/** \file blender/bmesh/operators/bmo_beautify.c
* \ingroup bmesh
+ *
+ * Beautify the mesh by rotating edes between triangles
+ * to more attractive positions until no more rotations can be made.
+ *
+ * In princible this is very simple however there is the possability of
+ * going into an eternal loop where edges keep rotating.
+ * To avoid this - each edge stores a hash of it previous
+ * states so as not to rotate back.
+ *
+ * TODO
+ * - Take face normals into account.
*/
#include "BLI_math.h"
+#include "BLI_heap.h"
#include "MEM_guardedalloc.h"
@@ -112,21 +124,159 @@ static void erot_state_alternate(const BMEdge *e, EdRotState *e_state)
}
/* -------------------------------------------------------------------- */
-/* Util for setting edge tag once rotated */
+/* Calculate the improvement of rotating the edge */
+
+/**
+ * \return a negative value means the edge can be rotated.
+ */
+static float bm_edge_calc_rotate_beauty(const BMEdge *e)
+{
+ /* not a loop (only to be able to break out) */
+ do {
+ float v1_xy[2], v2_xy[2], v3_xy[2], v4_xy[2];
+
+ /* first get the 2d values */
+ {
+ const float *v1, *v2, *v3, *v4;
+ bool is_zero_a, is_zero_b;
+ float no[3];
+ float axis_mat[3][3];
+
+ v1 = e->l->prev->v->co; /* first face co */
+ v2 = e->l->v->co; /* e->v1 or e->v2*/
+ v3 = e->l->radial_next->prev->v->co; /* second face co */
+ v4 = e->l->next->v->co; /* e->v1 or e->v2*/
+
+ if (UNLIKELY(v1 == v3)) {
+ // printf("This should never happen, but does sometimes!\n");
+ break;
+ }
+
+ // printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
+ BLI_assert((ELEM3(v1, v2, v3, v4) == false) &&
+ (ELEM3(v2, v1, v3, v4) == false) &&
+ (ELEM3(v3, v1, v2, v4) == false) &&
+ (ELEM3(v4, v1, v2, v3) == false));
+
+ is_zero_a = area_tri_v3(v2, v3, v4) <= FLT_EPSILON;
+ is_zero_b = area_tri_v3(v2, v4, v1) <= FLT_EPSILON;
+
+ if (LIKELY(is_zero_a == false && is_zero_b == false)) {
+ float no_a[3], no_b[3];
+ normal_tri_v3(no_a, v2, v3, v4); /* a */
+ normal_tri_v3(no_b, v2, v4, v1); /* b */
+ add_v3_v3v3(no, no_a, no_b);
+ if (UNLIKELY(normalize_v3(no) <= FLT_EPSILON)) {
+ break;
+ }
+ }
+ else if (is_zero_a == false) {
+ normal_tri_v3(no, v2, v3, v4); /* a */
+ }
+ else if (is_zero_b == false) {
+ normal_tri_v3(no, v2, v4, v1); /* b */
+ }
+ else {
+ /* both zero area, no useful normal can be calculated */
+ break;
+ }
+
+ // { float a = angle_normalized_v3v3(no_a, no_b); printf("~ %.7f\n", a); fflush(stdout);}
+
+ axis_dominant_v3_to_m3(axis_mat, no);
+ mul_v2_m3v3(v1_xy, axis_mat, v1);
+ mul_v2_m3v3(v2_xy, axis_mat, v2);
+ mul_v2_m3v3(v3_xy, axis_mat, v3);
+ mul_v2_m3v3(v4_xy, axis_mat, v4);
+ }
+
+ // printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
+
+ if (is_quad_convex_v2(v1_xy, v2_xy, v3_xy, v4_xy)) {
+ float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
+ /* testing rule:
+ * the area divided by the total edge lengths
+ */
+ len1 = len_v2v2(v1_xy, v2_xy);
+ len2 = len_v2v2(v2_xy, v3_xy);
+ len3 = len_v2v2(v3_xy, v4_xy);
+ len4 = len_v2v2(v4_xy, v1_xy);
+ len5 = len_v2v2(v1_xy, v3_xy);
+ len6 = len_v2v2(v2_xy, v4_xy);
+
+ opp1 = area_tri_v2(v1_xy, v2_xy, v3_xy);
+ opp2 = area_tri_v2(v1_xy, v3_xy, v4_xy);
+
+ fac1 = opp1 / (len1 + len2 + len5) + opp2 / (len3 + len4 + len5);
+
+ opp1 = area_tri_v2(v2_xy, v3_xy, v4_xy);
+ opp2 = area_tri_v2(v2_xy, v4_xy, v1_xy);
+
+ fac2 = opp1 / (len2 + len3 + len6) + opp2 / (len4 + len1 + len6);
+ /* negative number if we're OK */
+ return fac2 - fac1;
+ }
+ } while (false);
+
+ return FLT_MAX;
+}
+
+/* -------------------------------------------------------------------- */
+/* Update the edge cost of rotation in the heap */
+
+/* recalc an edge in the heap (surrounding geometry has changed) */
+static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GHash **edge_state_arr)
+{
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ const int i = BM_elem_index_get(e);
+ GHash *e_state_hash = edge_state_arr[i];
+
+ if (eheap_table[i]) {
+ BLI_heap_remove(eheap, eheap_table[i]);
+ eheap_table[i] = NULL;
+ }
+
+ /* check if we can add it back */
+ BLI_assert(BM_edge_is_manifold(e) == true);
+ //BLI_assert(BMO_elem_flag_test(bm, e->l->f, FACE_MARK) &&
+ // BMO_elem_flag_test(bm, e->l->radial_next->f, FACE_MARK));
+
+ /* check we're not moving back into a state we have been in before */
+ if (e_state_hash != NULL) {
+ EdRotState e_state_alt;
+ erot_state_alternate(e, &e_state_alt);
+ if (BLI_ghash_haskey(e_state_hash, (void *)&e_state_alt)) {
+ // printf(" skipping, we already have this state\n");
+ return;
+ }
+ }
+
+ {
+ /* recalculate edge */
+ const float cost = bm_edge_calc_rotate_beauty(e);
+ if (cost < 0.0f) {
+ eheap_table[i] = BLI_heap_insert(eheap, cost, e);
+ }
+ else {
+ eheap_table[i] = NULL;
+ }
+ }
+ }
+}
/* we have rotated an edge, tag other egdes and clear this one */
-static void bm_edge_tag_rotated(BMEdge *e)
+static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GHash **edge_state_arr)
{
BMLoop *l;
BLI_assert(e->l->f->len == 3 &&
e->l->radial_next->f->len == 3);
l = e->l;
- BM_elem_flag_enable(l->next->e, BM_ELEM_TAG);
- BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG);
+ bm_edge_update_beauty_cost_single(l->next->e, eheap, eheap_table, edge_state_arr);
+ bm_edge_update_beauty_cost_single(l->prev->e, eheap, eheap_table, edge_state_arr);
l = l->radial_next;
- BM_elem_flag_enable(l->next->e, BM_ELEM_TAG);
- BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG);
+ bm_edge_update_beauty_cost_single(l->next->e, eheap, eheap_table, edge_state_arr);
+ bm_edge_update_beauty_cost_single(l->prev->e, eheap, eheap_table, edge_state_arr);
}
/* -------------------------------------------------------------------- */
@@ -141,160 +291,71 @@ static void bm_edge_tag_rotated(BMEdge *e)
*/
static void bm_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge_array_len)
{
+ Heap *eheap; /* edge heap */
+ HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */
+
GHash **edge_state_arr = MEM_callocN(edge_array_len * sizeof(GHash *), __func__);
BLI_mempool *edge_state_pool = BLI_mempool_create(sizeof(EdRotState), 512, 512, BLI_MEMPOOL_SYSMALLOC);
- bool is_breaked;
int i;
#ifdef DEBUG_TIME
TIMEIT_START(beautify_fill);
#endif
- do {
- is_breaked = true;
-
- for (i = 0; i < edge_array_len; i++) {
- BMEdge *e = edge_array[i];
- GHash *e_state_hash;
-
- float v1_xy[2], v2_xy[2], v3_xy[2], v4_xy[2];
-
- BLI_assert(BM_edge_is_manifold(e) == true);
- BLI_assert(BMO_elem_flag_test(bm, e->l->f, FACE_MARK) &&
- BMO_elem_flag_test(bm, e->l->radial_next->f, FACE_MARK));
+ eheap = BLI_heap_new_ex(edge_array_len);
+ eheap_table = MEM_mallocN(sizeof(HeapNode *) * edge_array_len, __func__);
- if (!BM_elem_flag_test(e, BM_ELEM_TAG)) {
- continue;
- }
- else {
- /* don't check this edge again, unless adjaced edges are rotated */
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- }
+ /* build heap */
+ for (i = 0; i < edge_array_len; i++) {
+ BMEdge *e = edge_array[i];
+ const float cost = bm_edge_calc_rotate_beauty(e);
+ if (cost < 0.0f) {
+ eheap_table[i] = BLI_heap_insert(eheap, cost, e);
+ }
+ else {
+ eheap_table[i] = NULL;
+ }
+ }
- /* check we're not moving back into a state we have been in before */
- e_state_hash = edge_state_arr[i];
- if (e_state_hash != NULL) {
- EdRotState e_state_alt;
- erot_state_alternate(e, &e_state_alt);
- if (BLI_ghash_haskey(e_state_hash, (void *)&e_state_alt)) {
- // printf(" skipping, we already have this state\n");
- continue;
- }
+ while (BLI_heap_is_empty(eheap) == false) {
+ BMEdge *e = BLI_heap_popmin(eheap);
+ i = BM_elem_index_get(e);
+ eheap_table[i] = NULL;
+
+ e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS);
+ if (LIKELY(e)) {
+ GHash *e_state_hash = edge_state_arr[i];
+
+ /* add the new state into the hash so we don't move into this state again
+ * note: we could add the previous state too but this isn't essential)
+ * for avoiding eternal loops */
+ EdRotState *e_state = BLI_mempool_alloc(edge_state_pool);
+ erot_state_current(e, e_state);
+ if (UNLIKELY(e_state_hash == NULL)) {
+ edge_state_arr[i] = e_state_hash = erot_ghash_new(); /* store previous state */
}
+ BLI_assert(BLI_ghash_haskey(e_state_hash, (void *)e_state) == false);
+ BLI_ghash_insert(e_state_hash, e_state, NULL);
- {
- const float *v1, *v2, *v3, *v4;
- bool is_zero_a, is_zero_b;
- float no[3];
- float axis_mat[3][3];
-
- v1 = e->l->prev->v->co; /* first face co */
- v2 = e->l->v->co; /* e->v1 or e->v2*/
- v3 = e->l->radial_next->prev->v->co; /* second face co */
- v4 = e->l->next->v->co; /* e->v1 or e->v2*/
-
- if (UNLIKELY(v1 == v3)) {
- // printf("This should never happen, but does sometimes!\n");
- continue;
- }
-
- // printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
- BLI_assert((ELEM3(v1, v2, v3, v4) == false) &&
- (ELEM3(v2, v1, v3, v4) == false) &&
- (ELEM3(v3, v1, v2, v4) == false) &&
- (ELEM3(v4, v1, v2, v3) == false));
-
- is_zero_a = area_tri_v3(v2, v3, v4) <= FLT_EPSILON;
- is_zero_b = area_tri_v3(v2, v4, v1) <= FLT_EPSILON;
-
- if (LIKELY(is_zero_a == false && is_zero_b == false)) {
- float no_a[3], no_b[3];
- normal_tri_v3(no_a, v2, v3, v4); /* a */
- normal_tri_v3(no_b, v2, v4, v1); /* b */
- add_v3_v3v3(no, no_a, no_b);
- if (UNLIKELY(normalize_v3(no) <= FLT_EPSILON)) {
- continue;
- }
- }
- else if (is_zero_a == false) {
- normal_tri_v3(no, v2, v3, v4); /* a */
- }
- else if (is_zero_b == false) {
- normal_tri_v3(no, v2, v4, v1); /* b */
- }
- else {
- /* both zero area, no useful normal can be calculated */
- continue;
- }
- // { float a = angle_normalized_v3v3(no_a, no_b); printf("~ %.7f\n", a); fflush(stdout);}
+ // printf(" %d -> %d, %d\n", i, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2));
- axis_dominant_v3_to_m3(axis_mat, no);
- mul_v2_m3v3(v1_xy, axis_mat, v1);
- mul_v2_m3v3(v2_xy, axis_mat, v2);
- mul_v2_m3v3(v3_xy, axis_mat, v3);
- mul_v2_m3v3(v4_xy, axis_mat, v4);
- }
+ /* maintain the index array */
+ edge_array[i] = e;
+ BM_elem_index_set(e, i);
- // printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
+ /* recalculate faces connected on the heap */
+ bm_edge_update_beauty_cost(e, eheap, eheap_table, edge_state_arr);
- if (is_quad_convex_v2(v1_xy, v2_xy, v3_xy, v4_xy)) {
- float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
- /* testing rule:
- * the area divided by the total edge lengths
- */
- len1 = len_v2v2(v1_xy, v2_xy);
- len2 = len_v2v2(v2_xy, v3_xy);
- len3 = len_v2v2(v3_xy, v4_xy);
- len4 = len_v2v2(v4_xy, v1_xy);
- len5 = len_v2v2(v1_xy, v3_xy);
- len6 = len_v2v2(v2_xy, v4_xy);
-
- opp1 = area_tri_v2(v1_xy, v2_xy, v3_xy);
- opp2 = area_tri_v2(v1_xy, v3_xy, v4_xy);
-
- fac1 = opp1 / (len1 + len2 + len5) + opp2 / (len3 + len4 + len5);
-
- opp1 = area_tri_v2(v2_xy, v3_xy, v4_xy);
- opp2 = area_tri_v2(v2_xy, v4_xy, v1_xy);
-
- fac2 = opp1 / (len2 + len3 + len6) + opp2 / (len4 + len1 + len6);
-
- if (fac1 > fac2) {
- e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS);
- if (LIKELY(e)) {
-
- /* add the new state into the hash so we don't move into this state again
- * note: we could add the previous state too but this isn't essential)
- * for avoiding eternal loops */
- EdRotState *e_state = BLI_mempool_alloc(edge_state_pool);
- erot_state_current(e, e_state);
- if (UNLIKELY(e_state_hash == NULL)) {
- edge_state_arr[i] = e_state_hash = erot_ghash_new(); /* store previous state */
- }
- BLI_assert(BLI_ghash_haskey(e_state_hash, (void *)e_state) == false);
- BLI_ghash_insert(e_state_hash, e_state, NULL);
-
-
- // printf(" %d -> %d, %d\n", i, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2));
-
- /* maintain the index array */
- edge_array[i] = e;
- BM_elem_index_set(e, i);
-
- /* tag other edges so we know to check them again */
- bm_edge_tag_rotated(e);
-
- /* update flags */
- BMO_elem_flag_enable(bm, e, ELE_NEW);
- BMO_elem_flag_enable(bm, e->l->f, FACE_MARK | ELE_NEW);
- BMO_elem_flag_enable(bm, e->l->radial_next->f, FACE_MARK | ELE_NEW);
- is_breaked = false;
- }
- }
- }
+ /* update flags */
+ BMO_elem_flag_enable(bm, e, ELE_NEW);
+ BMO_elem_flag_enable(bm, e->l->f, FACE_MARK | ELE_NEW);
+ BMO_elem_flag_enable(bm, e->l->radial_next->f, FACE_MARK | ELE_NEW);
}
- } while (is_breaked == false);
+ }
+
+ BLI_heap_free(eheap, NULL);
+ MEM_freeN(eheap_table);
for (i = 0; i < edge_array_len; i++) {
if (edge_state_arr[i]) {
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index 052ae9336ab..dc06b0b4f13 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_bevel.c
* \ingroup bmesh
+ *
+ * Bevel wrapper around #BM_mesh_bevel
*/
#include "BLI_utildefines.h"
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index dc00d020083..2e9cb11569d 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_connect.c
* \ingroup bmesh
+ *
+ * Connect verts across faces (splits faces) and bridge tool.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index 86904155cd3..ad858c514d2 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -15,13 +15,15 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor(s): Joseph Eagar.
+ * Contributor(s): Joseph Eagar, Campbell Barton.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/bmesh/operators/bmo_create.c
- * \ingroup bmesh
+ * \ingroup bmesh
+ *
+ * Create faces or edges (Fkey by default).
*/
#include "MEM_guardedalloc.h"
@@ -41,14 +43,9 @@
*/
void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
{
- BMOperator op2;
BMOIter oiter;
- BMIter iter;
BMHeader *h;
- BMVert *v, *verts[4];
- BMEdge *e;
- BMFace *f;
- int totv = 0, tote = 0, totf = 0, amount;
+ int totv = 0, tote = 0, totf = 0;
const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
@@ -63,6 +60,24 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
BMO_elem_flag_enable(bm, (BMElemF *)h, ELE_NEW);
}
+ /* --- Support Edge Creation ---
+ * simple case when we only have 2 verts selected.
+ */
+ if (totv == 2 && tote == 0 && totf == 0) {
+ BMVert *verts[2];
+ BMEdge *e;
+
+ BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)verts, 2);
+
+ /* create edge */
+ e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE);
+ BMO_elem_flag_enable(bm, e, ELE_OUT);
+ tote += 1;
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
+ return;
+ }
+
+
/* --- Support for Special Case ---
* where there is a contiguous edge ring with one isolated vertex.
*
@@ -83,29 +98,20 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
/* Here we check for consistency and create 2 edges */
if (totf == 0 && totv >= 4 && totv == tote + 2) {
/* find a free standing vertex and 2 endpoint verts */
- BMVert *v_free = NULL, *v_a = NULL, *v_b = NULL;
+ BMVert *v, *v_free = NULL, *v_a = NULL, *v_b = NULL;
bool ok = true;
BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) {
/* count how many flagged edges this vertex uses */
- int tot_edges = 0;
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- if (BMO_elem_flag_test(bm, e, ELE_NEW)) {
- tot_edges++;
- if (tot_edges > 2) {
- break;
- }
- }
- }
-
+ const int tot_edges = BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, v, ELE_NEW, true);
if (tot_edges == 0) {
/* only accept 1 free vert */
if (v_free == NULL) v_free = v;
else ok = false; /* only ever want one of these */
}
else if (tot_edges == 1) {
- if (v_a == NULL) v_a = v;
+ if (v_a == NULL) v_a = v;
else if (v_b == NULL) v_b = v;
else ok = false; /* only ever want 2 of these */
}
@@ -122,6 +128,8 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
}
if (ok == true && v_free && v_a && v_b) {
+ BMEdge *e;
+
e = BM_edge_create(bm, v_free, v_a, NULL, BM_CREATE_NO_DOUBLE);
BMO_elem_flag_enable(bm, e, ELE_NEW);
@@ -135,92 +143,81 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
/* -------------------------------------------------------------------- */
/* EdgeNet Create */
+ if (tote != 0) {
+ /* call edgenet prepare op so additional face creation cases work */
+ BMOperator op_sub;
+ BMO_op_initf(bm, &op_sub, op->flag, "edgenet_prepare edges=%fe", ELE_NEW);
+ BMO_op_exec(bm, &op_sub);
+ BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "edges.out", BM_EDGE, ELE_NEW);
+ BMO_op_finish(bm, &op_sub);
+
+ BMO_op_initf(bm, &op_sub, op->flag,
+ "edgenet_fill edges=%fe use_fill_check=%b mat_nr=%i use_smooth=%b",
+ ELE_NEW, true, mat_nr, use_smooth);
+
+ BMO_op_exec(bm, &op_sub);
+
+ /* return if edge net create did something */
+ if (BMO_slot_buffer_count(op_sub.slots_out, "faces.out")) {
+ BMO_slot_copy(&op_sub, slots_out, "faces.out",
+ op, slots_out, "faces.out");
+ BMO_op_finish(bm, &op_sub);
+ return;
+ }
- /* call edgenet prepare op so additional face creation cases wore */
- BMO_op_initf(bm, &op2, op->flag, "edgenet_prepare edges=%fe", ELE_NEW);
- BMO_op_exec(bm, &op2);
- BMO_slot_buffer_flag_enable(bm, op2.slots_out, "edges.out", BM_EDGE, ELE_NEW);
- BMO_op_finish(bm, &op2);
-
- BMO_op_initf(bm, &op2, op->flag,
- "edgenet_fill edges=%fe use_fill_check=%b mat_nr=%i use_smooth=%b",
- ELE_NEW, true, mat_nr, use_smooth);
-
- BMO_op_exec(bm, &op2);
-
- /* return if edge net create did something */
- if (BMO_slot_buffer_count(op2.slots_out, "faces.out")) {
- BMO_slot_copy(&op2, slots_out, "faces.out",
- op, slots_out, "faces.out");
- BMO_op_finish(bm, &op2);
- return;
+ BMO_op_finish(bm, &op_sub);
}
- BMO_op_finish(bm, &op2);
-
/* -------------------------------------------------------------------- */
/* Dissolve Face */
- BMO_op_initf(bm, &op2, op->flag, "dissolve_faces faces=%ff", ELE_NEW);
- BMO_op_exec(bm, &op2);
-
- /* if we dissolved anything, then return */
- if (BMO_slot_buffer_count(op2.slots_out, "region.out")) {
- BMO_slot_copy(&op2, slots_out, "region.out",
- op, slots_out, "faces.out");
- BMO_op_finish(bm, &op2);
- return;
- }
+ if (totf != 0) { /* should be (totf > 1)... see below */
+ /* note: allow this to run on single faces so running on a single face
+ * won't go on to create a face, treating them as random */
+ BMOperator op_sub;
+ BMO_op_initf(bm, &op_sub, op->flag, "dissolve_faces faces=%ff", ELE_NEW);
+ BMO_op_exec(bm, &op_sub);
+
+ /* if we dissolved anything, then return */
+ if (BMO_slot_buffer_count(op_sub.slots_out, "region.out")) {
+ BMO_slot_copy(&op_sub, slots_out, "region.out",
+ op, slots_out, "faces.out");
+ BMO_op_finish(bm, &op_sub);
+ return;
+ }
- BMO_op_finish(bm, &op2);
+ BMO_op_finish(bm, &op_sub);
+ }
/* -------------------------------------------------------------------- */
/* Fill EdgeLoop's - fills isolated loops, different from edgenet */
+ if (tote > 2) {
+ BMOperator op_sub;
+ /* note: in most cases 'edgenet_fill' will handle this case since in common cases
+ * users fill in empty spaces, however its possible to have an edge selection around
+ * existing geometry that makes 'edgenet_fill' fail. */
+ BMO_op_initf(bm, &op_sub, op->flag, "edgeloop_fill edges=%fe", ELE_NEW);
+ BMO_op_exec(bm, &op_sub);
+
+ /* return if edge loop fill did something */
+ if (BMO_slot_buffer_count(op_sub.slots_out, "faces.out")) {
+ BMO_slot_copy(&op_sub, slots_out, "faces.out",
+ op, slots_out, "faces.out");
+ BMO_op_finish(bm, &op_sub);
+ return;
+ }
- /* note: in most cases 'edgenet_fill' will handle this case since in common cases
- * users fill in empty spaces, however its possible to have an edge selection around
- * existing geometry that makes 'edgenet_fill' fail. */
- BMO_op_initf(bm, &op2, op->flag, "edgeloop_fill edges=%fe", ELE_NEW);
- BMO_op_exec(bm, &op2);
-
- /* return if edge loop fill did something */
- if (BMO_slot_buffer_count(op2.slots_out, "faces.out")) {
- BMO_slot_copy(&op2, slots_out, "faces.out",
- op, slots_out, "faces.out");
- BMO_op_finish(bm, &op2);
- return;
+ BMO_op_finish(bm, &op_sub);
}
- BMO_op_finish(bm, &op2);
-
/* -------------------------------------------------------------------- */
/* Continue with ad-hoc fill methods since operators fail,
* edge, vcloud... may add more */
- /* now, count how many verts we have */
- amount = 0;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_elem_flag_test(bm, v, ELE_NEW)) {
- verts[amount] = v;
- if (amount == 3) {
- break;
- }
- amount++;
-
- }
- }
-
- if (amount == 2) {
- /* create edge */
- e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(bm, e, ELE_OUT);
- tote += 1;
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
- }
- else if (0) { /* nice feature but perhaps it should be a different tool? */
+ if (0) { /* nice feature but perhaps it should be a different tool? */
/* tricky feature for making a line/edge from selection history...
*
@@ -255,9 +252,9 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
for (ese = bm->selected.first; ese; ese = ese->next) {
if (ese->htype == BM_VERT) {
- v = (BMVert *)ese->ele;
+ BMVert *v = (BMVert *)ese->ele;
if (v_prev) {
- e = BM_edge_create(bm, v, v_prev, NULL, BM_CREATE_NO_DOUBLE);
+ BMEdge *e = BM_edge_create(bm, v, v_prev, NULL, BM_CREATE_NO_DOUBLE);
BMO_elem_flag_enable(bm, e, ELE_OUT);
}
v_prev = v;
@@ -266,20 +263,25 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
}
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
/* done creating edges */
+
+ return;
}
- else if (amount > 2) {
+
+
+ /* -------------------------------------------------------------------- */
+ /* Fill Vertex Cloud
+ *
+ * last resort when all else fails.
+ */
+ if (totv > 2) {
/* TODO, some of these vertes may be connected by edges,
* this connectivity could be used rather then treating
* them as a bunch of isolated verts. */
BMVert **vert_arr = MEM_mallocN(sizeof(BMVert **) * totv, __func__);
- int i = 0;
-
- BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) {
- vert_arr[i] = v;
- i++;
- }
+ BMFace *f;
+ BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)vert_arr, totv);
f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, BM_CREATE_NO_DOUBLE);
if (f) {
@@ -293,6 +295,4 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
MEM_freeN(vert_arr);
}
-
- (void)tote;
}
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index 4a241ca645f..13d706d8eed 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_dissolve.c
* \ingroup bmesh
+ *
+ * Removes isolated geometry regions without creating holes in the mesh.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 1448129ccde..9cc96fdca5a 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_dupe.c
* \ingroup bmesh
+ *
+ * Duplicate, Split, Spint operators.
*/
#include "MEM_guardedalloc.h"
@@ -124,7 +126,6 @@ static BMEdge *copy_edge(BMOperator *op,
*
* Copy an existing face from one bmesh to another.
*/
-
static BMFace *copy_face(BMOperator *op,
BMOpSlot *slot_facemap_out,
BMesh *source_mesh,
@@ -183,7 +184,6 @@ static BMFace *copy_face(BMOperator *op,
*
* Internal Copy function.
*/
-
static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst)
{
@@ -320,7 +320,6 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst)
* BMOP_DUPE_ENEW: Buffer containing pointers to the new mesh edges
* BMOP_DUPE_FNEW: Buffer containing pointers to the new mesh faces
*/
-
void bmo_duplicate_exec(BMesh *bm, BMOperator *op)
{
BMOperator *dupeop = op;
@@ -378,11 +377,10 @@ void BMO_dupe_from_flag(BMesh *bm, int htype, const char hflag)
* BMOP_DUPE_EOUTPUT: Buffer containing pointers to the split mesh edges
* BMOP_DUPE_FOUTPUT: Buffer containing pointers to the split mesh faces
*/
-
-#define SPLIT_INPUT 1
-
void bmo_split_exec(BMesh *bm, BMOperator *op)
{
+#define SPLIT_INPUT 1
+
BMOperator *splitop = op;
BMOperator dupeop;
BMOperator delop;
@@ -455,6 +453,8 @@ void bmo_split_exec(BMesh *bm, BMOperator *op)
/* cleanup */
BMO_op_finish(bm, &delop);
BMO_op_finish(bm, &dupeop);
+
+#undef SPLIT_INPUT
}
@@ -478,7 +478,6 @@ void bmo_delete_exec(BMesh *bm, BMOperator *op)
* Extrude or duplicate geometry a number of times,
* rotating and possibly translating after each step
*/
-
void bmo_spin_exec(BMesh *bm, BMOperator *op)
{
BMOperator dupop, extop;
diff --git a/source/blender/bmesh/operators/bmo_edgeloop_fill.c b/source/blender/bmesh/operators/bmo_edgeloop_fill.c
index 3818f449a15..604feeeef5d 100644
--- a/source/blender/bmesh/operators/bmo_edgeloop_fill.c
+++ b/source/blender/bmesh/operators/bmo_edgeloop_fill.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_edgeloop_fill.c
* \ingroup bmesh
+ *
+ * Fill discreet edge loop(s) with faces.
*/
#include "MEM_guardedalloc.h"
@@ -54,6 +56,7 @@ void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op)
const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
/* 'VERT_USED' will be disabled, so enable and fill the array */
+ i = 0;
BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
BMIter viter;
BMO_elem_flag_enable(bm, e, EDGE_MARK);
@@ -61,7 +64,7 @@ void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op)
if (BMO_elem_flag_test(bm, v, VERT_USED) == false) {
BMO_elem_flag_enable(bm, v, VERT_USED);
verts[i++] = v;
- if (i > tote) {
+ if (i == tote) {
break;
}
}
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c
index cf91dfd0f15..a4af570ded0 100644
--- a/source/blender/bmesh/operators/bmo_edgenet.c
+++ b/source/blender/bmesh/operators/bmo_edgenet.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_edgenet.c
* \ingroup bmesh
+ *
+ * Edge-Net for filling in open edge-loops.
*/
#include "MEM_guardedalloc.h"
@@ -43,7 +45,6 @@
#define FACE_NEW 1
#define ELE_NEW 1
-#define ELE_OUT 2
#define ELE_ORIG 4
#define FACE_IGNORE 16
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index 62220510623..acb1001ca83 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_extrude.c
* \ingroup bmesh
+ *
+ * Extrude faces and solidify.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c
index 810b608b28e..500e984f4c9 100644
--- a/source/blender/bmesh/operators/bmo_hull.c
+++ b/source/blender/bmesh/operators/bmo_hull.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_hull.c
* \ingroup bmesh
+ *
+ * Create a convex hull using bullet physics library.
*/
#ifdef WITH_BULLET
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index ef99dae5ac9..a3656ce5b74 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -22,6 +22,11 @@
/** \file blender/bmesh/operators/bmo_inset.c
* \ingroup bmesh
+ *
+ * Inset face regions.
+ *
+ * TODO
+ * - Inset indervidual faces.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index e052968a6a0..5e4fa29d953 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -22,6 +22,11 @@
/** \file blender/bmesh/operators/bmo_join_triangles.c
* \ingroup bmesh
+ *
+ * Convert triangle to quads.
+ *
+ * TODO
+ * - convert triangles to any sided faces, not just quads.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/bmesh/operators/bmo_mirror.c b/source/blender/bmesh/operators/bmo_mirror.c
index 48b2f76665c..6aff41b47d1 100644
--- a/source/blender/bmesh/operators/bmo_mirror.c
+++ b/source/blender/bmesh/operators/bmo_mirror.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_mirror.c
* \ingroup bmesh
+ *
+ * Basic mirror, optionally with UVs's.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index 10a48c1b78c..9f17c1dd8e3 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_primitive.c
* \ingroup bmesh
+ *
+ * Primitive shapes.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index 65b3267914f..da70e201976 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_removedoubles.c
* \ingroup bmesh
+ *
+ * Welding and merging functionality.
*/
#include "MEM_guardedalloc.h"
@@ -99,11 +101,11 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
{
BMIter iter, liter;
BMVert *v, *v2;
- BMEdge *e, *e2, **edges = NULL;
+ BMEdge *e, *e_new, **edges = NULL;
BLI_array_declare(edges);
- BMLoop *l, *l2, **loops = NULL;
+ BMLoop *l, *l_new, **loops = NULL;
BLI_array_declare(loops);
- BMFace *f, *f2;
+ BMFace *f, *f_new;
int a, b;
BMOpSlot *slot_targetmap = BMO_slot_get(op->slots_in, "targetmap");
@@ -180,10 +182,10 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
v2 = BMO_slot_map_elem_get(slot_targetmap, v2);
}
- e2 = v != v2 ? BM_edge_exists(v, v2) : NULL;
- if (e2) {
+ e_new = v != v2 ? BM_edge_exists(v, v2) : NULL;
+ if (e_new) {
for (b = 0; b < a; b++) {
- if (edges[b] == e2) {
+ if (edges[b] == e_new) {
break;
}
}
@@ -194,7 +196,7 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
BLI_array_grow_one(edges);
BLI_array_grow_one(loops);
- edges[a] = e2;
+ edges[a] = e_new;
loops[a] = l;
a++;
@@ -213,14 +215,14 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
v2 = BMO_slot_map_elem_get(slot_targetmap, v2);
}
- f2 = BM_face_create_ngon(bm, v, v2, edges, a, BM_CREATE_NO_DOUBLE);
- if (f2 && (f2 != f)) {
- BM_elem_attrs_copy(bm, bm, f, f2);
+ f_new = BM_face_create_ngon(bm, v, v2, edges, a, BM_CREATE_NO_DOUBLE);
+ if (f_new && (f_new != f)) {
+ BM_elem_attrs_copy(bm, bm, f, f_new);
a = 0;
- BM_ITER_ELEM (l, &liter, f2, BM_LOOPS_OF_FACE) {
- l2 = loops[a];
- BM_elem_attrs_copy(bm, bm, l2, l);
+ BM_ITER_ELEM (l, &liter, f_new, BM_LOOPS_OF_FACE) {
+ l_new = loops[a];
+ BM_elem_attrs_copy(bm, bm, l_new, l);
a++;
}
diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
index 0c0a2c308ee..12368d1aeda 100644
--- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c
+++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_smooth_laplacian.c
* \ingroup bmesh
+ *
+ * Advanced smoothing.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index 9115ee882dd..32c5385bee6 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_subdivide.c
* \ingroup bmesh
+ *
+ * Edge based subdivision with various subdivision patterns.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c
index 0bfc81f83cf..b684240dc76 100644
--- a/source/blender/bmesh/operators/bmo_symmetrize.c
+++ b/source/blender/bmesh/operators/bmo_symmetrize.c
@@ -20,6 +20,13 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/bmesh/operators/bmo_symmetrize.c
+ * \ingroup bmesh
+ *
+ * Makes the mesh symmetrical by splitting along an axis and duplicating the geometry.
+ */
+
+
#include "MEM_guardedalloc.h"
#include "BLI_array.h"
diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c
index 29c3764045e..754709b18c0 100644
--- a/source/blender/bmesh/operators/bmo_triangulate.c
+++ b/source/blender/bmesh/operators/bmo_triangulate.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_triangulate.c
* \ingroup bmesh
+ *
+ * Triangulate faces, also defines triangle fill.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/bmesh/operators/bmo_unsubdivide.c b/source/blender/bmesh/operators/bmo_unsubdivide.c
index 784e695efb0..c1cfb1866f4 100644
--- a/source/blender/bmesh/operators/bmo_unsubdivide.c
+++ b/source/blender/bmesh/operators/bmo_unsubdivide.c
@@ -22,6 +22,9 @@
/** \file blender/bmesh/operators/bmo_unsubdivide.c
* \ingroup bmesh
+ *
+ * Pattern based geometry reduction which has the result similar to undoing
+ * a subdivide operation.
*/
#include "BLI_math.h"
diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c
index 00838533104..935a743116e 100644
--- a/source/blender/bmesh/operators/bmo_wireframe.c
+++ b/source/blender/bmesh/operators/bmo_wireframe.c
@@ -22,6 +22,8 @@
/** \file blender/bmesh/operators/bmo_wireframe.c
* \ingroup bmesh
+ *
+ * Creates a solid wireframe from conected faces.
*/
#include "MEM_guardedalloc.h"