bmesh knife tool:

- only cut selected geometry.
- exclude hidden geometry from snapping.
This commit is contained in:
Campbell Barton
2012-04-18 16:27:11 +00:00
parent 40e3ae6478
commit 486bf16af5
3 changed files with 68 additions and 7 deletions

View File

@@ -90,6 +90,7 @@ BMBVHTree *BMBVH_NewBVH(BMEditMesh *em, int flag, Scene *scene, Object *obedit)
SmallHash shash;
float cos[3][3], (*cagecos)[3] = NULL;
int i;
int tottri;
/* when initializing cage verts, we only want the first cage coordinate for each vertex,
* so that e.g. mirror or array use original vertex coordinates and not mirrored or duplicate */
@@ -104,7 +105,19 @@ BMBVHTree *BMBVH_NewBVH(BMEditMesh *em, int flag, Scene *scene, Object *obedit)
tree->epsilon = FLT_EPSILON * 2.0f;
tree->flag = flag;
tree->tree = BLI_bvhtree_new(em->tottri, tree->epsilon, 8, 8);
if (flag & BMBVH_RESPECT_HIDDEN) {
tottri = 0;
for (i = 0; i < em->tottri; i++) {
if (!BM_elem_flag_test(em->looptris[i][0]->f, BM_ELEM_HIDDEN)) {
tottri++;
}
}
}
else {
tottri = em->tottri;
}
tree->tree = BLI_bvhtree_new(tottri, tree->epsilon, 8, 8);
if (flag & BMBVH_USE_CAGE) {
BMIter iter;
@@ -132,6 +145,14 @@ BMBVHTree *BMBVH_NewBVH(BMEditMesh *em, int flag, Scene *scene, Object *obedit)
tree->cagecos = cagecos;
for (i = 0; i < em->tottri; i++) {
if (flag & BMBVH_RESPECT_HIDDEN) {
/* note, the arrays wont allign now! take care */
if (BM_elem_flag_test(em->looptris[i][0]->f, BM_ELEM_HIDDEN)) {
continue;
}
}
if (flag & BMBVH_USE_CAGE) {
copy_v3_v3(cos[0], cagecos[BM_elem_index_get(em->looptris[i][0]->v)]);
copy_v3_v3(cos[1], cagecos[BM_elem_index_get(em->looptris[i][1]->v)]);

View File

@@ -60,8 +60,11 @@ int BMBVH_EdgeVisible(struct BMBVHTree *tree, struct BMEdge *e,
/*find a vert closest to co in a sphere of radius maxdist*/
struct BMVert *BMBVH_FindClosestVert(struct BMBVHTree *tree, float *co, float maxdist);
/*BMBVH_NewBVH flag parameter*/
#define BMBVH_USE_CAGE 1 /*project geometry onto modifier cage */
#define BMBVH_RETURN_ORIG 2 /*use with BMBVH_USE_CAGE, returns hits in relation to original geometry*/
/* BMBVH_NewBVH flag parameter */
enum {
BMBVH_USE_CAGE = 1, /* project geometry onto modifier cage */
BMBVH_RETURN_ORIG = 2, /* use with BMBVH_USE_CAGE, returns hits in relation to original geometry */
BMBVH_RESPECT_HIDDEN = 4
};
#endif /* __EDITBMESH_BVH_H__ */

View File

@@ -67,6 +67,8 @@
#define KMAXDIST 10 /* max mouse distance from edge before not detecting it */
#define USE_SELECTED_ONLY
/* knifetool operator */
typedef struct KnifeVert {
BMVert *v; /* non-NULL if this is an original vert */
@@ -713,6 +715,15 @@ static void knife_add_cut(knifetool_opdata *kcd)
if (len_v3v3(kcd->cur.cage, lh->realhit) < FLT_EPSILON * 80)
continue;
#if 0 /* not working perfect, ignore for now */
#ifdef USE_SELECTED_ONLY
/* don't mess up logic by skipping too early */
if (lh->kfe->e && !BM_elem_flag_test(lh->kfe->e, BM_ELEM_SELECT)) {
continue;
}
#endif
#endif
if (kcd->prev.is_space) {
kcd->prev.is_space = 0;
copy_v3_v3(kcd->prev.co, lh->hit);
@@ -923,6 +934,13 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
lh = kcd->linehits;
for (i = 0; i < kcd->totlinehit; i++, lh++) {
float sv1[3], sv2[3];
int do_draw = TRUE;
#ifdef USE_SELECTED_ONLY
if (!BM_elem_flag_test(lh->f, BM_ELEM_SELECT)) {
do_draw = FALSE;
}
#endif
knife_project_v3(kcd, lh->kfe->v1->cageco, sv1);
knife_project_v3(kcd, lh->kfe->v2->cageco, sv2);
@@ -930,12 +948,12 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
if (len_v2v2(lh->schit, sv1) < kcd->vthresh / 4.0f) {
copy_v3_v3(lh->cagehit, lh->kfe->v1->cageco);
glVertex3fv(lh->cagehit);
if (do_draw) glVertex3fv(lh->cagehit);
lh->v = lh->kfe->v1;
}
else if (len_v2v2(lh->schit, sv2) < kcd->vthresh / 4.0f) {
copy_v3_v3(lh->cagehit, lh->kfe->v2->cageco);
glVertex3fv(lh->cagehit);
if (do_draw) glVertex3fv(lh->cagehit);
lh->v = lh->kfe->v2;
}
}
@@ -947,6 +965,13 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
glBegin(GL_POINTS);
lh = kcd->linehits;
for (i = 0; i < kcd->totlinehit; i++, lh++) {
#ifdef USE_SELECTED_ONLY
if (!BM_elem_flag_test(lh->f, BM_ELEM_SELECT)) {
continue;
}
#endif
glVertex3fv(lh->cagehit);
}
glEnd();
@@ -2588,6 +2613,12 @@ static void knife_make_cuts(knifetool_opdata *kcd)
for (lst = BLI_smallhash_iternew(ehash, &hiter, (uintptr_t *)&e); lst;
lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&e))
{
#ifdef USE_SELECTED_ONLY
if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
continue;
}
#endif
sort_by_frac_along(lst, e);
for (ref = lst->first; ref; ref = ref->next) {
kfv = ref->ref;
@@ -2600,6 +2631,12 @@ static void knife_make_cuts(knifetool_opdata *kcd)
for (lst = BLI_smallhash_iternew(fhash, &hiter, (uintptr_t *)&f); lst;
lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f))
{
#ifdef USE_SELECTED_ONLY
if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
continue;
}
#endif
knife_make_face_cuts(kcd, f, lst);
}
@@ -2733,7 +2770,7 @@ static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut))
cage->foreachMappedVert(cage, cage_mapped_verts_callback, data);
BLI_smallhash_release(&shash);
kcd->bmbvh = BMBVH_NewBVH(kcd->em, BMBVH_USE_CAGE | BMBVH_RETURN_ORIG, scene, obedit);
kcd->bmbvh = BMBVH_NewBVH(kcd->em, BMBVH_USE_CAGE | BMBVH_RETURN_ORIG | BMBVH_RESPECT_HIDDEN, scene, obedit);
kcd->arena = BLI_memarena_new(1 << 15, "knife");
kcd->vthresh = KMAXDIST - 1;
kcd->ethresh = KMAXDIST;