From 35ecfefaec231772d3cd366d21240636b9940be1 Mon Sep 17 00:00:00 2001 From: Sebastian Parborg Date: Thu, 23 Apr 2020 14:11:15 +0200 Subject: Made pose push/relax to breakdown behave smooth on rotations A follow up to T67212. I missed that the rotation interpolation had its own code path. The previous rotation push code was actually wrong (but smooth). Now all of the actions behave correctly and is smoothly interpolated. --- source/blender/editors/armature/pose_slide.c | 77 +++++++++++----------------- 1 file changed, 31 insertions(+), 46 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index ae08aee3c47..481282d6df3 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -544,71 +544,56 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) /* only if all channels exist, proceed */ if (fcu_w && fcu_x && fcu_y && fcu_z) { - float quat_prev[4], quat_prev_orig[4]; - float quat_next[4], quat_next_orig[4]; - float quat_curr[4], quat_curr_orig[4]; float quat_final[4]; - copy_qt_qt(quat_curr_orig, pchan->quat); - - /* get 2 quats */ - quat_prev_orig[0] = evaluate_fcurve(fcu_w, prevFrameF); - quat_prev_orig[1] = evaluate_fcurve(fcu_x, prevFrameF); - quat_prev_orig[2] = evaluate_fcurve(fcu_y, prevFrameF); - quat_prev_orig[3] = evaluate_fcurve(fcu_z, prevFrameF); - - quat_next_orig[0] = evaluate_fcurve(fcu_w, nextFrameF); - quat_next_orig[1] = evaluate_fcurve(fcu_x, nextFrameF); - quat_next_orig[2] = evaluate_fcurve(fcu_y, nextFrameF); - quat_next_orig[3] = evaluate_fcurve(fcu_z, nextFrameF); - - normalize_qt_qt(quat_prev, quat_prev_orig); - normalize_qt_qt(quat_next, quat_next_orig); - normalize_qt_qt(quat_curr, quat_curr_orig); - /* perform blending */ if (pso->mode == POSESLIDE_BREAKDOWN) { /* Just perform the interpolation between quat_prev and * quat_next using pso->percentage as a guide. */ - interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage); - } - else if (pso->mode == POSESLIDE_PUSH) { - float quat_diff[4]; + float quat_prev[4]; + float quat_next[4]; + + quat_prev[0] = evaluate_fcurve(fcu_w, prevFrameF); + quat_prev[1] = evaluate_fcurve(fcu_x, prevFrameF); + quat_prev[2] = evaluate_fcurve(fcu_y, prevFrameF); + quat_prev[3] = evaluate_fcurve(fcu_z, prevFrameF); - /* calculate the delta transform from the previous to the current */ - /* TODO: investigate ways to favor one transform more? */ - sub_qt_qtqt(quat_diff, quat_curr, quat_prev); + quat_next[0] = evaluate_fcurve(fcu_w, nextFrameF); + quat_next[1] = evaluate_fcurve(fcu_x, nextFrameF); + quat_next[2] = evaluate_fcurve(fcu_y, nextFrameF); + quat_next[3] = evaluate_fcurve(fcu_z, nextFrameF); - /* increase the original by the delta transform, by an amount determined by percentage */ - add_qt_qtqt(quat_final, quat_curr, quat_diff, pso->percentage); + normalize_qt(quat_prev); + normalize_qt(quat_next); - normalize_qt(quat_final); + interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage); } else { - BLI_assert(pso->mode == POSESLIDE_RELAX); - float quat_interp[4], quat_final_prev[4]; - /* TODO: maybe a sensitivity ctrl on top of this is needed */ - int iters = (int)ceil(10.0f * pso->percentage); + /* POSESLIDE_PUSH and POSESLIDE_RELAX. */ + float quat_breakdown[4]; + float quat_curr[4]; - copy_qt_qt(quat_final, quat_curr); + copy_qt_qt(quat_curr, pchan->quat); - /* perform this blending several times until a satisfactory result is reached */ - while (iters-- > 0) { - /* calculate the interpolation between the endpoints */ - interp_qt_qtqt(quat_interp, - quat_prev, - quat_next, - (cframe - pso->prevFrame) / (pso->nextFrame - pso->prevFrame)); + quat_breakdown[0] = evaluate_fcurve(fcu_w, cframe); + quat_breakdown[1] = evaluate_fcurve(fcu_x, cframe); + quat_breakdown[2] = evaluate_fcurve(fcu_y, cframe); + quat_breakdown[3] = evaluate_fcurve(fcu_z, cframe); - normalize_qt_qt(quat_final_prev, quat_final); + normalize_qt(quat_breakdown); + normalize_qt(quat_curr); - /* tricky interpolations - blending between original and new */ - interp_qt_qtqt(quat_final, quat_final_prev, quat_interp, 1.0f / 6.0f); + if (pso->mode == POSESLIDE_PUSH) { + interp_qt_qtqt(quat_final, quat_breakdown, quat_curr, 1.0f + pso->percentage); + } + else { + BLI_assert(pso->mode == POSESLIDE_RELAX); + interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, pso->percentage); } } /* Apply final to the pose bone, keeping compatible for similar keyframe positions. */ - quat_to_compatible_quat(pchan->quat, quat_final, quat_curr_orig); + quat_to_compatible_quat(pchan->quat, quat_final, pchan->quat); } /* free the path now */ -- cgit v1.2.3