[Bf-blender-cvs] [865bf8ecbc1] blender2.8: Manipulator: correct dial angle

Campbell Barton noreply at git.blender.org
Sat Jun 17 06:30:53 CEST 2017


Commit: 865bf8ecbc1cf3aac3107cbb70b2e94d8e239adc
Author: Campbell Barton
Date:   Sat Jun 17 14:31:27 2017 +1000
Branches: blender2.8
https://developer.blender.org/rB865bf8ecbc1cf3aac3107cbb70b2e94d8e239adc

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.

===================================================================

M	source/blender/editors/manipulator_library/dial3d_manipulator.c

===================================================================

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;




More information about the Bf-blender-cvs mailing list