[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