[Bf-blender-cvs] [3daacbe6638] temp-T52744-euler-filter: New Euler filter implementation

Sybren A. Stüvel noreply at git.blender.org
Thu Nov 19 12:47:34 CET 2020


Commit: 3daacbe6638741177f0ca6a458b4715351edc7a4
Author: Sybren A. Stüvel
Date:   Thu Nov 19 12:41:13 2020 +0100
Branches: temp-T52744-euler-filter
https://developer.blender.org/rB3daacbe6638741177f0ca6a458b4715351edc7a4

New Euler filter implementation

This new discontinuity filter performs actions on the entire Euler
rotation, rather than on the individual X/Y/Z channels only. This should
make it fix a wider range of discontinuities, for example those in .

Manifest Task: T52744

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

M	source/blender/blenkernel/BKE_fcurve.h
M	source/blender/blenkernel/intern/fcurve.c
M	source/blender/editors/space_graph/graph_edit.c

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

diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index f527f40d0d7..4569e68ea4a 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -248,6 +248,10 @@ bool BKE_fcurve_calc_bounds(struct FCurve *fcu,
 void BKE_fcurve_active_keyframe_set(struct FCurve *fcu, const struct BezTriple *active_bezt);
 int BKE_fcurve_active_keyframe_index(const struct FCurve *fcu);
 
+/* Move the indexed keyframe to the given value, and move the handles with it to ensure the slope
+ * remains the same. */
+void BKE_fcurve_keyframe_move_value_with_handles(struct BezTriple *keyframe, float new_value);
+
 /* .............. */
 
 /* Are keyframes on F-Curve of any use (to final result, and to show in editors)? */
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index e6d3696b198..bcd2fe098b7 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -884,6 +884,14 @@ int BKE_fcurve_active_keyframe_index(const FCurve *fcu)
 
 /** \} */
 
+void BKE_fcurve_keyframe_move_value_with_handles(struct BezTriple *keyframe, const float new_value)
+{
+  const float value_delta = new_value - keyframe->vec[1][1];
+  keyframe->vec[0][1] += value_delta;
+  keyframe->vec[1][1] = new_value;
+  keyframe->vec[2][1] += value_delta;
+}
+
 /* -------------------------------------------------------------------- */
 /** \name Status Checks
  * \{ */
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index bf76d4a632a..678a1358174 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -2690,40 +2690,52 @@ static int euler_filter_perform_filter(ListBase /*tEulerFilter*/ *eulers, Report
       continue;
     }
 
-    /* Simple method: just treat any difference between
-     * keys of greater than 180 degrees as being a flip. */
-    /* FIXME: there are more complicated methods that
-     * will be needed to fix more cases than just some */
-    for (int f = 0; f < 3; f++) {
-      FCurve *fcu = euf->fcurves[f];
-      BezTriple *bezt, *prev;
-      uint i;
-
-      /* Skip if not enough vets to do a decent analysis of.... */
-      if (fcu->totvert <= 2) {
-        continue;
-      }
-
-      /* Prev follows bezt, bezt = "current" point to be fixed. */
-      /* Our method depends on determining a "difference" from the previous vert. */
-      for (i = 1, prev = fcu->bezt, bezt = fcu->bezt + 1; i < fcu->totvert; i++, prev = bezt++) {
-        const float sign = (prev->vec[1][1] > bezt->vec[1][1]) ? 1.0f : -1.0f;
+    FCurve *fcu_rot_x = euf->fcurves[0];
+    FCurve *fcu_rot_y = euf->fcurves[1];
+    FCurve *fcu_rot_z = euf->fcurves[2];
+    if (fcu_rot_x->totvert != fcu_rot_y->totvert || fcu_rot_y->totvert != fcu_rot_z->totvert) {
+      /* Report which components are missing. */
+      BKE_reportf(reports,
+                  RPT_WARNING,
+                  "XYZ rotations not equally keyed for ID='%s' and RNA-Path='%s'",
+                  euf->id->name,
+                  euf->rna_path);
 
-        /* >= 180 degree flip? */
-        if ((sign * (prev->vec[1][1] - bezt->vec[1][1])) < (float)M_PI) {
-          continue;
-        }
+      /* Keep track of number of failed sets, and carry on to next group. */
+      failed++;
+      continue;
+    }
 
-        /* 360 degrees to add/subtract frame value until difference
-         * is acceptably small that there's no more flip. */
-        const float fac = sign * 2.0f * (float)M_PI;
+    if (fcu_rot_x->totvert < 2) {
+      /* Single rotations are trivially "filtered". */
+      continue;
+    }
 
-        while ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) {
-          bezt->vec[0][1] += fac;
-          bezt->vec[1][1] += fac;
-          bezt->vec[2][1] += fac;
-        }
-      }
+    float last_euler[3] = {
+        fcu_rot_x->bezt[0].vec[1][1],
+        fcu_rot_y->bezt[0].vec[1][1],
+        fcu_rot_z->bezt[0].vec[1][1],
+    };
+
+    for (int keyframe_index = 1; keyframe_index < fcu_rot_x->totvert; ++keyframe_index) {
+      /* TODO(Sybren): check X-coordinates of keyframes to ensure they're on the same frame, and we
+       * don't accidentally just have the same number of keyframes but on different frames. */
+      const float euler[3] = {
+          fcu_rot_x->bezt[keyframe_index].vec[1][1],
+          fcu_rot_y->bezt[keyframe_index].vec[1][1],
+          fcu_rot_z->bezt[keyframe_index].vec[1][1],
+      };
+
+      /* TODO(Sybren): Quaternions are nice, but the calls below internally use rotation matrices.
+       * Directly using matrices here may speed things up a bit. */
+      float quaternion[4];
+      eul_to_quat(quaternion, euler);
+      quat_to_compatible_eul(last_euler, last_euler, quaternion);
+
+      /* Update the FCurves to have the new rotation values. */
+      BKE_fcurve_keyframe_move_value_with_handles(&fcu_rot_x->bezt[keyframe_index], last_euler[0]);
+      BKE_fcurve_keyframe_move_value_with_handles(&fcu_rot_y->bezt[keyframe_index], last_euler[1]);
+      BKE_fcurve_keyframe_move_value_with_handles(&fcu_rot_z->bezt[keyframe_index], last_euler[2]);
     }
   }



More information about the Bf-blender-cvs mailing list