[Bf-blender-cvs] [cee484a4c51] master: Fix T67067: Wrong rotation input values when using shortcuts on keyboard like rx720.

Bastien Montagne noreply at git.blender.org
Tue Jul 30 14:25:49 CEST 2019


Commit: cee484a4c51a3d207e42b2d0486846da6db386cf
Author: Bastien Montagne
Date:   Tue Jul 30 13:00:48 2019 +0200
Branches: master
https://developer.blender.org/rBcee484a4c51a3d207e42b2d0486846da6db386cf

Fix T67067: Wrong rotation input values when using shortcuts on keyboard like rx720.

This allows to type in numinput 720 and indeed get a rotation of 720°, not 0°...

This patch basically applies 'big rotations' in steps < 180°, such that
compatible rotation works as expected. This implies resetting current
rotation to initial one first, otherwise we'd end up applying much more
turns than expected when that code is called more than once.

It also makes things somewhat slower for big rotations (millions of degrees),
Hence we clamp to 1000 turns max.

And since that's a case that cannot happen with regular tool/widget-driven rotation,
it's only enabled when numinput is used for now.

Review task: https://developer.blender.org/D5289

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

M	source/blender/editors/transform/transform.c

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

diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 6add395361e..d8dd6aa97b5 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -4583,17 +4583,42 @@ static void ElementRotation(
   ElementRotation_ex(t, tc, td, mat, center);
 }
 
-static void applyRotationValue(TransInfo *t, float angle, float axis[3])
+static float large_rotation_limit(float angle)
+{
+  /* Limit rotation to 1001 turns max
+   * (otherwise iterative handling of 'large' rotations would become too slow). */
+  const float angle_max = (float)(M_PI * 2000.0);
+  if (fabsf(angle) > angle_max) {
+    const float angle_sign = angle < 0.0f ? -1.0f : 1.0f;
+    angle = angle_sign * (fmodf(fabsf(angle), (float)(M_PI * 2.0)) + angle_max);
+  }
+  return angle;
+}
+
+static void applyRotationValue(TransInfo *t,
+                               float angle,
+                               float axis[3],
+                               const bool is_large_rotation)
 {
   float mat[3][3];
   int i;
 
+  const float angle_sign = angle < 0.0f ? -1.0f : 1.0f;
+  /* We cannot use something too close to 180°, or 'continuous' rotation may fail
+   * due to computing error... */
+  const float angle_step = angle_sign * (float)(0.9 * M_PI);
+
+  if (is_large_rotation) {
+    /* Just in case, calling code should have already done that in practice
+     * (for UI feedback reasons). */
+    angle = large_rotation_limit(angle);
+  }
+
   axis_angle_normalized_to_mat3(mat, axis, angle);
 
   FOREACH_TRANS_DATA_CONTAINER (t, tc) {
     TransData *td = tc->data;
     for (i = 0; i < tc->data_len; i++, td++) {
-
       if (td->flag & TD_NOACTION) {
         break;
       }
@@ -4602,14 +4627,32 @@ static void applyRotationValue(TransInfo *t, float angle, float axis[3])
         continue;
       }
 
+      float angle_final = angle;
       if (t->con.applyRot) {
         t->con.applyRot(t, tc, td, axis, NULL);
-        axis_angle_normalized_to_mat3(mat, axis, angle * td->factor);
+        angle_final = angle * td->factor;
       }
       else if (t->flag & T_PROP_EDIT) {
-        axis_angle_normalized_to_mat3(mat, axis, angle * td->factor);
+        angle_final = angle * td->factor;
       }
 
+      /* Rotation is very likely to be above 180°, we need to do rotation by steps.
+       * Note that this is only needed when doing 'absolute' rotation
+       * (i.e. from initial rotation again, typically when using numinput).
+       * regular incremental rotation (from mouse/widget/...) will be called often enough,
+       * hence steps are small enough to be properly handled without that complicated trick. */
+      if (is_large_rotation) {
+        copy_v3_v3(td->ext->rot, td->ext->irot);
+        for (float angle_progress = angle_step; fabsf(angle_progress) < fabsf(angle_final);
+             angle_progress += angle_step) {
+          axis_angle_normalized_to_mat3(mat, axis, angle_progress);
+          ElementRotation(t, tc, td, mat, t->around);
+        }
+        axis_angle_normalized_to_mat3(mat, axis, angle_final);
+      }
+      else if (angle_final != angle) {
+        axis_angle_normalized_to_mat3(mat, axis, angle_final);
+      }
       ElementRotation(t, tc, td, mat, t->around);
     }
   }
@@ -4634,15 +4677,18 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
 
   applySnapping(t, &final);
 
-  /* Used to clamp final result in [-PI, PI[ range, no idea why,
-   * inheritance from 2.4x area, see T48998. */
-  applyNumInput(&t->num, &final);
+  if (applyNumInput(&t->num, &final)) {
+    /* We have to limit the amount of turns to a reasonable number here,
+     * to avoid things getting *very* slow, see how applyRotationValue() handles those... */
+    final = large_rotation_limit(final);
+  }
 
   t->values[0] = final;
 
   headerRotation(t, str, final);
 
-  applyRotationValue(t, final, axis_final);
+  const bool is_large_rotation = hasNumInput(&t->num);
+  applyRotationValue(t, final, axis_final, is_large_rotation);
 
   recalcData(t);



More information about the Bf-blender-cvs mailing list