Refactor: pose_slide.c #107610

Merged
Christoph Lendenfeld merged 4 commits from ChrisLend/blender:refactor_pose_slide into main 2023-05-05 15:30:36 +02:00
1 changed files with 103 additions and 111 deletions

View File

@ -138,12 +138,12 @@ typedef struct tPoseSlideOp {
struct AnimKeylist *keylist;
/** current frame number - global time */
int cframe;
int current_frame;
/** frame before current frame (blend-from) - global time */
int prevFrame;
int prev_frame;
/** frame after current frame (blend-to) - global time */
int nextFrame;
int next_frame;
/** Sliding Mode. */
ePoseSlide_Modes mode;
@ -169,10 +169,10 @@ typedef struct tPoseSlideOp {
typedef struct tPoseSlideObject {
/** Active object that Pose Info comes from. */
Object *ob;
/** `prevFrame`, but in local action time (for F-Curve look-ups to work). */
float prevFrameF;
/** `nextFrame`, but in local action time (for F-Curve look-ups to work). */
float nextFrameF;
/** `prev_frame`, but in local action time (for F-Curve look-ups to work). */
float prev_frame;
/** `next_frame`, but in local action time (for F-Curve look-ups to work). */
float next_frame;
bool valid;
} tPoseSlideObject;
@ -216,12 +216,12 @@ static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode)
pso->area = CTX_wm_area(C); /* Only really needed when doing modal(). */
pso->region = CTX_wm_region(C); /* Only really needed when doing modal(). */
pso->cframe = pso->scene->r.cfra;
pso->current_frame = pso->scene->r.cfra;
pso->mode = mode;
/* Set range info from property values - these may get overridden for the invoke(). */
pso->prevFrame = RNA_int_get(op->ptr, "prev_frame");
pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
pso->prev_frame = RNA_int_get(op->ptr, "prev_frame");
pso->next_frame = RNA_int_get(op->ptr, "next_frame");
/* Get the set of properties/axes that can be operated on. */
pso->channels = RNA_enum_get(op->ptr, "channels");
@ -255,10 +255,10 @@ static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode)
ob_data->valid = true;
/* Apply NLA mapping corrections so the frame look-ups work. */
ob_data->prevFrameF = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
ob_data->nextFrameF = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
ob_data->prev_frame = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->prev_frame, NLATIME_CONVERT_UNMAP);
ob_data->next_frame = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->next_frame, NLATIME_CONVERT_UNMAP);
/* Set depsgraph flags. */
/* Make sure the lock is set OK, unlock can be accidentally saved? */
@ -335,20 +335,20 @@ static void pose_slide_refresh(bContext *C, tPoseSlideOp *pso)
*/
static bool pose_frame_range_from_object_get(tPoseSlideOp *pso,
Object *ob,
float *prevFrameF,
float *nextFrameF)
float *prev_frame,
float *next_frame)
{
for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
Object *ob_iter = ob_data->ob;
if (ob_iter == ob) {
*prevFrameF = ob_data->prevFrameF;
*nextFrameF = ob_data->nextFrameF;
*prev_frame = ob_data->prev_frame;
*next_frame = ob_data->next_frame;
return true;
}
}
*prevFrameF = *nextFrameF = 0.0f;
*prev_frame = *next_frame = 0.0f;
return false;
}
@ -357,81 +357,71 @@ static bool pose_frame_range_from_object_get(tPoseSlideOp *pso,
*/
static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, float *val)
{
float prevFrameF, nextFrameF;
float cframe = (float)pso->cframe;
float sVal, eVal;
float w1, w2;
float prev_frame, next_frame;
float prev_weight, next_weight;

Now that you're cleaning up anyway, probably a good idea to keep the prev/next order consistent between the two lines.

Now that you're cleaning up anyway, probably a good idea to keep the prev/next order consistent between the two lines.
pose_frame_range_from_object_get(pso, ob, &prev_frame, &next_frame);
pose_frame_range_from_object_get(pso, ob, &prevFrameF, &nextFrameF);
/* Get keyframe values for endpoint poses to blend with. */
/* Previous/start. */
sVal = evaluate_fcurve(fcu, prevFrameF);
/* Next/end. */
eVal = evaluate_fcurve(fcu, nextFrameF);
const float factor = ED_slider_factor_get(pso->slider);
const float current_frame = (float)pso->current_frame;
/* Calculate the relative weights of the endpoints. */
if (pso->mode == POSESLIDE_BREAKDOWN) {
/* Get weights from the factor control. */
w1 = ED_slider_factor_get(pso->slider); /* This must come second. */
w2 = 1.0f - w1; /* This must come first. */
next_weight = factor;
prev_weight = 1.0f - next_weight;

AAAAAAAA those comments (I know, not yours, just AAAAAA). IMO you can just remove those as well. I mean, saying "this must come first" on the 2nd thing just makes no sense to me.

AAAAAAAA those comments (I know, not yours, just AAAAAA). IMO you can just remove those as well. I mean, saying "this must come first" on the 2nd thing just makes no sense to me.
}
else {
/* - these weights are derived from the relative distance of these
* poses from the current frame
* - they then get normalized so that they only sum up to 1
*/
float wtot;
w1 = cframe - (float)pso->prevFrame;
w2 = (float)pso->nextFrame - cframe;
next_weight = current_frame - (float)pso->prev_frame;
prev_weight = (float)pso->next_frame - current_frame;
wtot = w1 + w2;
w1 = (w1 / wtot);
w2 = (w2 / wtot);
const float total_weight = next_weight + prev_weight;
next_weight = (next_weight / total_weight);
prev_weight = (prev_weight / total_weight);
}
/* Depending on the mode, calculate the new value:
* - In all of these, the start+end values are multiplied by w2 and w1 (respectively),
* since multiplication in another order would decrease
* the value the current frame is closer to.
*/
/* Get keyframe values for endpoint poses to blend with. */
/* Previous/start. */
const float prev_frame_y = evaluate_fcurve(fcu, prev_frame);
const float next_frame_y = evaluate_fcurve(fcu, next_frame);
/* Depending on the mode, calculate the new value. */
switch (pso->mode) {
case POSESLIDE_PUSH: /* Make the current pose more pronounced. */
{

Aaaah that is what those comments were referring to. Yeah, just remove them. This one explains it all, and is just as clear without the confusion.

... wait... no it doesn't make sense at all. The 'prev' and 'next' values are just summed, so it doesn't matter in which order they're calculated. And with the naming that you're introducing now it's so logical that you multiply the prevs together and the nexts, that IMO this comment can just be removed as well.

Aaaah **that** is what those comments were referring to. Yeah, just remove them. This one explains it all, and is just as clear without the confusion. ... wait... no it doesn't make sense at all. The 'prev' and 'next' values are just summed, so it doesn't matter in which order they're calculated. And with the naming that you're introducing now it's *so* logical that you multiply the `prev`s together and the `next`s, that IMO this comment can just be removed as well.
/* Slide the pose away from the breakdown pose in the timeline */
(*val) -= ((sVal * w2) + (eVal * w1) - (*val)) * ED_slider_factor_get(pso->slider);
(*val) -= ((prev_frame_y * prev_weight) + (next_frame_y * next_weight) - (*val)) * factor;
break;
}
case POSESLIDE_RELAX: /* Make the current pose more like its surrounding ones. */
{
/* Slide the pose towards the breakdown pose in the timeline */
(*val) += ((sVal * w2) + (eVal * w1) - (*val)) * ED_slider_factor_get(pso->slider);
(*val) += ((prev_frame_y * prev_weight) + (next_frame_y * next_weight) - (*val)) * factor;
break;
}
case POSESLIDE_BREAKDOWN: /* Make the current pose slide around between the endpoints. */
{
/* Perform simple linear interpolation -
* coefficient for start must come from pso->factor. */
/* TODO: make this use some kind of spline interpolation instead? */
(*val) = ((sVal * w2) + (eVal * w1));
/* Perform simple linear interpolation. */
(*val) = interpf(next_frame_y, prev_frame_y, factor);
break;
}
case POSESLIDE_BLEND: /* Blend the current pose with the previous (<50%) or next key (>50%). */
{
/* FCurve value on current frame. */
const float cVal = evaluate_fcurve(fcu, cframe);
const float factor = ED_slider_factor_get(pso->slider);
/* Convert factor to absolute 0-1 range. */
const float current_frame_y = evaluate_fcurve(fcu, current_frame);
/* Convert factor to absolute 0-1 range which is needed for lerpf. */
const float blend_factor = fabs((factor - 0.5f) * 2);
if (factor < 0.5) {
/* Blend to previous key. */
(*val) = (cVal * (1 - blend_factor)) + (sVal * blend_factor);
(*val) = interpf(prev_frame_y, current_frame_y, blend_factor);
}
else {
/* Blend to next key. */
(*val) = (cVal * (1 - blend_factor)) + (eVal * blend_factor);
(*val) = interpf(next_frame_y, current_frame_y, blend_factor);
}
break;
@ -618,10 +608,9 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
bPoseChannel *pchan = pfl->pchan;
LinkData *ld = NULL;
char *path = NULL;
float cframe;
float prevFrameF, nextFrameF;
float prev_frame, next_frame;
if (!pose_frame_range_from_object_get(pso, pfl->ob, &prevFrameF, &nextFrameF)) {
if (!pose_frame_range_from_object_get(pso, pfl->ob, &prev_frame, &next_frame)) {
BLI_assert_msg(0, "Invalid pfl data");
return;
}
@ -630,7 +619,8 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
path = BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion");
/* Get the current frame number. */
cframe = (float)pso->cframe;
const float current_frame = (float)pso->current_frame;
const float factor = ED_slider_factor_get(pso->slider);
/* Using this path, find each matching F-Curve for the variables we're interested in. */
while ((ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path))) {
@ -661,15 +651,15 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
if (ELEM(pso->mode, POSESLIDE_BREAKDOWN, POSESLIDE_PUSH, POSESLIDE_RELAX)) {
float quat_prev[4], 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_prev[0] = evaluate_fcurve(fcu_w, prev_frame);
quat_prev[1] = evaluate_fcurve(fcu_x, prev_frame);
quat_prev[2] = evaluate_fcurve(fcu_y, prev_frame);
quat_prev[3] = evaluate_fcurve(fcu_z, prev_frame);
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);
quat_next[0] = evaluate_fcurve(fcu_w, next_frame);
quat_next[1] = evaluate_fcurve(fcu_x, next_frame);
quat_next[2] = evaluate_fcurve(fcu_y, next_frame);
quat_next[3] = evaluate_fcurve(fcu_z, next_frame);
normalize_qt(quat_prev);
normalize_qt(quat_next);
@ -677,7 +667,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
if (pso->mode == POSESLIDE_BREAKDOWN) {
/* Just perform the interpolation between quat_prev and
* quat_next using pso->factor as a guide. */
interp_qt_qtqt(quat_final, quat_prev, quat_next, ED_slider_factor_get(pso->slider));
interp_qt_qtqt(quat_final, quat_prev, quat_next, factor);
}
else {
float quat_curr[4], quat_breakdown[4];
@ -685,17 +675,17 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
normalize_qt_qt(quat_curr, pchan->quat);
/* Compute breakdown based on actual frame range. */
const float factor = (cframe - pso->prevFrame) / (float)(pso->nextFrame - pso->prevFrame);
const float interp_factor = (current_frame - pso->prev_frame) /
(float)(pso->next_frame - pso->prev_frame);
interp_qt_qtqt(quat_breakdown, quat_prev, quat_next, factor);
interp_qt_qtqt(quat_breakdown, quat_prev, quat_next, interp_factor);
if (pso->mode == POSESLIDE_PUSH) {

Could you use interpf() here as well? Might simplify the code a little bit.

Could you use `interpf()` here as well? Might simplify the code a little bit.

not sure how tbh. This is calculation the factor to use in the interp_qt
how would I get the 0-1 value from an interpf

not sure how tbh. This is calculation the factor to use in the `interp_qt` how would I get the 0-1 value from an `interpf`

You're right, I mis-read.

You're right, I mis-read.
interp_qt_qtqt(
quat_final, quat_breakdown, quat_curr, 1.0f + ED_slider_factor_get(pso->slider));
interp_qt_qtqt(quat_final, quat_breakdown, quat_curr, 1.0f + factor);
}
else {
BLI_assert(pso->mode == POSESLIDE_RELAX);
interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, ED_slider_factor_get(pso->slider));
interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, factor);
}
}
}
@ -705,23 +695,23 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
copy_qt_qt(quat_curr, pchan->quat);
if (ED_slider_factor_get(pso->slider) < 0.5) {
quat_blend[0] = evaluate_fcurve(fcu_w, prevFrameF);
quat_blend[1] = evaluate_fcurve(fcu_x, prevFrameF);
quat_blend[2] = evaluate_fcurve(fcu_y, prevFrameF);
quat_blend[3] = evaluate_fcurve(fcu_z, prevFrameF);
if (factor < 0.5) {
quat_blend[0] = evaluate_fcurve(fcu_w, prev_frame);
quat_blend[1] = evaluate_fcurve(fcu_x, prev_frame);
quat_blend[2] = evaluate_fcurve(fcu_y, prev_frame);
quat_blend[3] = evaluate_fcurve(fcu_z, prev_frame);
}
else {
quat_blend[0] = evaluate_fcurve(fcu_w, nextFrameF);
quat_blend[1] = evaluate_fcurve(fcu_x, nextFrameF);
quat_blend[2] = evaluate_fcurve(fcu_y, nextFrameF);
quat_blend[3] = evaluate_fcurve(fcu_z, nextFrameF);
quat_blend[0] = evaluate_fcurve(fcu_w, next_frame);
quat_blend[1] = evaluate_fcurve(fcu_x, next_frame);
quat_blend[2] = evaluate_fcurve(fcu_y, next_frame);
quat_blend[3] = evaluate_fcurve(fcu_z, next_frame);
}
normalize_qt(quat_blend);
normalize_qt(quat_curr);
const float blend_factor = fabs((ED_slider_factor_get(pso->slider) - 0.5f) * 2);
const float blend_factor = fabs((factor - 0.5f) * 2);
interp_qt_qtqt(quat_final, quat_curr, quat_blend, blend_factor);
}
@ -738,17 +728,18 @@ static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], flo
{
/* We only slide to the rest pose. So only use the default rest pose value. */
const int lock = pso->axislock;
const float factor = ED_slider_factor_get(pso->slider);
for (int idx = 0; idx < 3; idx++) {
if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) ||
((lock & PS_LOCK_Z) && (idx == 2)))
{
float diff_val = default_value - vec[idx];
if (pso->mode == POSESLIDE_RELAX_REST) {
vec[idx] += ED_slider_factor_get(pso->slider) * diff_val;
vec[idx] += factor * diff_val;
}
else {
/* Push */
vec[idx] -= ED_slider_factor_get(pso->slider) * diff_val;
vec[idx] -= factor * diff_val;
}
}
}
@ -763,14 +754,15 @@ static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4]
default_values[0] = 0.0f;
default_values[2] = 1.0f;
}
const float factor = ED_slider_factor_get(pso->slider);
for (int idx = 0; idx < 4; idx++) {
float diff_val = default_values[idx] - vec[idx];
if (pso->mode == POSESLIDE_RELAX_REST) {
vec[idx] += ED_slider_factor_get(pso->slider) * diff_val;
vec[idx] += factor * diff_val;
}
else {
/* Push */
vec[idx] -= ED_slider_factor_get(pso->slider) * diff_val;
vec[idx] -= factor * diff_val;
}
}
}
@ -842,10 +834,10 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
tPChanFCurveLink *pfl;
/* Sanitize the frame ranges. */
if (pso->prevFrame == pso->nextFrame) {
if (pso->prev_frame == pso->next_frame) {
/* Move out one step either side. */
pso->prevFrame--;
pso->nextFrame++;
pso->prev_frame--;
pso->next_frame++;
for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
@ -855,10 +847,10 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
}
/* Apply NLA mapping corrections so the frame look-ups work. */
ob_data->prevFrameF = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
ob_data->nextFrameF = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
ob_data->prev_frame = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->prev_frame, NLATIME_CONVERT_UNMAP);
ob_data->next_frame = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->next_frame, NLATIME_CONVERT_UNMAP);
}
}
@ -918,7 +910,7 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
static void pose_slide_autoKeyframe(bContext *C, tPoseSlideOp *pso)
{
/* Wrapper around the generic call. */
poseAnim_mapping_autoKeyframe(C, pso->scene, &pso->pfLinks, (float)pso->cframe);
poseAnim_mapping_autoKeyframe(C, pso->scene, &pso->pfLinks, (float)pso->current_frame);
}
/**
@ -1074,42 +1066,42 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, const wmEvent *
return OPERATOR_CANCELLED;
}
float cframe = (float)pso->cframe;
float current_frame = (float)pso->current_frame;
/* Firstly, check if the current frame is a keyframe. */
const ActKeyColumn *ak = ED_keylist_find_exact(pso->keylist, cframe);
const ActKeyColumn *ak = ED_keylist_find_exact(pso->keylist, current_frame);
if (ak == NULL) {
/* Current frame is not a keyframe, so search. */
const ActKeyColumn *pk = ED_keylist_find_prev(pso->keylist, cframe);
const ActKeyColumn *nk = ED_keylist_find_next(pso->keylist, cframe);
const ActKeyColumn *pk = ED_keylist_find_prev(pso->keylist, current_frame);
const ActKeyColumn *nk = ED_keylist_find_next(pso->keylist, current_frame);
/* New set the frames. */
/* Previous frame. */
pso->prevFrame = (pk) ? (pk->cfra) : (pso->cframe - 1);
RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
pso->prev_frame = (pk) ? (pk->cfra) : (pso->current_frame - 1);
RNA_int_set(op->ptr, "prev_frame", pso->prev_frame);
/* Next frame. */
pso->nextFrame = (nk) ? (nk->cfra) : (pso->cframe + 1);
RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
pso->next_frame = (nk) ? (nk->cfra) : (pso->current_frame + 1);
RNA_int_set(op->ptr, "next_frame", pso->next_frame);
}
else {
/* Current frame itself is a keyframe, so just take keyframes on either side. */
/* Previous frame. */
pso->prevFrame = (ak->prev) ? (ak->prev->cfra) : (pso->cframe - 1);
RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
pso->prev_frame = (ak->prev) ? (ak->prev->cfra) : (pso->current_frame - 1);
RNA_int_set(op->ptr, "prev_frame", pso->prev_frame);
/* Next frame. */
pso->nextFrame = (ak->next) ? (ak->next->cfra) : (pso->cframe + 1);
RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
pso->next_frame = (ak->next) ? (ak->next->cfra) : (pso->current_frame + 1);
RNA_int_set(op->ptr, "next_frame", pso->next_frame);
}
/* Apply NLA mapping corrections so the frame look-ups work. */
for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) {
tPoseSlideObject *ob_data = &pso->ob_data_array[ob_index];
if (ob_data->valid) {
ob_data->prevFrameF = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP);
ob_data->nextFrameF = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP);
ob_data->prev_frame = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->prev_frame, NLATIME_CONVERT_UNMAP);
ob_data->next_frame = BKE_nla_tweakedit_remap(
ob_data->ob->adt, pso->next_frame, NLATIME_CONVERT_UNMAP);
}
}