[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [45796] trunk/blender/source/blender: bmesh: improve rip tool

Campbell Barton ideasman42 at gmail.com
Thu Apr 19 23:47:33 CEST 2012


Revision: 45796
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=45796
Author:   campbellbarton
Date:     2012-04-19 21:47:32 +0000 (Thu, 19 Apr 2012)
Log Message:
-----------
bmesh: improve rip tool
- When the rip extends into a fan, pick the opposite edge in the fan (rather then 2 along)
- When stepping over the fan to find the rip edge, walk in the direction closest to the mouse (generally works nicer) 

Modified Paths:
--------------
    trunk/blender/source/blender/bmesh/intern/bmesh_core.c
    trunk/blender/source/blender/bmesh/intern/bmesh_queries.c
    trunk/blender/source/blender/bmesh/intern/bmesh_queries.h
    trunk/blender/source/blender/editors/mesh/editmesh_rip.c

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_core.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_core.c	2012-04-19 21:14:11 UTC (rev 45795)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_core.c	2012-04-19 21:47:32 UTC (rev 45796)
@@ -814,8 +814,7 @@
 
 	do {
 		i += BM_ELEM_API_FLAG_TEST(e, flag) ? 1 : 0;
-		e = bmesh_disk_edge_next(e, v);
-	} while (e != v->e);
+	} while ((e = bmesh_disk_edge_next(e, v)) != v->e);
 
 	return i;
 }

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_queries.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_queries.c	2012-04-19 21:14:11 UTC (rev 45795)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_queries.c	2012-04-19 21:47:32 UTC (rev 45796)
@@ -309,6 +309,59 @@
 }
 
 /**
+ * The function takes a vertex at the center of a fan and returns the opposite edge in the fan.
+ * All edges in the fan must be manifold, otherwise return NULL.
+ *
+ * \note This could (probably) be done more effieiently.
+ */
+BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
+{
+	BMLoop *l_a;
+	int tot = 0;
+	int i;
+
+	BLI_assert(BM_vert_in_edge(e_first, v));
+
+	l_a = e_first->l;
+	do {
+		l_a = BM_loop_other_vert_loop(l_a, v);
+		l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
+		if (BM_edge_is_manifold(l_a->e)) {
+			l_a = l_a->radial_next;
+		}
+		else {
+			return NULL;
+		}
+
+		tot++;
+	} while (l_a != e_first->l);
+
+	/* we know the total, now loop half way */
+	tot /= 2;
+	i = 0;
+
+	l_a = e_first->l;
+	do {
+		if (i == tot) {
+			l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
+			return l_a->e;
+		}
+
+		l_a = BM_loop_other_vert_loop(l_a, v);
+		l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
+		if (BM_edge_is_manifold(l_a->e)) {
+			l_a = l_a->radial_next;
+		}
+		/* this wont have changed from the previous loop */
+
+
+		i++;
+	} while (l_a != e_first->l);
+
+	return NULL;
+}
+
+/**
  * Returms edge length
  */
 float BM_edge_length_calc(BMEdge *e)

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_queries.h
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_queries.h	2012-04-19 21:14:11 UTC (rev 45795)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_queries.h	2012-04-19 21:47:32 UTC (rev 45796)
@@ -49,6 +49,7 @@
 int     BM_vert_edge_count(BMVert *v);
 int     BM_edge_face_count(BMEdge *e);
 int     BM_vert_face_count(BMVert *v);
+BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e);
 
 int     BM_vert_is_wire(BMVert *v);
 int     BM_edge_is_wire(BMEdge *e);

Modified: trunk/blender/source/blender/editors/mesh/editmesh_rip.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_rip.c	2012-04-19 21:14:11 UTC (rev 45795)
+++ trunk/blender/source/blender/editors/mesh/editmesh_rip.c	2012-04-19 21:47:32 UTC (rev 45796)
@@ -66,7 +66,7 @@
 	return dist_to_line_segment_v2(mvalf, vec1, vec2);
 }
 
