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.
This commit is contained in:
Sebastian Parborg 2020-04-23 14:11:15 +02:00
parent 8f51f60948
commit 35ecfefaec
1 changed files with 33 additions and 48 deletions

View File

@ -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. */
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);
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);
normalize_qt(quat_prev);
normalize_qt(quat_next);
interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage);
}
else if (pso->mode == POSESLIDE_PUSH) {
float quat_diff[4];
/* 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);
/* 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_final);
}
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 */