Fix to knife: would sometimes miss cuts on non-planar faces.
Also, there was a needless loop through all three loops of a tesselation triangle, which all share the same original face. Also, made an early out for case where an edge cut had already been discovered on a Knife edge.
This commit is contained in:
@@ -1092,9 +1092,9 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
|
||||
BLI_array_declare(edges);
|
||||
BVHTreeOverlap *results, *result;
|
||||
BMLoop **ls;
|
||||
float cos[9], uv[3], lambda;
|
||||
float cos[9], lambda;
|
||||
unsigned int tot = 0;
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
/* for comparing distances, error of intersection depends on triangle scale.
|
||||
* need to scale down before squaring for accurate comparison */
|
||||
@@ -1112,105 +1112,107 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
|
||||
|
||||
for (i = 0; i < tot; i++, result++) {
|
||||
float p[3];
|
||||
BMLoop *l1;
|
||||
BMFace *hitf;
|
||||
ListBase *lst;
|
||||
Ref *ref;
|
||||
|
||||
ls = (BMLoop **)kcd->em->looptris[result->indexA];
|
||||
|
||||
for (j = 0; j < 3; j++) {
|
||||
BMLoop *l1 = ls[j];
|
||||
BMFace *hitf;
|
||||
ListBase *lst = knife_get_face_kedges(kcd, l1->f);
|
||||
Ref *ref;
|
||||
l1 = ls[0];
|
||||
lst = knife_get_face_kedges(kcd, l1->f);
|
||||
|
||||
for (ref = lst->first; ref; ref = ref->next) {
|
||||
KnifeEdge *kfe = ref->ref;
|
||||
for (ref = lst->first; ref; ref = ref->next) {
|
||||
KnifeEdge *kfe = ref->ref;
|
||||
|
||||
//if (kfe == kcd->cur.edge || kfe == kcd->prev.edge)
|
||||
// continue;
|
||||
if (BLI_smallhash_haskey(ehash, (intptr_t)kfe)) {
|
||||
continue; // We already found a hit on this knife edge
|
||||
}
|
||||
|
||||
if (isect_line_tri_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, uv)) {
|
||||
float no[3], view[3], sp[3];
|
||||
if (isect_line_tri_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, NULL)) {
|
||||
float no[3], view[3], sp[3];
|
||||
|
||||
interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda);
|
||||
interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda);
|
||||
|
||||
if (kcd->cur.vert && len_squared_v3v3(kcd->cur.vert->cageco, p) < depsilon_squared)
|
||||
continue;
|
||||
if (kcd->prev.vert && len_squared_v3v3(kcd->prev.vert->cageco, p) < depsilon_squared)
|
||||
continue;
|
||||
if (len_squared_v3v3(kcd->prev.cage, p) < depsilon_squared ||
|
||||
len_squared_v3v3(kcd->cur.cage, p) < depsilon_squared)
|
||||
{
|
||||
continue;
|
||||
if (kcd->cur.vert && len_squared_v3v3(kcd->cur.vert->cageco, p) < depsilon_squared)
|
||||
continue;
|
||||
if (kcd->prev.vert && len_squared_v3v3(kcd->prev.vert->cageco, p) < depsilon_squared)
|
||||
continue;
|
||||
if (len_squared_v3v3(kcd->prev.cage, p) < depsilon_squared ||
|
||||
len_squared_v3v3(kcd->cur.cage, p) < depsilon_squared)
|
||||
continue;
|
||||
|
||||
knife_project_v3(kcd, p, sp);
|
||||
view3d_unproject(mats, view, sp[0], sp[1], 0.0f);
|
||||
mul_m4_v3(kcd->ob->imat, view);
|
||||
|
||||
if (kcd->cut_through) {
|
||||
hitf = FALSE;
|
||||
} else {
|
||||
/* check if this point is visible in the viewport */
|
||||
float p1[3], lambda1;
|
||||
|
||||
/* if face isn't planer, p may be behind the current tesselated tri,
|
||||
so move it onto that and then a little towards eye */
|
||||
if (isect_line_tri_v3(p, view, ls[0]->v->co, ls[1]->v->co, ls[2]->v->co, &lambda1, NULL)) {
|
||||
interp_v3_v3v3(p1, p, view, lambda1);
|
||||
} else {
|
||||
copy_v3_v3(p1, p);
|
||||
}
|
||||
sub_v3_v3(view, p1);
|
||||
normalize_v3(view);
|
||||
|
||||
knife_project_v3(kcd, p, sp);
|
||||
view3d_unproject(mats, view, sp[0], sp[1], 0.0f);
|
||||
mul_m4_v3(kcd->ob->imat, view);
|
||||
copy_v3_v3(no, view);
|
||||
mul_v3_fl(no, 0.003);
|
||||
|
||||
if (kcd->cut_through) {
|
||||
hitf = FALSE;
|
||||
}
|
||||
else {
|
||||
/* check if this point is visible in the viewport */
|
||||
sub_v3_v3(view, p);
|
||||
normalize_v3(view);
|
||||
|
||||
copy_v3_v3(no, view);
|
||||
mul_v3_fl(no, 0.003);
|
||||
|
||||
/* go towards view a bit */
|
||||
add_v3_v3(p, no);
|
||||
|
||||
/* ray cast */
|
||||
hitf = BMBVH_RayCast(bmtree, p, no, NULL, NULL);
|
||||
}
|
||||
|
||||
/* ok, if visible add the new point */
|
||||
if (!hitf && !BLI_smallhash_haskey(ehash, (intptr_t)kfe)) {
|
||||
BMEdgeHit hit;
|
||||
/* go towards view a bit */
|
||||
add_v3_v3(p1, no);
|
||||
|
||||
if (len_squared_v3v3(p, kcd->cur.co) < depsilon_squared ||
|
||||
len_squared_v3v3(p, kcd->prev.co) < depsilon_squared)
|
||||
{
|
||||
continue;
|
||||
/* ray cast */
|
||||
hitf = BMBVH_RayCast(bmtree, p1, no, NULL, NULL);
|
||||
}
|
||||
|
||||
/* ok, if visible add the new point */
|
||||
if (!hitf && !BLI_smallhash_haskey(ehash, (intptr_t)kfe)) {
|
||||
BMEdgeHit hit;
|
||||
|
||||
if (len_squared_v3v3(p, kcd->cur.co) < depsilon_squared ||
|
||||
len_squared_v3v3(p, kcd->prev.co) < depsilon_squared)
|
||||
continue;
|
||||
|
||||
hit.kfe = kfe;
|
||||
hit.v = NULL;
|
||||
|
||||
knife_find_basef(kfe);
|
||||
hit.f = kfe->basef;
|
||||
hit.perc = len_v3v3(p, kfe->v1->cageco) / len_v3v3(kfe->v1->cageco, kfe->v2->cageco);
|
||||
copy_v3_v3(hit.cagehit, p);
|
||||
|
||||
interp_v3_v3v3(p, kfe->v1->co, kfe->v2->co, hit.perc);
|
||||
copy_v3_v3(hit.realhit, p);
|
||||
|
||||
/* BMESH_TODO: should also snap to vertices */
|
||||
if (kcd->snap_midpoints) {
|
||||
float perc = hit.perc;
|
||||
|
||||
/* select the closest from the edge endpoints or the midpoint */
|
||||
if (perc < 0.25f) {
|
||||
perc = 0.0f;
|
||||
} else if (perc < 0.75f) {
|
||||
perc = 0.5f;
|
||||
} else {
|
||||
perc = 1.0f;
|
||||
}
|
||||
|
||||
hit.kfe = kfe;
|
||||
hit.v = NULL;
|
||||
|
||||
knife_find_basef(kfe);
|
||||
hit.f = kfe->basef;
|
||||
hit.perc = len_v3v3(p, kfe->v1->cageco) / len_v3v3(kfe->v1->cageco, kfe->v2->cageco);
|
||||
copy_v3_v3(hit.cagehit, p);
|
||||
|
||||
interp_v3_v3v3(p, kfe->v1->co, kfe->v2->co, hit.perc);
|
||||
copy_v3_v3(hit.realhit, p);
|
||||
|
||||
/* BMESH_TODO: should also snap to vertices */
|
||||
if (kcd->snap_midpoints) {
|
||||
float perc = hit.perc;
|
||||
|
||||
/* select the closest from the edge endpoints or the midpoint */
|
||||
if (perc < 0.25f) {
|
||||
perc = 0.0f;
|
||||
}
|
||||
else if (perc < 0.75f) {
|
||||
perc = 0.5f;
|
||||
}
|
||||
else {
|
||||
perc = 1.0f;
|
||||
}
|
||||
|
||||
interp_v3_v3v3(hit.hit, kfe->v1->co, kfe->v2->co, perc);
|
||||
interp_v3_v3v3(hit.cagehit, kfe->v1->cageco, kfe->v2->cageco, perc);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(hit.hit, p);
|
||||
}
|
||||
knife_project_v3(kcd, hit.cagehit, hit.schit);
|
||||
|
||||
BLI_array_append(edges, hit);
|
||||
BLI_smallhash_insert(ehash, (intptr_t)kfe, NULL);
|
||||
interp_v3_v3v3(hit.hit, kfe->v1->co, kfe->v2->co, perc);
|
||||
interp_v3_v3v3(hit.cagehit, kfe->v1->cageco, kfe->v2->cageco, perc);
|
||||
} else {
|
||||
copy_v3_v3(hit.hit, p);
|
||||
}
|
||||
knife_project_v3(kcd, hit.cagehit, hit.schit);
|
||||
|
||||
BLI_array_append(edges, hit);
|
||||
BLI_smallhash_insert(ehash, (intptr_t)kfe, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user