[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