peach request, pose relax - similar to mesh smooth, moves selected pose bones to closer match keyframes on either side.
This commit is contained in:
@@ -67,6 +67,6 @@ void pose_clear_paths(struct Object *ob);
|
||||
void pose_flip_names(void);
|
||||
void pose_activate_flipped_bone(void);
|
||||
void pose_movetolayer(void);
|
||||
|
||||
void pose_relax(void);
|
||||
#endif
|
||||
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include "DNA_action_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_constraint_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
@@ -56,6 +57,7 @@
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_ipo.h"
|
||||
|
||||
#include "BIF_editarmature.h"
|
||||
#include "BIF_editaction.h"
|
||||
@@ -77,6 +79,9 @@
|
||||
|
||||
#include "mydevice.h"
|
||||
#include "blendef.h"
|
||||
#include "transform.h"
|
||||
|
||||
#include "BIF_transform.h" /* for autokey TFM_TRANSLATION, etc */
|
||||
|
||||
void enter_posemode(void)
|
||||
{
|
||||
@@ -479,7 +484,7 @@ void pose_special_editmenu(void)
|
||||
if(!ob && !ob->pose) return;
|
||||
if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
|
||||
|
||||
nr= pupmenu("Specials%t|Select Constraint Target%x1|Flip Left-Right Names%x2|Calculate Paths%x3|Clear Paths%x4|Clear User Transform %x5");
|
||||
nr= pupmenu("Specials%t|Select Constraint Target%x1|Flip Left-Right Names%x2|Calculate Paths%x3|Clear Paths%x4|Clear User Transform %x5|Relax Pose %x6");
|
||||
if(nr==1) {
|
||||
pose_select_constraint_target();
|
||||
}
|
||||
@@ -497,6 +502,9 @@ void pose_special_editmenu(void)
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
||||
BIF_undo_push("Clear User Transform Pose");
|
||||
}
|
||||
else if(nr==6) {
|
||||
pose_relax();
|
||||
}
|
||||
}
|
||||
|
||||
void pose_add_IK(void)
|
||||
@@ -1070,3 +1078,150 @@ void pose_movetolayer(void)
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* for use with pose_relax only */
|
||||
static int pose_relax_icu(struct IpoCurve *icu, float framef, float *val, float *frame_prev, float *frame_next)
|
||||
{
|
||||
if (!icu) {
|
||||
return 0;
|
||||
} else {
|
||||
BezTriple *bezt = icu->bezt;
|
||||
|
||||
BezTriple *bezt_prev=NULL, *bezt_next=NULL;
|
||||
float w1, w2, wtot;
|
||||
int i;
|
||||
|
||||
for (i=0; i < icu->totvert; i++, bezt++) {
|
||||
if (bezt->vec[1][0] < framef - 1.0) {
|
||||
bezt_prev = bezt;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bezt_prev==NULL) return 0;
|
||||
|
||||
/* advance to the next, dont need to advance i */
|
||||
bezt = bezt_prev+1;
|
||||
|
||||
for (; i < icu->totvert; i++, bezt++) {
|
||||
if (bezt->vec[1][0] > framef + 1.0) {
|
||||
bezt_next = bezt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bezt_next==NULL) return 0;
|
||||
|
||||
if (val) {
|
||||
w1 = framef - bezt_prev->vec[1][0];
|
||||
w2 = bezt_next->vec[1][0] - framef;
|
||||
wtot = w1 + w2;
|
||||
w1=w1/wtot;
|
||||
w2=w2/wtot;
|
||||
#if 0
|
||||
val = (bezt_prev->vec[1][1] * w2) + (bezt_next->vec[1][1] * w1);
|
||||
#else
|
||||
/* apply the value with a hard coded 6th */
|
||||
*val = (((bezt_prev->vec[1][1] * w2) + (bezt_next->vec[1][1] * w1)) + (*val * 5.0f)) / 6.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (frame_prev) *frame_prev = bezt_prev->vec[1][0];
|
||||
if (frame_next) *frame_next = bezt_next->vec[1][0];
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void pose_relax()
|
||||
{
|
||||
Object *ob = OBACT;
|
||||
bPose *pose;
|
||||
bAction *act;
|
||||
bArmature *arm;
|
||||
|
||||
IpoCurve *icu_w, *icu_x, *icu_y, *icu_z;
|
||||
|
||||
bPoseChannel *pchan;
|
||||
bActionChannel *achan;
|
||||
float framef = F_CFRA;
|
||||
float frame_prev, frame_next;
|
||||
float quat_prev[4], quat_next[4], quat_interp[4], quat_orig[4];
|
||||
|
||||
int do_scale = 0;
|
||||
int do_loc = 0;
|
||||
int do_quat = 0;
|
||||
int flag = 0;
|
||||
|
||||
if (!ob) return;
|
||||
|
||||
pose = ob->pose;
|
||||
act = ob->action;
|
||||
arm = (bArmature *)ob->data;
|
||||
|
||||
if (!pose || !act || !arm) return;
|
||||
|
||||
for (pchan=pose->chanbase.first; pchan; pchan= pchan->next){
|
||||
if(pchan->bone->layer & arm->layer) {
|
||||
if(pchan->bone->flag & BONE_SELECTED) {
|
||||
/* do we have an ipo curve? */
|
||||
achan= get_action_channel(act, pchan->name);
|
||||
if(achan->ipo) {
|
||||
/*calc_ipo(achan->ipo, ctime);*/
|
||||
do_loc += pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_X), framef, &pchan->loc[0], NULL, NULL);
|
||||
do_loc += pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Y), framef, &pchan->loc[1], NULL, NULL);
|
||||
do_loc += pose_relax_icu(find_ipocurve(achan->ipo, AC_LOC_Z), framef, &pchan->loc[2], NULL, NULL);
|
||||
|
||||
do_scale += pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_X), framef, &pchan->size[0], NULL, NULL);
|
||||
do_scale += pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Y), framef, &pchan->size[1], NULL, NULL);
|
||||
do_scale += pose_relax_icu(find_ipocurve(achan->ipo, AC_SIZE_Z), framef, &pchan->size[2], NULL, NULL);
|
||||
|
||||
if( ((icu_w = find_ipocurve(achan->ipo, AC_QUAT_W))) &&
|
||||
((icu_x = find_ipocurve(achan->ipo, AC_QUAT_X))) &&
|
||||
((icu_y = find_ipocurve(achan->ipo, AC_QUAT_Y))) &&
|
||||
((icu_z = find_ipocurve(achan->ipo, AC_QUAT_Z))) )
|
||||
{
|
||||
/* use the quatw keyframe as a basis for others */
|
||||
if (pose_relax_icu(icu_w, framef, NULL, &frame_prev, &frame_next)) {
|
||||
/* get 2 quats */
|
||||
quat_prev[0] = eval_icu(icu_w, frame_prev);
|
||||
quat_prev[1] = eval_icu(icu_x, frame_prev);
|
||||
quat_prev[2] = eval_icu(icu_y, frame_prev);
|
||||
quat_prev[3] = eval_icu(icu_z, frame_prev);
|
||||
|
||||
quat_next[0] = eval_icu(icu_w, frame_next);
|
||||
quat_next[1] = eval_icu(icu_x, frame_next);
|
||||
quat_next[2] = eval_icu(icu_y, frame_next);
|
||||
quat_next[3] = eval_icu(icu_z, frame_next);
|
||||
|
||||
#if 0
|
||||
/* apply the setting, completely smooth */
|
||||
QuatInterpol(pchan->quat, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) );
|
||||
#else
|
||||
/* tricky interpolation */
|
||||
QuatInterpol(quat_interp, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) );
|
||||
QUATCOPY(quat_orig, pchan->quat);
|
||||
QuatInterpol(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f);
|
||||
/* done */
|
||||
#endif
|
||||
do_quat++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
|
||||
|
||||
/* auto-keyframing */
|
||||
if (do_loc) flag |= TFM_TRANSLATION;
|
||||
if (do_scale) flag |= TFM_RESIZE;
|
||||
if (do_quat) flag |= TFM_ROTATION;
|
||||
autokeyframe_pose_cb_func(ob, flag, 0);
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
||||
BIF_undo_push("Relax Pose");
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user