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>2015-05-05 00:11:31 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-05-05 00:22:35 +0300
commit22bbd1c51219aafb40adb3e9a206f660a621fd70 (patch)
tree379fd0b62591041ada3e53bb8f287b3c4aba31e6 /source/blender/editors/mesh/editmesh_rip.c
parente59bd19fa75e65b794e4c67bdcfb8d13867900f9 (diff)
BMesh: improve rip tool /w mon-manifold verts
Can now rip from multiple fans (mixed single faces or larger regions) Also add BM_vert_is_manifold_region which only checks if a vert has disconnected fans.
Diffstat (limited to 'source/blender/editors/mesh/editmesh_rip.c')
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c106
1 files changed, 51 insertions, 55 deletions
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index abd88ae65aa..1e207a8edf8 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -532,14 +532,14 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BMesh *bm = em->bm;
BMIter iter, liter;
BMLoop *l;
- BMEdge *e, *e2;
+ BMEdge *e2;
BMVert *v;
const int totvert_orig = bm->totvert;
int i;
float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
float dist_sq = FLT_MAX;
float d;
- bool is_wire;
+ bool is_wire, is_manifold_region;
BMEditSelection ese;
int totboundary_edge = 0;
@@ -565,17 +565,19 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
}
is_wire = BM_vert_is_wire(v);
+ is_manifold_region = BM_vert_is_manifold_region(v);
e2 = NULL;
- if (v->e) {
+ {
+ BMEdge *e;
/* find closest edge to mouse cursor */
BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
/* consider wire as boundary for this purpose,
* otherwise we can't a face away from a wire edge */
totboundary_edge += (BM_edge_is_boundary(e) || BM_edge_is_wire(e));
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- if (BM_edge_is_manifold(e)) {
+ if ((is_manifold_region == false) || BM_edge_is_manifold(e)) {
d = edbm_rip_edgedist_squared(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT);
if ((e2 == NULL) || (d < dist_sq)) {
dist_sq = d;
@@ -584,67 +586,60 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
}
}
}
-
- /* if we are ripping a single vertex from 3 faces,
- * then measure the distance to the face corner as well as the edge */
- if (BM_vert_face_count_is_equal(v, 3) &&
- BM_vert_edge_count_is_equal(v, 3))
- {
- BMEdge *e_all[3];
- BMLoop *l_all[3];
- int i1, i2;
-
- BM_iter_as_array(bm, BM_EDGES_OF_VERT, v, (void **)e_all, 3);
- BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)l_all, 3);
-
- /* not do a loop similar to the one above, but test against loops */
- for (i1 = 0; i1 < 3; i1++) {
- /* consider wire as boundary for this purpose,
- * otherwise we can't a face away from a wire edge */
- float l_mid_co[3];
- l = l_all[i1];
- edbm_calc_loop_co(l, l_mid_co);
- d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT);
- if ((e2 == NULL) || (d < dist_sq)) {
- dist_sq = d;
-
- /* find the edge that is not in this loop */
- e2 = NULL;
- for (i2 = 0; i2 < 3; i2++) {
- if (!BM_edge_in_loop(e_all[i2], l)) {
- e2 = e_all[i2];
- break;
- }
- }
- BLI_assert(e2 != NULL);
- }
- }
- }
}
- if (e2) {
+ if (e2 && (is_manifold_region == false)) {
/* Try to split off a non-manifold fan (when we have multiple disconnected fans) */
-
- /* note: we're lazy here and first split then check there are any faces remaining,
- * this isn't good practice, however its less hassle then checking for multiple-disconnected regions */
BMLoop *l_sep = e2->l->v == v ? e2->l : e2->l->next;
BMVert *v_new;
+
BLI_assert(l_sep->v == v);
v_new = bmesh_urmv_loop_region(bm, l_sep);
- if (BM_vert_find_first_loop(v)) {
- BM_vert_select_set(bm, v, false);
- BM_select_history_remove(bm, v);
+ BLI_assert(BM_vert_find_first_loop(v));
- BM_vert_select_set(bm, v_new, true);
- if (ese.ele) {
- BM_select_history_store(bm, v_new);
- }
+ BM_vert_select_set(bm, v, false);
+ BM_select_history_remove(bm, v);
- return OPERATOR_FINISHED;
+ BM_vert_select_set(bm, v_new, true);
+ if (ese.ele) {
+ BM_select_history_store(bm, v_new);
}
- else {
- /* rewind */
- BM_vert_splice(bm, v, v_new);
+ return OPERATOR_FINISHED;
+ }
+
+ /* if we are ripping a single vertex from 3 faces,
+ * then measure the distance to the face corner as well as the edge */
+ if (BM_vert_face_count_is_equal(v, 3) &&
+ BM_vert_edge_count_is_equal(v, 3))
+ {
+ BMEdge *e_all[3];
+ BMLoop *l_all[3];
+ int i1, i2;
+
+ BM_iter_as_array(bm, BM_EDGES_OF_VERT, v, (void **)e_all, 3);
+ BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)l_all, 3);
+
+ /* not do a loop similar to the one above, but test against loops */
+ for (i1 = 0; i1 < 3; i1++) {
+ /* consider wire as boundary for this purpose,
+ * otherwise we can't a face away from a wire edge */
+ float l_mid_co[3];
+ l = l_all[i1];
+ edbm_calc_loop_co(l, l_mid_co);
+ d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT);
+ if ((e2 == NULL) || (d < dist_sq)) {
+ dist_sq = d;
+
+ /* find the edge that is not in this loop */
+ e2 = NULL;
+ for (i2 = 0; i2 < 3; i2++) {
+ if (!BM_edge_in_loop(e_all[i2], l)) {
+ e2 = e_all[i2];
+ break;
+ }
+ }
+ BLI_assert(e2 != NULL);
+ }
}
}
@@ -703,6 +698,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
}
}
else {
+ BMEdge *e;
/* a wire vert, find the best edge */
BM_ITER_ELEM (e, &iter, vout[i], BM_EDGES_OF_VERT) {
if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {