From db0e2e7347db73786b38c0cbace60741ddd28b7e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 15 Dec 2014 14:17:28 +0100 Subject: Fix T42864 (partial): knife-project included uncut backfaces When knife-project ran with cut-through disabled, it would still try to select faces behind the cut. Now check if the faces are obscured. --- source/blender/editors/mesh/editmesh_knife.c | 78 +++++++++++++--------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index c94e4ca2c95..c2aafba9249 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -3168,16 +3168,14 @@ void MESH_OT_knife_tool(wmOperatorType *ot) * tessellation here seems way overkill, * but without this its very hard to know of a point is inside the face */ -static void edvm_mesh_knife_face_point(BMFace *f, float r_cent[3]) +static void edbm_mesh_knife_face_point(BMFace *f, float r_cent[3]) { const int tottri = f->len - 2; BMLoop **loops = BLI_array_alloca(loops, f->len); unsigned int (*index)[3] = BLI_array_alloca(index, tottri); int j; - - const float *best_co[3] = {NULL}; - float best_area = -1.0f; - bool ok = false; + int j_best = 0; /* use as fallback when unset */ + float area_best = -1.0f; BM_face_calc_tessellation(f, loops, index); @@ -3190,49 +3188,34 @@ static void edvm_mesh_knife_face_point(BMFace *f, float r_cent[3]) float cross[3]; cross_v3_v3v3(cross, p2, p3); area = fabsf(dot_v3v3(p1, cross)); - if (area > best_area) { - best_co[0] = p1; - best_co[1] = p2; - best_co[2] = p3; - best_area = area; - ok = true; + if (area > area_best) { + j_best = j; + area_best = area; } } - if (ok) { - mid_v3_v3v3v3(r_cent, best_co[0], best_co[1], best_co[2]); - } - else { - mid_v3_v3v3v3(r_cent, loops[0]->v->co, loops[1]->v->co, loops[2]->v->co); - } + mid_v3_v3v3v3( + r_cent, + loops[index[j_best][0]]->v->co, + loops[index[j_best][1]]->v->co, + loops[index[j_best][2]]->v->co); } -static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f, float projmat[4][4]) +static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2]) { - float cent_ss[2]; - float cent[3]; - - edvm_mesh_knife_face_point(f, cent); - - ED_view3d_project_float_v2_m4(ar, cent, cent_ss, projmat); - - /* check */ - { - LinkNode *p = polys; - int isect = 0; - - while (p) { - const float (*mval_fl)[2] = p->link; - const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl); - isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false); - p = p->next; - } + LinkNode *p = polys; + int isect = 0; - if (isect % 2) { - return true; - } + while (p) { + const float (*mval_fl)[2] = p->link; + const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl); + isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false); + p = p->next; } + if (isect % 2) { + return true; + } return false; } @@ -3242,6 +3225,7 @@ static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f, void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_through) { KnifeTool_OpData *kcd; + bglMats mats; view3d_operator_needs_opengl(C); @@ -3260,6 +3244,10 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug if (use_tag) { BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false); } + + if (kcd->cut_through == false) { + bgl_get_mats(&mats); + } } /* execute */ @@ -3324,7 +3312,10 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug BMFace *f; BMIter fiter; BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { - if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) { + float cent[3], cent_ss[2]; + edbm_mesh_knife_face_point(f, cent); + knife_project_v2(kcd, cent, cent_ss); + if (edbm_mesh_knife_point_isect(polys, cent_ss)) { BM_elem_flag_enable(f, BM_ELEM_TAG); } } @@ -3357,7 +3348,12 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug } while ((l_iter = l_iter->next) != l_first && (found == false)); if (found) { - if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) { + float cent[3], cent_ss[2]; + edbm_mesh_knife_face_point(f, cent); + knife_project_v2(kcd, cent, cent_ss); + if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, &mats)) && + edbm_mesh_knife_point_isect(polys, cent_ss)) + { BM_elem_flag_enable(f, BM_ELEM_TAG); keep_search = true; } -- cgit v1.2.3