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:
authorCampbell Barton <ideasman42@gmail.com>2012-04-20 01:47:32 +0400
committerCampbell Barton <ideasman42@gmail.com>2012-04-20 01:47:32 +0400
commit741a177a74057b9baaae17640205017ca393ed89 (patch)
tree33cf96b86350248bcbd54df29d57f64510f12c52
parentebbfcd71e5ea35a64759ecbf9bc0f34d582a6bde (diff)
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)
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c3
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c53
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h1
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c65
4 files changed, 105 insertions, 17 deletions
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 76095728d5a..51ca11b0898 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -814,8 +814,7 @@ static int UNUSED_FUNCTION(count_flagged_disk)(BMVert *v, int flag)
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;
}
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 09cd6a2f96b..3561092b1cf 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -309,6 +309,59 @@ BMVert *BM_edge_other_vert(BMEdge *e, BMVert *v)
}
/**
+ * 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)
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index d69a57bdb40..5178311eea4 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -49,6 +49,7 @@ int BM_vert_edge_count_nonwire(BMVert *v);
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);
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 34666c2cb7a..3d310e5ea90 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -66,7 +66,7 @@ static float edbm_rip_rip_edgedist(ARegion *ar, float mat[][4], float *co1, floa
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 @@ static float edbm_rip_edge_side_measure(BMEdge *e,
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 @@ static float edbm_rip_edge_side_measure(BMEdge *e,
/* 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 @@ static void edbm_ripsel_deselect_helper(BMesh *bm, EdgeLoopPair *eloop_pairs,
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,26 +540,59 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, wmEvent *event)
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;
+
+ /* 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;
- if (l) {
- BM_elem_flag_enable(l->e, BM_ELEM_TAG);
+ 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);
+ }
}
}
}