From 400a0297b0b10dbed6a4f5fe8fddd9cdc58914af Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 7 Mar 2012 00:08:00 +0000 Subject: - simplify rip code not to expand/contract selection. - disable BVH edge visibility test (ifdef'd out. dont think its really needed) --- source/blender/bmesh/intern/bmesh_polygon.c | 41 +++++------ source/blender/editors/mesh/bmesh_tools.c | 90 ++++++++++++------------ source/blender/render/intern/include/rayobject.h | 21 +++--- 3 files changed, 73 insertions(+), 79 deletions(-) (limited to 'source') diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index bb2740e8115..09ca1024ce2 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -220,39 +220,39 @@ float BM_face_area_calc(BMesh *bm, BMFace *f) /** * computes center of face in 3d. uses center of bounding box. */ -void BM_face_center_bounds_calc(BMesh *bm, BMFace *f, float r_cent[3]) +void BM_face_center_bounds_calc(BMesh *UNUSED(bm), BMFace *f, float r_cent[3]) { - BMIter iter; - BMLoop *l; + BMLoop *l_iter; + BMLoop *l_first; float min[3], max[3]; - int i; INIT_MINMAX(min, max); - l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, f); - for (i = 0; l; l = BM_iter_step(&iter), i++) { - DO_MINMAX(l->v->co, min, max); - } + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + DO_MINMAX(l_iter->v->co, min, max); + } while ((l_iter = l_iter->next) != l_first); mid_v3_v3v3(r_cent, min, max); } /** - * computes the centroid of a face, using the mean average + * computes the center of a face, using the mean average */ -void BM_face_center_mean_calc(BMesh *bm, BMFace *f, float r_cent[3]) +void BM_face_center_mean_calc(BMesh *UNUSED(bm), BMFace *f, float r_cent[3]) { - BMIter iter; - BMLoop *l; - int i; + BMLoop *l_iter; + BMLoop *l_first; zero_v3(r_cent); - l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, f); - for (i = 0; l; l = BM_iter_step(&iter), i++) { - add_v3_v3(r_cent, l->v->co); - } + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + add_v3_v3(r_cent, l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); - if (f->len) mul_v3_fl(r_cent, 1.0f / (float)f->len); + if (f->len) + mul_v3_fl(r_cent, 1.0f / (float) f->len); } /** @@ -291,11 +291,6 @@ void compute_poly_plane(float (*verts)[3], int nverts) avgn[2] = 1.0f; } else { - /* XXX, why is this being divided and _then_ normalized - * division could be removed? - campbell */ - avgn[0] /= nverts; - avgn[1] /= nverts; - avgn[2] /= nverts; normalize_v3(avgn); } diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c index 559ad4d4ce2..d02fc5f51d5 100644 --- a/source/blender/editors/mesh/bmesh_tools.c +++ b/source/blender/editors/mesh/bmesh_tools.c @@ -2327,26 +2327,40 @@ 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; BMOperator bmop; - BMBVHTree *bvhtree; BMOIter siter; - BMIter iter, eiter, liter; + BMIter iter, eiter; BMLoop *l; BMEdge *e, *e2, *closest = NULL; BMVert *v, *ripvert = NULL; - int side = 0, i, singlesel = 0; + int side = 0, i, singlesel = FALSE; float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]}; float dist = FLT_MAX, d; + /* note on selection: + * When calling edge split we operate on tagged edges rather then selected + * this is important because the edges to operate on are extended by one, + * but the selection is left alone. + * + * After calling edge split - the duplicated edges have the same selection state as the + * original, so all we do is de-select the far side from the mouse and we have a + * useful selection for grabbing. + */ + ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat); /* BM_ELEM_SELECT --> BM_ELEM_TAG */ @@ -2358,12 +2372,18 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) * closest edge around that vert to mouse cursor, * then rip two adjacent edges in the vert fan. */ if (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0) { - singlesel = 1; + BMEditSelection ese; + singlesel = TRUE; - /* find selected vert */ - BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) - break; + /* find selected vert - same some time and check history first */ + if (EDBM_get_actSelection(em, &ese) && ese.htype == BM_VERT) { + v = (BMVert *)ese.ele; + } + else { + BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) + break; + } } /* this should be impossible, but sanity checks are a good thing */ @@ -2402,12 +2422,10 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) l = e2->l; e = BM_face_other_edge_loop(l->f, e2, v)->e; BM_elem_flag_enable(e, BM_ELEM_TAG); - BM_elem_select_set(bm, e, TRUE); l = e2->l->radial_next; e = BM_face_other_edge_loop(l->f, e2, v)->e; BM_elem_flag_enable(e, BM_ELEM_TAG); - BM_elem_select_set(bm, e, TRUE); } dist = FLT_MAX; @@ -2418,7 +2436,9 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) e2 = NULL; i = 0; BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) { - if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + /* 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++; } @@ -2430,37 +2450,38 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) l = BM_face_other_edge_loop(l->f, l->e, v); if (l) { - BM_elem_select_set(bm, l->e, TRUE); + BM_elem_flag_enable(l->e, BM_ELEM_TAG); } } } } - if (!EDBM_InitOpf(em, &bmop, op, "edgesplit edges=%he", BM_ELEM_SELECT)) { + if (!EDBM_InitOpf(em, &bmop, op, "edgesplit edges=%he", BM_ELEM_TAG)) { return OPERATOR_CANCELLED; } BMO_op_exec(bm, &bmop); +#ifdef USE_BVH_VISIBILITY /* build bvh tree for edge visibility tests */ 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], vec[3]; +#ifdef USE_BVH_VISIBILITY 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. */ - BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, e->l->f) { - add_v3_v3(cent, l->v->co); - } - mul_v3_fl(cent, 1.0f/(float)e->l->f->len); + BM_face_center_mean_calc(bm, e->l->f, cent); mid_v3_v3v3(mid, e->v1->co, e->v2->co); sub_v3_v3v3(vec, cent, mid); @@ -2468,7 +2489,7 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) mul_v3_fl(vec, 0.01f); add_v3_v3v3(mid, mid, vec); - /* yay we have our comparison point, now project it */ + /* We have our comparison point, now project it */ ED_view3d_project_float(ar, mid, mid, projectMat); d = len_squared_v2v2(fmval, mid); @@ -2480,34 +2501,13 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) } } } - - BMBVH_FreeBVH(bvhtree); - - EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(bm, &bmop, side?"edgeout2":"edgeout1", BM_ELEM_SELECT, BM_EDGE, TRUE); - BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) { - BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT)); - } +#ifdef USE_BVH_VISIBILITY + BMBVH_FreeBVH(bvhtree); +#endif - /* constrict edge selection again */ - BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) { - e2 = NULL; - i = 0; - BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) { - if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - e2 = e; - i++; - } - } - - if (i == 1) { - if (singlesel) - BM_elem_select_set(bm, v, FALSE); - else - BM_elem_select_set(bm, e2, FALSE); - } - } + /* de-select one of the sides */ + BMO_slot_buffer_hflag_disable(bm, &bmop, side ? "edgeout1" : "edgeout2", BM_ELEM_SELECT, BM_EDGE, TRUE); if (ripvert) { BM_elem_select_set(bm, ripvert, TRUE); @@ -2962,7 +2962,7 @@ static float bm_edge_seg_isect(BMEdge *e, CutCurve *c, int len, char mode, } } - /* now check for edge interesect (may produce vertex intersection as well)*/ + /* now check for edge intersect (may produce vertex intersection as well) */ for (i = 0; i < len; i++) { if (i > 0) { x11 = x12; diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index c43712ab95e..ce20ce4ea46 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -43,11 +43,10 @@ struct RayHint; struct VlakRen; /* RayObject - - Can be a face/triangle, bvh tree, object instance, etc. This is the - public API used by the renderer, see rayobject_internal.h for the - internal implementation details. */ - + * Can be a face/triangle, bvh tree, object instance, etc. This is the + * public API used by the renderer, see rayobject_internal.h for the + * internal implementation details. + * */ typedef struct RayObject RayObject; /* Intersection, see rayintersection.h */ @@ -74,8 +73,8 @@ void RE_rayobject_free(RayObject *r); void RE_rayobject_set_control(RayObject *r, void *data, int (*test_break)(void *data)); /* RayObject representing faces, all data is locally available instead - of referring to some external data structure, for possibly faster - intersection tests. */ + * of referring to some external data structure, for possibly faster + * intersection tests. */ typedef struct RayFace { float v1[4], v2[4], v3[4], v4[3]; @@ -89,8 +88,8 @@ typedef struct RayFace { RayObject* RE_rayface_from_vlak(RayFace *face, struct ObjectInstanceRen *obi, struct VlakRen *vlr); /* RayObject representing faces directly from a given VlakRen structure. Thus - allowing to save memory, but making code triangle intersection dependent on - render structures. */ + * allowing to save memory, but making code triangle intersection dependent on + * render structures. */ typedef struct VlakPrimitive { struct ObjectInstanceRen *ob; @@ -104,10 +103,10 @@ RayObject* RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstance /* extend min/max coords so that the rayobject is inside them */ void RE_rayobject_merge_bb(RayObject *ob, float *min, float *max); -/* initializes an hint for optiming raycast where it is know that a ray will pass by the given BB often the origin point */ +/* initializes an hint for optimizing raycast where it is know that a ray will pass by the given BB often the origin point */ void RE_rayobject_hint_bb(RayObject *r, struct RayHint *hint, float *min, float *max); -/* initializes an hint for optiming raycast where it is know that a ray will be contained inside the given cone*/ +/* initializes an hint for optimizing raycast where it is know that a ray will be contained inside the given cone*/ /* void RE_rayobject_hint_cone(RayObject *r, struct RayHint *hint, float *); */ /* Internals */ -- cgit v1.2.3