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
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2014-05-20 07:51:22 +0400
committerCampbell Barton <ideasman42@gmail.com>2014-05-20 07:53:52 +0400
commit71c11dbb02e3f41ae5c1e3c965fae0ce89ae4898 (patch)
tree4f794bbac8ee0a53ae82df4474b13aadb89780e5 /source
parentba1acec6bcb82fe1c744de43e5ea3b927819fc00 (diff)
Fix T40252: Knife snapping ignores axis-constraint
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c87
1 files changed, 63 insertions, 24 deletions
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 2ef68b27358..0c84199f2c4 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -208,6 +208,9 @@ typedef struct KnifeTool_OpData {
bool ignore_edge_snapping;
bool ignore_vert_snapping;
+ /* use to check if we're currently dragging an angle snapped line */
+ bool is_angle_snapping;
+
enum {
ANGLE_FREE,
ANGLE_0,
@@ -1606,6 +1609,7 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo
if (f) {
const float maxdist_sq = maxdist * maxdist;
KnifeEdge *cure = NULL;
+ float cur_cagep[3];
ListBase *lst;
Ref *ref;
float dis_sq, curdis_sq = FLT_MAX;
@@ -1616,29 +1620,56 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo
lst = knife_get_face_kedges(kcd, f);
for (ref = lst->first; ref; ref = ref->next) {
KnifeEdge *kfe = ref->ref;
+ float test_cagep[3];
+ float lambda;
/* project edge vertices into screen space */
knife_project_v2(kcd, kfe->v1->cageco, kfe->v1->sco);
knife_project_v2(kcd, kfe->v2->cageco, kfe->v2->sco);
- dis_sq = dist_squared_to_line_segment_v2(sco, kfe->v1->sco, kfe->v2->sco);
- if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
- if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
- float lambda = line_point_factor_v2(sco, kfe->v1->sco, kfe->v2->sco);
- float vec[3];
+ /* check if we're close enough and calculate 'lambda' */
+ if (kcd->is_angle_snapping) {
+ /* if snapping, check we're in bounds */
+ float sco_snap[2];
+ isect_line_line_v2_point(kfe->v1->sco, kfe->v2->sco, kcd->prev.mval, kcd->curr.mval, sco_snap);
+ lambda = line_point_factor_v2(sco_snap, kfe->v1->sco, kfe->v2->sco);
- interp_v3_v3v3(vec, kfe->v1->cageco, kfe->v2->cageco, lambda);
+ /* be strict about angle-snapping within edge */
+ if ((lambda < 0.0f - KNIFE_FLT_EPSBIG) || (lambda > 1.0f + KNIFE_FLT_EPSBIG)) {
+ continue;
+ }
- if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, true) == 0) {
- cure = kfe;
- curdis_sq = dis_sq;
- }
+ dis_sq = len_squared_v2v2(sco, sco_snap);
+ if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
+ /* we already have 'lambda' */
+ }
+ else {
+ continue;
+ }
+ }
+ else {
+ dis_sq = dist_squared_to_line_segment_v2(sco, kfe->v1->sco, kfe->v2->sco);
+ if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
+ lambda = line_point_factor_v2(sco, kfe->v1->sco, kfe->v2->sco);
}
else {
- cure = kfe;
- curdis_sq = dis_sq;
+ continue;
+ }
+ }
+
+ /* now we have 'lambda' calculated */
+ interp_v3_v3v3(test_cagep, kfe->v1->cageco, kfe->v2->cageco, lambda);
+
+ if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
+ /* check we're in the view */
+ if (ED_view3d_clipping_test(kcd->vc.rv3d, test_cagep, true)) {
+ continue;
}
}
+
+ cure = kfe;
+ curdis_sq = dis_sq;
+ copy_v3_v3(cur_cagep, test_cagep);
}
if (fptr)
@@ -1653,11 +1684,9 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo
mid_v3_v3v3(cagep, cure->v1->cageco, cure->v2->cageco);
}
else {
- float d;
-
- closest_to_line_segment_v3(cagep, cageco, cure->v1->cageco, cure->v2->cageco);
- d = len_v3v3(cagep, cure->v1->cageco) / len_v3v3(cure->v1->cageco, cure->v2->cageco);
- interp_v3_v3v3(p, cure->v1->co, cure->v2->co, d);
+ float lambda = line_point_factor_v3(cur_cagep, cure->v1->cageco, cure->v2->cageco);
+ copy_v3_v3(cagep, cur_cagep);
+ interp_v3_v3v3(p, cure->v1->co, cure->v2->co, lambda);
}
/* update mouse coordinates to the snapped-to edge's screen coordinates
@@ -1717,6 +1746,13 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo
knife_project_v2(kcd, kfv->cageco, kfv->sco);
+ /* be strict about angle snapping, the vertex needs to be very close to the angle, or we ignore */
+ if (kcd->is_angle_snapping) {
+ if (dist_squared_to_line_segment_v2(kfv->sco, kcd->prev.mval, kcd->curr.mval) > KNIFE_FLT_EPSBIG) {
+ continue;
+ }
+ }
+
dis_sq = len_squared_v2v2(kfv->sco, sco);
if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
@@ -1764,7 +1800,7 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo
}
/* update both kcd->curr.mval and kcd->mval to snap to required angle */
-static void knife_snap_angle(KnifeTool_OpData *kcd)
+static bool knife_snap_angle(KnifeTool_OpData *kcd)
{
float dx, dy;
float w, abs_tan;
@@ -1772,7 +1808,7 @@ static void knife_snap_angle(KnifeTool_OpData *kcd)
dx = kcd->curr.mval[0] - kcd->prev.mval[0];
dy = kcd->curr.mval[1] - kcd->prev.mval[1];
if (dx == 0.0f && dy == 0.0f)
- return;
+ return false;
if (dx == 0.0f) {
kcd->angle_snapping = ANGLE_90;
@@ -1801,6 +1837,8 @@ static void knife_snap_angle(KnifeTool_OpData *kcd)
}
copy_v2_v2(kcd->mval, kcd->curr.mval);
+
+ return true;
}
/* update active knife edge/vert pointers */
@@ -1812,12 +1850,13 @@ static int knife_update_active(KnifeTool_OpData *kcd)
/* view matrix may have changed, reproject */
knife_project_v2(kcd, kcd->prev.co, kcd->prev.mval);
- if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING)
- knife_snap_angle(kcd);
+ if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING) {
+ kcd->is_angle_snapping = knife_snap_angle(kcd);
+ }
+ else {
+ kcd->is_angle_snapping = false;
+ }
- /* XXX knife_snap_angle updates the view coordinate mouse values to constrained angles,
- * which current mouse values are set to current mouse values are then used
- * for vertex and edge snap detection, without regard to the exact angle constraint */
kcd->curr.vert = knife_find_closest_vert(kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.bmface, &kcd->curr.is_space);
if (!kcd->curr.vert) {