[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [12788] trunk/blender/source/blender: peach request, pose relax - similar to mesh smooth, moves selected pose bones to closer match keyframes on either side.
Campbell Barton
ideasman42 at gmail.com
Tue Dec 4 22:12:23 CET 2007
Revision: 12788
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=12788
Author: campbellbarton
Date: 2007-12-04 22:12:23 +0100 (Tue, 04 Dec 2007)
Log Message:
-----------
peach request, pose relax - similar to mesh smooth, moves selected pose bones to closer match keyframes on either side.
Modified Paths:
--------------
trunk/blender/source/blender/include/BIF_poseobject.h
trunk/blender/source/blender/src/poseobject.c
Modified: trunk/blender/source/blender/include/BIF_poseobject.h
===================================================================
--- trunk/blender/source/blender/include/BIF_poseobject.h 2007-12-04 19:06:00 UTC (rev 12787)
+++ trunk/blender/source/blender/include/BIF_poseobject.h 2007-12-04 21:12:23 UTC (rev 12788)
@@ -67,6 +67,6 @@
void pose_flip_names(void);
void pose_activate_flipped_bone(void);
void pose_movetolayer(void);
-
+void pose_relax(void);
#endif
Modified: trunk/blender/source/blender/src/poseobject.c
===================================================================
--- trunk/blender/source/blender/src/poseobject.c 2007-12-04 19:06:00 UTC (rev 12787)
+++ trunk/blender/source/blender/src/poseobject.c 2007-12-04 21:12:23 UTC (rev 12788)
@@ -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,7 +79,10 @@
#include "mydevice.h"
#include "blendef.h"
+#include "transform.h"
+#include "BIF_transform.h" /* for autokey TFM_TRANSLATION, etc */
+
void enter_posemode(void)
{
Base *base;
@@ -479,7 +484,7 @@
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 @@
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 @@
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");
+
+}
More information about the Bf-blender-cvs
mailing list