- simplify rip code not to expand/contract selection.

- disable BVH edge visibility test (ifdef'd out. dont think its really needed)
This commit is contained in:
Campbell Barton
2012-03-07 00:08:00 +00:00
parent bf9de9d934
commit 400a0297b0
3 changed files with 73 additions and 79 deletions

View File

@@ -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);
}

View File

@@ -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)
}
}
}
#ifdef USE_BVH_VISIBILITY
BMBVH_FreeBVH(bvhtree);
#endif
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));
}
/* 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;

View File

@@ -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 */