Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c124
1 files changed, 76 insertions, 48 deletions
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 873bdf2a674..347f6806d13 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -1564,15 +1564,12 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
void **val_p;
float s[2], se1[2], se2[2], sint[2];
float r1[3], r2[3];
- float d, d1, d2, lambda;
+ float d1, d2, lambda;
float vert_tol, vert_tol_sq;
float line_tol, line_tol_sq;
float face_tol, face_tol_sq;
- int isect_kind;
uint tot;
int i;
- const bool use_hit_prev = true;
- const bool use_hit_curr = (kcd->is_drag_hold == false);
if (kcd->linehits) {
MEM_freeN(kcd->linehits);
@@ -1703,10 +1700,25 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
val_p = BLI_smallhash_iternext_p(&hiter, (uintptr_t *)&v)) {
KnifeEdge *kfe_hit = NULL;
- knife_project_v2(kcd, v->cageco, s);
- d = dist_squared_to_line_segment_v2(s, s1, s2);
- if ((d <= vert_tol_sq) &&
- (point_is_visible(kcd, v->cageco, s, bm_elem_from_knife_vert(v, &kfe_hit)))) {
+ bool kfv_is_in_cut = false;
+ if (ELEM(v, kcd->prev.vert, kcd->curr.vert)) {
+ /* This KnifeVert was captured by the snap system.
+ * Since the tolerance distance can be different, add this vertex directly.
+ * Otherwise, the cut may fail or a close cut on a connected edge can be performed. */
+ bm_elem_from_knife_vert(v, &kfe_hit);
+ copy_v2_v2(s, (v == kcd->prev.vert) ? kcd->prev.mval : kcd->curr.mval);
+ kfv_is_in_cut = true;
+ }
+ else {
+ knife_project_v2(kcd, v->cageco, s);
+ float d = dist_squared_to_line_segment_v2(s, s1, s2);
+ if ((d <= vert_tol_sq) &&
+ (point_is_visible(kcd, v->cageco, s, bm_elem_from_knife_vert(v, &kfe_hit)))) {
+ kfv_is_in_cut = true;
+ }
+ }
+
+ if (kfv_is_in_cut) {
memset(&hit, 0, sizeof(hit));
hit.v = v;
@@ -1724,7 +1736,9 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
BLI_array_append(linehits, hit);
}
else {
- /* note that these vertes aren't used */
+ /* This vertex isn't used so remove from `kfvs`.
+ * This is useful to detect KnifeEdges that can be skipped.
+ * And it optimizes smallhash_iternext a little bit. */
*val_p = NULL;
}
}
@@ -1732,30 +1746,38 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
/* now edge hits; don't add if a vertex at end of edge should have hit */
for (val = BLI_smallhash_iternew(&kfes, &hiter, (uintptr_t *)&kfe); val;
val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&kfe)) {
- int kfe_verts_in_cut;
- /* if we intersect both verts, don't attempt to intersect the edge */
-
- kfe_verts_in_cut = (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v1) != NULL) +
- (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v2) != NULL);
- if (kfe_verts_in_cut == 2) {
+ /* If we intersect any of the vertices, don't attempt to intersect the edge. */
+ if (BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v1) ||
+ BLI_smallhash_lookup(&kfvs, (intptr_t)kfe->v2)) {
continue;
}
knife_project_v2(kcd, kfe->v1->cageco, se1);
knife_project_v2(kcd, kfe->v2->cageco, se2);
- isect_kind = (kfe_verts_in_cut) ? -1 : isect_seg_seg_v2_point(s1, s2, se1, se2, sint);
- if (isect_kind == -1) {
- /* isect_seg_seg_v2_simple doesn't do tolerance test around ends of s1-s2 */
- closest_to_line_segment_v2(sint, s1, se1, se2);
- if (len_squared_v2v2(sint, s1) <= line_tol_sq) {
- isect_kind = 1;
- }
- else {
- closest_to_line_segment_v2(sint, s2, se1, se2);
- if (len_squared_v2v2(sint, s2) <= line_tol_sq) {
+ int isect_kind = 1;
+ if (kfe == kcd->prev.edge) {
+ /* This KnifeEdge was captured by the snap system. */
+ copy_v2_v2(sint, kcd->prev.mval);
+ }
+ else if (kfe == kcd->curr.edge) {
+ /* This KnifeEdge was captured by the snap system. */
+ copy_v2_v2(sint, kcd->curr.mval);
+ }
+ else {
+ isect_kind = isect_seg_seg_v2_point_ex(s1, s2, se1, se2, 0.0f, sint);
+ if (isect_kind == -1) {
+ /* isect_seg_seg_v2_point doesn't do tolerance test around ends of s1-s2 */
+ closest_to_line_segment_v2(sint, s1, se1, se2);
+ if (len_squared_v2v2(sint, s1) <= line_tol_sq) {
isect_kind = 1;
}
+ else {
+ closest_to_line_segment_v2(sint, s2, se1, se2);
+ if (len_squared_v2v2(sint, s2) <= line_tol_sq) {
+ isect_kind = 1;
+ }
+ }
}
}
if (isect_kind == 1) {
@@ -1790,32 +1812,38 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
}
}
}
+
/* now face hits; don't add if a vertex or edge in face should have hit */
- for (val = BLI_smallhash_iternew(&faces, &hiter, (uintptr_t *)&f); val;
- val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) {
- float p[3], p_cage[3];
-
- if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) {
- memset(&hit, 0, sizeof(hit));
- hit.f = f;
- copy_v3_v3(hit.hit, p);
- copy_v3_v3(hit.cagehit, p_cage);
- copy_v2_v2(hit.schit, s1);
- set_linehit_depth(kcd, &hit);
- BLI_array_append(linehits, hit);
+ const bool use_hit_prev = (kcd->prev.vert == NULL) && (kcd->prev.edge == NULL);
+ const bool use_hit_curr = (kcd->curr.vert == NULL) && (kcd->curr.edge == NULL) &&
+ !kcd->is_drag_hold;
+ if (use_hit_prev || use_hit_curr) {
+ for (val = BLI_smallhash_iternew(&faces, &hiter, (uintptr_t *)&f); val;
+ val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) {
+ float p[3], p_cage[3];
+
+ if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) {
+ if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) {
+ memset(&hit, 0, sizeof(hit));
+ hit.f = f;
+ copy_v3_v3(hit.hit, p);
+ copy_v3_v3(hit.cagehit, p_cage);
+ copy_v2_v2(hit.schit, s1);
+ set_linehit_depth(kcd, &hit);
+ BLI_array_append(linehits, hit);
+ }
}
- }
- if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) {
- memset(&hit, 0, sizeof(hit));
- hit.f = f;
- copy_v3_v3(hit.hit, p);
- copy_v3_v3(hit.cagehit, p_cage);
- copy_v2_v2(hit.schit, s2);
- set_linehit_depth(kcd, &hit);
- BLI_array_append(linehits, hit);
+ if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) {
+ if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) {
+ memset(&hit, 0, sizeof(hit));
+ hit.f = f;
+ copy_v3_v3(hit.hit, p);
+ copy_v3_v3(hit.cagehit, p_cage);
+ copy_v2_v2(hit.schit, s2);
+ set_linehit_depth(kcd, &hit);
+ BLI_array_append(linehits, hit);
+ }
}
}
}