-static float edbm_rip_edge_side_measure(BMEdge *e,
+static float edbm_rip_edge_side_measure(BMEdge *e, BMLoop *e_l,
                                         ARegion *ar,
                                         float projectMat[4][4], const float fmval[2])
 {
@@ -80,6 +80,8 @@
 	BMVert *v1_other;
 	BMVert *v2_other;
 
+	BLI_assert(BM_vert_in_edge(e, e_l->v));
+
 	/* method for calculating distance:
 	 *
 	 * for each edge: calculate face center, then made a vector
@@ -88,8 +90,8 @@
 
 	/* 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;
+	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);
 
@@ -323,12 +325,12 @@
 		e = lp->l_a->e;
 		v_prev = edbm_ripsel_edloop_pair_start_vert(e);
 		for (; e; e = edbm_ripsel_edge_uid_step(e, &v_prev)) {
-			score_a += edbm_rip_edge_side_measure(e, ar, projectMat, fmval);
+			score_a += edbm_rip_edge_side_measure(e, e->l, ar, projectMat, fmval);
 		}
 		e = lp->l_b->e;
 		v_prev = edbm_ripsel_edloop_pair_start_vert(e);
 		for (; e; e = edbm_ripsel_edge_uid_step(e, &v_prev)) {
-			score_b += edbm_rip_edge_side_measure(e, ar, projectMat, fmval);
+			score_b += edbm_rip_edge_side_measure(e, e->l, ar, projectMat, fmval);
 		}
 
 		e = (score_a > score_b) ? lp->l_a->e : lp->l_b->e;
@@ -538,27 +540,60 @@
 		dist = FLT_MAX;
 	}
 	else {
+		int totedge;
+		int all_minifold;
 		/* expand edge selection */
 		BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
 			e2 = NULL;
 			i = 0;
+			totedge = 0;
+			all_minifold = TRUE;
 			BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
-				/* important to check selection rather then tag here
-				 * else we get feedback loop */
-				if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
-					e2 = e;
-					i++;
+
+				if (!BM_edge_is_wire(e) &&
+				    !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
+				{
+					/* important to check selection rather then tag here
+					 * else we get feedback loop */
+					if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+						e2 = e;
+						i++;
+					}
+					totedge++;
 				}
+
+				/** #BM_vert_other_disk_edge has no hidden checks so don't check hidden here */
+				if ((all_minifold == TRUE) && (BM_edge_is_manifold(e) == FALSE)) {
+					all_minifold = FALSE;
+				}
 			}
 			
+			/* single edge, extend */
 			if (i == 1 && e2->l) {
-				l = BM_face_other_edge_loop(e2->l->f, e2, v);
-				l = l->radial_next;
-				l = BM_face_other_edge_loop(l->f, l->e, v);
+				if ((totedge == 4) || (all_minifold == FALSE)) {
+					BMLoop *l_a = e2->l;
+					BMLoop *l_b = l_a->radial_next;
 
-				if (l) {
-					BM_elem_flag_enable(l->e, BM_ELEM_TAG);
+					/* find the best face to follow, this wat the edge won't point away from
+					 * the mouse when there are more then 4 (takes the shortest face fan around) */
+					l = (edbm_rip_edge_side_measure(e2, l_a, ar, projectMat, fmval) <
+					     edbm_rip_edge_side_measure(e2, l_b, ar, projectMat, fmval)) ? l_a : l_b;
+
+					l = BM_face_other_edge_loop(l->f, e2, v);
+					l = l->radial_next;
+					l = BM_face_other_edge_loop(l->f, l->e, v);
+
+					if (l) {
+						BM_elem_flag_enable(l->e, BM_ELEM_TAG);
+					}
 				}
+				else {
+					e = BM_vert_other_disk_edge(v, e2);
+
+					if (e) {
+						BM_elem_flag_enable(e, BM_ELEM_TAG);
+					}
+				}
 			}
 		}
 	}




More information about the Bf-blender-cvs mailing list