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]); } } _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs