diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-06-17 07:31:27 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-06-17 07:34:23 +0300 |
commit | 865bf8ecbc1cf3aac3107cbb70b2e94d8e239adc (patch) | |
tree | aa1a96c1d770cf16183fe6b598f93a899dd06474 /source/blender | |
parent | 57c9bc9bb0b4caedd850d0f6797d3d010217bd78 (diff) |
Manipulator: correct dial angle
Calculation was done in screen-space giving inaccuracy,
making the angle incorrect for tool code.
Cast mouse coords onto the dial plane to calculate the angle instead.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/manipulator_library/dial3d_manipulator.c | 55 |
1 files changed, 37 insertions, 18 deletions
diff --git a/source/blender/editors/manipulator_library/dial3d_manipulator.c b/source/blender/editors/manipulator_library/dial3d_manipulator.c index b3b78826650..a0317fc34b2 100644 --- a/source/blender/editors/manipulator_library/dial3d_manipulator.c +++ b/source/blender/editors/manipulator_library/dial3d_manipulator.c @@ -188,38 +188,51 @@ static void dial_ghostarc_draw( } static void dial_ghostarc_get_angles( - const DialManipulator *dial, const wmEvent *event, const ARegion *ar, + const DialManipulator *dial, const wmEvent *event, + const ARegion *ar, const View3D *v3d, float mat[4][4], const float co_outer[3], float *r_start, float *r_delta) { DialInteraction *inter = dial->manipulator.interaction_data; const RegionView3D *rv3d = ar->regiondata; const float mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin}; - bool inv = false; /* we might need to invert the direction of the angles */ float view_vec[3], axis_vec[3]; ED_view3d_global_to_vector(rv3d, dial->manipulator.origin, view_vec); normalize_v3_v3(axis_vec, dial->direction); - if (dot_v3v3(view_vec, axis_vec) < 0.0f) { - inv = true; - } - float co[3], origin2d[2], co2d[2]; - mul_v3_project_m4_v3(co, mat, co_outer); - /* project 3d coordinats to 2d viewplane */ - ED_view3d_project_float_global(ar, dial->manipulator.origin, origin2d, V3D_PROJ_TEST_NOP); - ED_view3d_project_float_global(ar, co, co2d, V3D_PROJ_TEST_NOP); + float proj_outer_rel[3]; + mul_v3_project_m4_v3(proj_outer_rel, mat, co_outer); + sub_v3_v3(proj_outer_rel, dial->manipulator.origin); + + float proj_mval_new_rel[3]; + float proj_mval_init_rel[3]; + float dial_plane[4]; + float ray_co[3], ray_no[3]; + float ray_lambda; + + plane_from_point_normal_v3(dial_plane, dial->manipulator.origin, axis_vec); - /* convert to manipulator relative space */ - float rel_initmval[2], rel_mval[2], rel_co[2]; - sub_v2_v2v2(rel_initmval, inter->init_mval, origin2d); - sub_v2_v2v2(rel_mval, mval, origin2d); - sub_v2_v2v2(rel_co, co2d, origin2d); + if (!ED_view3d_win_to_ray(ar, v3d, inter->init_mval, ray_co, ray_no, false) || + !isect_ray_plane_v3(ray_co, ray_no, dial_plane, &ray_lambda, false)) + { + goto fail; + } + madd_v3_v3v3fl(proj_mval_init_rel, ray_co, ray_no, ray_lambda); + sub_v3_v3(proj_mval_init_rel, dial->manipulator.origin); + + if (!ED_view3d_win_to_ray(ar, v3d, mval, ray_co, ray_no, false) || + !isect_ray_plane_v3(ray_co, ray_no, dial_plane, &ray_lambda, false)) + { + goto fail; + } + madd_v3_v3v3fl(proj_mval_new_rel, ray_co, ray_no, ray_lambda); + sub_v3_v3(proj_mval_new_rel, dial->manipulator.origin); /* return angles */ - const float start = angle_signed_v2v2(rel_co, rel_initmval) * (inv ? -1 : 1); - const float delta = angle_signed_v2v2(rel_initmval, rel_mval) * (inv ? -1 : 1); + const float start = angle_wrap_rad(angle_signed_on_axis_v3v3_v3(proj_outer_rel, proj_mval_init_rel, axis_vec)); + const float delta = angle_wrap_rad(angle_signed_on_axis_v3v3_v3(proj_mval_init_rel, proj_mval_new_rel, axis_vec)); /* Change of sign, we passed the 180 degree threshold. This means we need to add a turn * to distinguish between transition from 0 to -1 and -PI to +PI, use comparison with PI/2. @@ -236,6 +249,12 @@ static void dial_ghostarc_get_angles( *r_start = start; *r_delta = fmod(delta + 2.0f * (float)M_PI * inter->rotations, 2 * (float)M_PI); + return; + + /* If we can't project (unlikely). */ +fail: + *r_start = 0.0; + *r_delta = 0.0; } static void dial_draw_intern( @@ -350,7 +369,7 @@ static void manipulator_dial_modal(bContext *C, wmManipulator *mpr, const wmEven dial_calc_matrix(dial, mat); - dial_ghostarc_get_angles(dial, event, CTX_wm_region(C), mat, co_outer, &angle_ofs, &angle_delta); + dial_ghostarc_get_angles(dial, event, CTX_wm_region(C), CTX_wm_view3d(C), mat, co_outer, &angle_ofs, &angle_delta); DialInteraction *inter = dial->manipulator.interaction_data; |