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
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2012-03-09 07:16:39 +0400
committerCampbell Barton <ideasman42@gmail.com>2012-03-09 07:16:39 +0400
commit78d73eb155035098f29581f3988779e3104b2599 (patch)
tree9978d34e8bcf7e5ed38c51a0919986d83df24c52 /source
parent4f7bdc59d31e94bc97955c1efeef2a8fce0c8ecd (diff)
BMesh: rewrite edge split code (used by edge split modifier and rip tool)
this fixes but [#30461] where the same vertex was added to some faces twice. Previous code rebuilt all faces around the split edges, replace this with much simpler code that uses existing bmesh API for splitting. This also gives a performance boost to the modifier (over 30x faster in the bug-report file).
Diffstat (limited to 'source')
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c16
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c3
-rw-r--r--source/blender/bmesh/operators/bmo_edgesplit.c398
-rw-r--r--source/blender/editors/mesh/bmesh_tools.c81
5 files changed, 73 insertions, 428 deletions
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 3ca7750f571..133e446f891 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -41,8 +41,6 @@
* TESTING ONLY! */
// #define USE_DEBUG_INDEX_MEMCHECK
-static int bm_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep);
-
#ifdef USE_DEBUG_INDEX_MEMCHECK
#define DEBUG_MEMCHECK_INDEX_INVALIDATE(ele) \
{ \
@@ -1748,7 +1746,7 @@ static int bm_vert_splice(BMesh *bm, BMVert *v, BMVert *vtarget)
*
* \return Success
*/
-int bm_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len)
+int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len)
{
BMEdge **stack = NULL;
BLI_array_declare(stack);
@@ -1856,11 +1854,11 @@ int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
for (i = 0; i < e_in_len; i++) {
BMEdge *e = e_in[i];
if (e->l && BM_vert_in_edge(e, v)) {
- bm_edge_separate(bm, e, e->l);
+ bmesh_edge_separate(bm, e, e->l);
}
}
- return bm_vert_separate(bm, v, r_vout, r_vout_len);
+ return bmesh_vert_separate(bm, v, r_vout, r_vout_len);
}
/**
@@ -1911,7 +1909,7 @@ int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget)
* \note Does nothing if \a l_sep is already the only loop in the
* edge radial.
*/
-static int bm_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep)
+int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep)
{
BMEdge *ne;
int radlen;
@@ -1959,8 +1957,8 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl)
/* peel the face from the edge radials on both sides of the
* loop vert, disconnecting the face from its fan */
- bm_edge_separate(bm, sl->e, sl);
- bm_edge_separate(bm, sl->prev->e, sl->prev);
+ bmesh_edge_separate(bm, sl->e, sl);
+ bmesh_edge_separate(bm, sl->prev->e, sl->prev);
if (bmesh_disk_count(sv) == 2) {
/* If there are still only two edges out of sv, then
@@ -1978,7 +1976,7 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl)
/* Split all fans connected to the vert, duplicating it for
* each fans. */
- bm_vert_separate(bm, sv, &vtar, &len);
+ bmesh_vert_separate(bm, sv, &vtar, &len);
/* There should have been at least two fans cut apart here,
* otherwise the early exit would have kicked in. */
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index 11f3e052bff..e10222dc29a 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -41,6 +41,9 @@ void BM_edge_kill(BMesh *bm, BMEdge *e);
void BM_vert_kill(BMesh *bm, BMVert *v);
int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget);
+int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep);
+
+int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len);
int bmesh_loop_reverse(BMesh *bm, BMFace *f);
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 97990c614d5..f2dcaded8ca 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -890,8 +890,7 @@ static BMOpDefine bmo_vertexshortestpath_def = {
static BMOpDefine bmo_edgesplit_def = {
"edgesplit",
{{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */
- {BMO_OP_SLOT_ELEMENT_BUF, "edgeout1"}, /* old output disconnected edges */
- {BMO_OP_SLOT_ELEMENT_BUF, "edgeout2"}, /* new output disconnected edges */
+ {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* old output disconnected edges */
{0} /* null-terminating sentine */},
bmo_edgesplit_exec,
BMO_OP_FLAG_UNTAN_MULTIRES
diff --git a/source/blender/bmesh/operators/bmo_edgesplit.c b/source/blender/bmesh/operators/bmo_edgesplit.c
index f1d3fbeb6af..44d0ad4ff94 100644
--- a/source/blender/bmesh/operators/bmo_edgesplit.c
+++ b/source/blender/bmesh/operators/bmo_edgesplit.c
@@ -15,208 +15,21 @@
* 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): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
-#include <string.h> /* for memcpy */
-
#include "MEM_guardedalloc.h"
-#include "BLI_array.h"
-
#include "bmesh.h"
#include "intern/bmesh_operators_private.h" /* own include */
-typedef struct EdgeTag {
- BMVert *newv1, *newv2;
- BMEdge *newe1, *newe2;
-} EdgeTag;
-
-/* (EDGE_DEL == FACE_DEL) - this must be the case */
-enum {
- EDGE_DEL = 1,
- EDGE_SEAM = 2,
- EDGE_MARK = 4,
- EDGE_RET1 = 8,
- EDGE_RET2 = 16
-};
-
enum {
- FACE_DEL = EDGE_DEL,
- FACE_NEW = 2
+ EDGE_SEAM = 1
};
-static BMFace *remake_face(BMesh *bm, EdgeTag *etags, BMFace *f, BMVert **f_verts, BMEdge **edges_tmp)
-{
- BMIter liter1, liter2;
- EdgeTag *et;
- BMFace *f2;
- BMLoop *l, *l2;
- BMEdge *e;
- BMVert *lastv1, *lastv2 /* , *v1, *v2 */ /* UNUSED */;
- int i;
-
- /* we do final edge last */
- lastv1 = f_verts[f->len - 1];
- lastv2 = f_verts[0];
- /* v1 = f_verts[0]; */ /* UNUSED */
- /* v2 = f_verts[1]; */ /* UNUSED */
- for (i = 0; i < f->len - 1; i++) {
- e = BM_edge_create(bm, f_verts[i], f_verts[i + 1], NULL, TRUE);
- if (!e) {
- return NULL;
- }
- edges_tmp[i] = e;
- }
-
- edges_tmp[i] = BM_edge_create(bm, lastv1, lastv2, NULL, TRUE);
-
- f2 = BM_face_create(bm, f_verts, edges_tmp, f->len, FALSE);
- if (!f2) {
- return NULL;
- }
-
- BM_elem_attrs_copy(bm, bm, f, f2);
-
- l = BM_iter_new(&liter1, bm, BM_LOOPS_OF_FACE, f);
- l2 = BM_iter_new(&liter2, bm, BM_LOOPS_OF_FACE, f2);
- for ( ; l && l2; l = BM_iter_step(&liter1), l2 = BM_iter_step(&liter2)) {
- BM_elem_attrs_copy(bm, bm, l, l2);
- if (l->e != l2->e) {
- /* set up data for figuring out the two sides of
- * the split */
-
- /* set edges index as dirty after running all */
- BM_elem_index_set(l2->e, BM_elem_index_get(l->e)); /* set_dirty! */
- et = &etags[BM_elem_index_get(l->e)];
-
- if (!et->newe1) {
- et->newe1 = l2->e;
- }
- else if (!et->newe2) {
- et->newe2 = l2->e;
- }
- else {
- /* Only two new edges should be created from each original edge
- * for edge split operation */
-
- //BLI_assert(et->newe1 == l2->e || et->newe2 == l2->e);
- et->newe2 = l2->e;
- }
-
- if (BMO_elem_flag_test(bm, l->e, EDGE_SEAM)) {
- BMO_elem_flag_enable(bm, l2->e, EDGE_SEAM);
- }
-
- BM_elem_attrs_copy(bm, bm, l->e, l2->e);
- }
-
- BMO_elem_flag_enable(bm, l->e, EDGE_MARK);
- BMO_elem_flag_enable(bm, l2->e, EDGE_MARK);
- }
-
- return f2;
-}
-
-static void tag_out_edges(BMesh *bm, EdgeTag *etags, BMOperator *UNUSED(op))
-{
- EdgeTag *et;
- BMIter iter;
- BMLoop *l, *l_start, *l_prev;
- BMEdge *e;
- BMVert *v;
- int i, ok;
-
- ok = 0;
- while (ok++ < 100000) {
- BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
- if (!BMO_elem_flag_test(bm, e, EDGE_SEAM))
- continue;
-
- if (e->l) {
- break;
- }
- }
-
- if (!e) {
- break;
- }
-
- /* ok we found an edge, part of a region of splits we need
- * to identify. now walk along it */
- for (i = 0; i < 2; i++) {
- l = e->l;
-
- v = i ? l->next->v : l->v;
-
- while (1) {
- et = &etags[BM_elem_index_get(l->e)];
- if (et->newe1 == l->e) {
- if (et->newe1) {
- BMO_elem_flag_enable(bm, et->newe1, EDGE_RET1);
- BMO_elem_flag_disable(bm, et->newe1, EDGE_SEAM);
- }
- if (et->newe2) {
- BMO_elem_flag_enable(bm, et->newe2, EDGE_RET2);
- BMO_elem_flag_disable(bm, et->newe2, EDGE_SEAM);
- }
- }
- else {
- if (et->newe1) {
- BMO_elem_flag_enable(bm, et->newe1, EDGE_RET2);
- BMO_elem_flag_disable(bm, et->newe1, EDGE_SEAM);
- }
- if (et->newe2) {
- BMO_elem_flag_enable(bm, et->newe2, EDGE_RET1);
- BMO_elem_flag_disable(bm, et->newe2, EDGE_SEAM);
- }
- }
-
- /* If the original edge was non-manifold edges, then it is
- * possible l->e is not et->newe1 or et->newe2. So always clear
- * the flag on l->e as well, to prevent infinite looping. */
- BMO_elem_flag_disable(bm, l->e, EDGE_SEAM);
- l_start = l;
-
- do {
- /* l_prev checks stops us from looping over the same edge forever [#30459] */
- l_prev = l;
- l = BM_face_other_edge_loop(l->f, l->e, v);
- if (l == l_start || BM_edge_face_count(l->e) != 2) {
- break;
- }
- l = l->radial_next;
- } while (l != l_start && l != l_prev && !BMO_elem_flag_test(bm, l->e, EDGE_SEAM));
-
- if (l == l_start || !BMO_elem_flag_test(bm, l->e, EDGE_SEAM)) {
- break;
- }
-
- v = (l->v == v) ? l->next->v : l->v;
- }
- }
- }
-}
-
-/* helper functions for edge tag's */
-BM_INLINE BMVert *bm_edge_tag_vert_get(EdgeTag *et, BMVert *v, BMLoop *l)
-{
- return (l->e->v1 == v) ? et->newv1 : et->newv2;
-}
-
-BM_INLINE void bm_edge_tag_vert_set(EdgeTag *et, BMVert *v, BMLoop *l, BMVert *vset)
-{
- if (l->e->v1 == v) {
- et->newv1 = vset;
- }
- else {
- et->newv2 = vset;
- }
-}
-
/**
* Remove the EDGE_SEAM flag for edges we cant split
*
@@ -238,6 +51,11 @@ static void bm_edgesplit_validate_seams(BMesh *bm, BMOperator *op)
/* tag all boundry verts so as not to untag an edge which is inbetween only 2 faces [] */
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+
+ /* unrelated to flag assignment in this function - since this is the
+ * only place we loop over all edges, disable tag */
+ BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
+
if (BM_edge_is_boundary(e)) {
vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++;
vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++;
@@ -270,202 +88,36 @@ static void bm_edgesplit_validate_seams(BMesh *bm, BMOperator *op)
void bmo_edgesplit_exec(BMesh *bm, BMOperator *op)
{
- EdgeTag *etags, *et; /* edge aligned array of tags */
- BMIter iter, liter;
- BMFace *f, *f2;
- BMLoop *l, *l2, *l3;
- BMLoop *l_next, *l_prev;
+ BMOIter siter;
BMEdge *e;
- BMVert *v, *v2;
-
- /* face/vert aligned vert array */
- BMVert **f_verts = NULL;
- BLI_array_declare(f_verts);
-
- BMEdge **edges_tmp = NULL;
- BLI_array_declare(edges_tmp);
- int i, j;
BMO_slot_buffer_flag_enable(bm, op, "edges", EDGE_SEAM, BM_EDGE);
bm_edgesplit_validate_seams(bm, op);
- etags = MEM_callocN(sizeof(EdgeTag) * bm->totedge, "EdgeTag");
-
- BM_mesh_elem_index_ensure(bm, BM_EDGE);
-
- BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
-
- if (BMO_elem_flag_test(bm, f, FACE_NEW)) {
- continue;
- }
-
- BLI_array_empty(f_verts);
- BLI_array_growitems(f_verts, f->len);
- memset(f_verts, 0, sizeof(BMVert *) * f->len);
-
- /* this is passed onto remake_face() so it doesnt need to allocate
- * a new array on each call. */
- BLI_array_empty(edges_tmp);
- BLI_array_growitems(edges_tmp, f->len);
-
- i = 0;
- BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
- if (!BMO_elem_flag_test(bm, l->e, EDGE_SEAM)) {
- if (!f_verts[i]) {
-
- et = &etags[BM_elem_index_get(l->e)];
- if (bm_edge_tag_vert_get(et, l->v, l)) {
- f_verts[i] = bm_edge_tag_vert_get(et, l->v, l);
- }
- else {
- f_verts[i] = l->v;
- }
- }
- i++;
- continue;
- }
-
- l_next = l->next;
- l_prev = l->prev;
-
- for (j = 0; j < 2; j++) {
- /* correct as long as i & j dont change during the loop */
- const int fv_index = j ? (i + 1) % f->len : i; /* face vert index */
- l2 = j ? l_next : l_prev;
- v = j ? l2->v : l->v;
-
- if (BMO_elem_flag_test(bm, l2->e, EDGE_SEAM)) {
- if (f_verts[fv_index] == NULL) {
- /* make unique vert here for this face only */
- v2 = BM_vert_create(bm, v->co, v);
- f_verts[fv_index] = v2;
- }
- else {
- v2 = f_verts[fv_index];
- }
- }
- else {
- /* generate unique vert for non-seam edge(s)
- * around the manifold vert fan if necessary */
-
- /* first check that we have two seam edges
- * somewhere within this fa */
- l3 = l2;
- do {
- if (BM_edge_face_count(l3->e) != 2) {
- /* if we hit a boundary edge, tag
- * l3 as null so we know to disconnect
- * it */
- if (BM_edge_face_count(l3->e) == 1) {
- l3 = NULL;
- }
- break;
- }
-
- l3 = l3->radial_next;
- l3 = BM_face_other_edge_loop(l3->f, l3->e, v);
- } while (l3 != l2 && !BMO_elem_flag_test(bm, l3->e, EDGE_SEAM));
-
- if (l3 == NULL || (BMO_elem_flag_test(bm, l3->e, EDGE_SEAM) && l3->e != l->e)) {
- et = &etags[BM_elem_index_get(l2->e)];
- if (bm_edge_tag_vert_get(et, v, l2) == NULL) {
- v2 = BM_vert_create(bm, v->co, v);
-
- l3 = l2;
- do {
- bm_edge_tag_vert_set(et, v, l3, v2);
- if (BM_edge_face_count(l3->e) != 2) {
- break;
- }
-
- l3 = l3->radial_next;
- l3 = BM_face_other_edge_loop(l3->f, l3->e, v);
-
- et = &etags[BM_elem_index_get(l3->e)];
- } while (l3 != l2 && !BMO_elem_flag_test(bm, l3->e, EDGE_SEAM));
- }
- else {
- v2 = bm_edge_tag_vert_get(et, v, l2);
- }
-
- f_verts[fv_index] = v2;
- }
- else {
- f_verts[fv_index] = v;
- }
- }
- }
-
- i++;
- }
-
- /* debugging code, quick way to find the face/vert combination
- * which is failing assuming quads start planer - campbell */
-#if 0
- if (f->len == 4) {
- float no1[3];
- float no2[3];
- float angle_error;
- printf(" ** found QUAD\n");
- normal_tri_v3(no1, f_verts[0]->co, f_verts[1]->co, f_verts[2]->co);
- normal_tri_v3(no2, f_verts[0]->co, f_verts[2]->co, f_verts[3]->co);
- if ((angle_error = angle_v3v3(no1, no2)) > 0.05) {
- printf(" ERROR %.4f\n", angle_error);
- print_v3("0", f_verts[0]->co);
- print_v3("1", f_verts[1]->co);
- print_v3("2", f_verts[2]->co);
- print_v3("3", f_verts[3]->co);
-
- }
- }
- else {
- printf(" ** fount %d len face\n", f->len);
- }
-#endif
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) {
+ /* this flag gets copied so we can be sure duplicate edges get it too (important) */
+ BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
- f2 = remake_face(bm, etags, f, f_verts, edges_tmp);
- if (f2) {
- BMO_elem_flag_enable(bm, f, FACE_DEL);
- BMO_elem_flag_enable(bm, f2, FACE_NEW);
+ bmesh_edge_separate(bm, e, e->l);
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
}
- /* else { ... should we raise an error here, or an assert? - campbell */
}
-
- /* remake_face() sets invalid indices,
- * likely these will be corrected on operator exit anyway */
- bm->elem_index_dirty &= ~BM_EDGE;
-
- /* cant call the operator because 'tag_out_edges'
- * relies on original index values, from before editing geometry */
-#if 0
- BMO_op_callf(bm, "del geom=%ff context=%i", FACE_DEL, DEL_ONLYFACES);
-#else
- BMO_remove_tagged_context(bm, FACE_DEL, DEL_ONLYFACES);
-#endif
-
- /* test EDGE_MARK'd edges if we need to delete them, EDGE_MARK
- * is set in remake_face */
- BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
- if (BMO_elem_flag_test(bm, e, EDGE_MARK)) {
- if (!e->l) {
- BMO_elem_flag_enable(bm, e, EDGE_DEL);
+ BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
+ if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) {
+ if (BM_elem_flag_test(e->v1, BM_ELEM_TAG)) {
+ BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
+ bmesh_vert_separate(bm, e->v1, NULL, NULL);
+ }
+ if (BM_elem_flag_test(e->v2, BM_ELEM_TAG)) {
+ BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
+ bmesh_vert_separate(bm, e->v2, NULL, NULL);
}
}
}
-#if 0
- BMO_op_callf(bm, "del geom=%fe context=%i", EDGE_DEL, DEL_EDGES);
-#else
- BMO_remove_tagged_context(bm, EDGE_DEL, DEL_EDGES);
-#endif
-
- tag_out_edges(bm, etags, op);
- BMO_slot_buffer_from_flag(bm, op, "edgeout1", EDGE_RET1, BM_EDGE);
- BMO_slot_buffer_from_flag(bm, op, "edgeout2", EDGE_RET2, BM_EDGE);
-
- BLI_array_free(f_verts);
- BLI_array_free(edges_tmp);
- if (etags) MEM_freeN(etags);
+ BMO_slot_buffer_from_hflag(bm, op, "edgeout", BM_ELEM_INTERNAL_TAG, BM_EDGE);
}
diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c
index 924e1fbf339..022e94e8209 100644
--- a/source/blender/editors/mesh/bmesh_tools.c
+++ b/source/blender/editors/mesh/bmesh_tools.c
@@ -2325,17 +2325,11 @@ static float mesh_rip_edgedist(ARegion *ar, float mat[][4], float *co1, float *c
return dist_to_line_segment_v2(mvalf, vec1, vec2);
}
-/* #define USE_BVH_VISIBILITY */
-
/* based on mouse cursor position, it defines how is being ripped */
static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
Object *obedit = CTX_data_edit_object(C);
ARegion *ar = CTX_wm_region(C);
-#ifdef USE_BVH_VISIBILITY
- BMBVHTree *bvhtree;
- View3D *v3d = CTX_wm_view3d(C);
-#endif
RegionView3D *rv3d = CTX_wm_region_view3d(C);
BMEditMesh *em = BMEdit_FromObject(obedit);
BMesh *bm = em->bm;
@@ -2345,9 +2339,10 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
BMLoop *l;
BMEdge *e, *e2;
BMVert *v, *ripvert = NULL;
- int side = 0, i, singlesel = FALSE;
+ int i, singlesel = FALSE;
float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
- float dist = FLT_MAX, d;
+ float dist = FLT_MAX;
+ float d, d_a, d_b;
/* note on selection:
* When calling edge split we operate on tagged edges rather then selected
@@ -2465,44 +2460,47 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
bvhtree = BMBVH_NewBVH(em, 0, NULL, NULL);
#endif
- for (i = 0; i < 2; i++) {
- BMO_ITER(e, &siter, bm, &bmop, i ? "edgeout2":"edgeout1", BM_EDGE) {
- float cent[3] = {0, 0, 0}, mid[3];
- float vec[3];
- float fmval_tweak[3];
- BMVert *v1_other;
- BMVert *v2_other;
+ BMO_ITER(e, &siter, bm, &bmop, "edgeout", BM_EDGE) {
+ float cent[3] = {0, 0, 0}, mid[3];
+ float vec[3];
+ float fmval_tweak[3];
+ BMVert *v1_other;
+ BMVert *v2_other;
#ifdef USE_BVH_VISIBILITY
- if (!BMBVH_EdgeVisible(bvhtree, e, ar, v3d, obedit) || !e->l)
- continue;
+ if (!BMBVH_EdgeVisible(bvhtree, e, ar, v3d, obedit) || !e->l)
+ continue;
#endif
- /* method for calculating distance:
- *
- * for each edge: calculate face center, then made a vector
- * from edge midpoint to face center. offset edge midpoint
- * by a small amount along this vector. */
-
- /* rather then the face center, get the middle of
- * both edge verts connected to this one */
- v1_other = BM_face_other_vert_loop(e->l->f, e->v2, e->v1)->v;
- v2_other = BM_face_other_vert_loop(e->l->f, e->v1, e->v2)->v;
- mid_v3_v3v3(cent, v1_other->co, v2_other->co);
- mid_v3_v3v3(mid, e->v1->co, e->v2->co);
- sub_v3_v3v3(vec, cent, mid);
- normalize_v3(vec);
- mul_v3_fl(vec, 0.01f);
+ /* method for calculating distance:
+ *
+ * for each edge: calculate face center, then made a vector
+ * from edge midpoint to face center. offset edge midpoint
+ * by a small amount along this vector. */
- /* ratrher then adding to both verts, subtract from the mouse */
- sub_v2_v2v2(fmval_tweak, fmval, vec);
+ /* rather then the face center, get the middle of
+ * both edge verts connected to this one */
+ v1_other = BM_face_other_vert_loop(e->l->f, e->v2, e->v1)->v;
+ v2_other = BM_face_other_vert_loop(e->l->f, e->v1, e->v2)->v;
+ mid_v3_v3v3(cent, v1_other->co, v2_other->co);
+ mid_v3_v3v3(mid, e->v1->co, e->v2->co);
- d = mesh_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, fmval_tweak);
+ ED_view3d_project_float_v2(ar, cent, cent, projectMat);
+ ED_view3d_project_float_v2(ar, mid, mid, projectMat);
- if (d < dist) {
- side = i;
- dist = d;
- }
+ sub_v2_v2v2(vec, cent, mid);
+ normalize_v2(vec);
+ mul_v2_fl(vec, 0.1f);
+
+
+ /* ratrher then adding to both verts, subtract from the mouse */
+ sub_v2_v2v2(fmval_tweak, fmval, vec);
+
+ d_a = mesh_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, fmval_tweak);
+ d_b = mesh_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, fmval);
+
+ if (d_a > d_b) {
+ BM_elem_select_set(bm, e, FALSE);
}
}
@@ -2553,11 +2551,6 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
BM_elem_select_set(bm, v_best, TRUE);
}
#endif
-
- }
- else {
- /* de-select one of the sides */
- BMO_slot_buffer_hflag_disable(bm, &bmop, side ? "edgeout1" : "edgeout2", BM_ELEM_SELECT, BM_EDGE, TRUE);
}
EDBM_selectmode_flush(em);