Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2007-11-04 20:14:39 +0300
committerTon Roosendaal <ton@blender.org>2007-11-04 20:14:39 +0300
commitf996607632e08b7545f61b36ebc651c0ecff75ae (patch)
tree595f75b0b5edb4a341a62744eda68857b79e72ee
parent034138b597f206aa6cc0c03872597e09b0d84b1f (diff)
New driver option for the poor suffering riggers:
"Rotation Difference" This option, for Bones, allows the angle between two Bones to be the driver for another Ipo channel. This angle now is hardcoded based on the Bone-space orientation (without parenting rotation). Thanks to nathan for poking and test!
-rw-r--r--source/blender/blenkernel/intern/ipo.c119
-rw-r--r--source/blender/makesdna/DNA_curve_types.h5
-rw-r--r--source/blender/makesdna/DNA_ipo_types.h2
-rw-r--r--source/blender/src/drawipo.c7
4 files changed, 92 insertions, 41 deletions
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 39602f00053..2e8dbccbe53 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -751,6 +751,46 @@ void berekenx(float *f, float *o, int b)
}
}
+#define TFM_WITHOUT_BONE 1
+
+static void posechannel_get_local_transform(bPoseChannel *pchan, float *quat, float *eul, float *size, int flag)
+{
+ float pose_mat[3][3];
+ float diff_mat[3][3], ipar_mat[3][3];
+
+ /* we need the local transform = current transform - (parent transform + bone transform) */
+
+ Mat3CpyMat4(pose_mat, pchan->pose_mat);
+
+ if (pchan->parent) {
+
+ if(flag & TFM_WITHOUT_BONE) {
+ float par_mat[3][3];
+ Mat3CpyMat4(par_mat, pchan->parent->pose_mat);
+ Mat3MulMat3(diff_mat, par_mat, pchan->bone->bone_mat);
+ }
+ else
+ Mat3CpyMat4(diff_mat, pchan->parent->pose_mat);
+
+ Mat3Inv(ipar_mat, diff_mat);
+ }
+ else {
+ if(flag & TFM_WITHOUT_BONE)
+ Mat3Inv(ipar_mat, pchan->bone->bone_mat);
+ else
+ Mat3One(ipar_mat);
+ }
+
+ Mat3MulMat3(diff_mat, ipar_mat, pose_mat);
+
+ if(quat)
+ Mat3ToQuat(diff_mat, quat);
+ if(eul)
+ Mat3ToEul(diff_mat, eul);
+ if(size)
+ Mat3ToSize(diff_mat, size);
+}
+
/* has to return a float value */
static float eval_driver(IpoDriver *driver, float ipotime)
{
@@ -802,48 +842,49 @@ static float eval_driver(IpoDriver *driver, float ipotime)
else { /* ID_AR */
bPoseChannel *pchan= get_pose_channel(ob->pose, driver->name);
if(pchan && pchan->bone) {
- float pose_mat[3][3];
- float diff_mat[3][3], par_mat[3][3], ipar_mat[3][3];
- float eul[3], size[3];
-
- /* we need the local transform = current transform - (parent transform + bone transform) */
- Mat3CpyMat4(pose_mat, pchan->pose_mat);
-
- if (pchan->parent) {
- Mat3CpyMat4(par_mat, pchan->parent->pose_mat);
- Mat3MulMat3(diff_mat, par_mat, pchan->bone->bone_mat);
-
- Mat3Inv(ipar_mat, diff_mat);
+ /* rotation difference is not a simple driver (i.e. value drives value), but the angle between 2 bones is driving stuff... which is useful */
+ if(driver->adrcode==OB_ROT_DIFF) {
+ bPoseChannel *pchan2= get_pose_channel(ob->pose, driver->name+DRIVER_NAME_OFFS);
+ if(pchan2 && pchan2->bone) {
+ float q1[4], q2[4], quat[4], angle;
+
+ posechannel_get_local_transform(pchan , q1, NULL, NULL, 0);
+ posechannel_get_local_transform(pchan2, q2, NULL, NULL, 0);
+
+ QuatInv(q1);
+ QuatMul(quat, q1, q2);
+ angle = 2.0f * (saacos(quat[0]));
+ angle= ABS(angle);
+
+ return angle>M_PI?2.0f*M_PI-angle:angle;
+ }
}
else {
- Mat3Inv(ipar_mat, pchan->bone->bone_mat);
- }
-
- Mat3MulMat3(diff_mat, ipar_mat, pose_mat);
-
- Mat3ToEul(diff_mat, eul);
- Mat3ToSize(diff_mat, size);
-
- switch(driver->adrcode) {
- case OB_LOC_X:
- return pchan->loc[0];
- case OB_LOC_Y:
- return pchan->loc[1];
- case OB_LOC_Z:
- return pchan->loc[2];
- case OB_ROT_X:
- return eul[0]/(M_PI_2/9.0);
- case OB_ROT_Y:
- return eul[1]/(M_PI_2/9.0);
- case OB_ROT_Z:
- return eul[2]/(M_PI_2/9.0);
- case OB_SIZE_X:
- return size[0];
- case OB_SIZE_Y:
- return size[1];
- case OB_SIZE_Z:
- return size[2];
+ float eul[3], size[3];
+
+ posechannel_get_local_transform(pchan, NULL, eul, size, TFM_WITHOUT_BONE);
+
+ switch(driver->adrcode) {
+ case OB_LOC_X:
+ return pchan->loc[0];
+ case OB_LOC_Y:
+ return pchan->loc[1];
+ case OB_LOC_Z:
+ return pchan->loc[2];
+ case OB_ROT_X:
+ return eul[0]/(M_PI_2/9.0);
+ case OB_ROT_Y:
+ return eul[1]/(M_PI_2/9.0);
+ case OB_ROT_Z:
+ return eul[2]/(M_PI_2/9.0);
+ case OB_SIZE_X:
+ return size[0];
+ case OB_SIZE_Y:
+ return size[1];
+ case OB_SIZE_Z:
+ return size[2];
+ }
}
}
}
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index bd772bbeecb..807fc2add07 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -193,9 +193,12 @@ typedef struct Curve {
typedef struct IpoDriver {
struct Object *ob;
short blocktype, adrcode, type, flag;
- char name[128]; /* bone or constraint(?), or python expression here */
+ char name[128]; /* bone or constraint(?), or python expression here */
} IpoDriver;
+/* temp? we store more bone names in 1 driver... */
+#define DRIVER_NAME_OFFS 32
+
typedef struct IpoCurve {
struct IpoCurve *next, *prev;
diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h
index 57f44e22334..1fca73b576c 100644
--- a/source/blender/makesdna/DNA_ipo_types.h
+++ b/source/blender/makesdna/DNA_ipo_types.h
@@ -108,6 +108,8 @@ typedef short IPO_Channel;
#define OB_PD_RDAMP 28
#define OB_PD_PERM 29
+/* exception: driver channel, for bone driver only */
+#define OB_ROT_DIFF 100
/* ******************** */
diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c
index f8fec5f6b7f..d9ef3349ec1 100644
--- a/source/blender/src/drawipo.c
+++ b/source/blender/src/drawipo.c
@@ -2031,6 +2031,7 @@ static char *ipodriver_channelselect_pup(void)
tmp+= sprintf(tmp, "|Scale X %%x%d", OB_SIZE_X);
tmp+= sprintf(tmp, "|Scale Y %%x%d", OB_SIZE_Y);
tmp+= sprintf(tmp, "|Scale Z %%x%d", OB_SIZE_Z);
+ tmp+= sprintf(tmp, "|Rotation Differance %%x%d", OB_ROT_DIFF);
return (string);
}
@@ -2081,6 +2082,10 @@ static void ipo_panel_properties(short cntrl) // IPO_HANDLER_PROPERTIES
if(driver->ob->type==OB_ARMATURE && driver->blocktype==ID_AR) {
icon = ICON_POSE_DEHLT;
uiDefBut(block, TEX, B_IPO_REDR, "BO:", 10,220,150,20, driver->name, 0, 31, 0, 0, "Bone name");
+
+ if(driver->adrcode==OB_ROT_DIFF)
+ uiDefBut(block, TEX, B_IPO_REDR, "BO:", 10,200,150,20, driver->name+DRIVER_NAME_OFFS, 0, 31, 0, 0, "Bone name for angular reference");
+
}
else driver->blocktype= ID_OB; /* safety when switching object button */
@@ -2106,7 +2111,7 @@ static void ipo_panel_properties(short cntrl) // IPO_HANDLER_PROPERTIES
/* note ranges for buttons below are idiot... we need 2 ranges, one for sliding scale, one for real clip */
if(G.sipo->ipo && G.sipo->ipo->curve.first && totipo_curve) {
extern int totipo_vertsel; // editipo.c
- uiDefBut(block, LABEL, 0, "Visible curves", 10, 200, 150, 19, NULL, 1.0, 0.0, 0, 0, "");
+ uiDefBut(block, LABEL, 0, "Visible curves", 160, 200, 150, 19, NULL, 1.0, 0.0, 0, 0, "");
uiBlockBeginAlign(block);
uiDefButF(block, NUM, B_MUL_IPO, "Xmin:", 10, 180, 150, 19, &G.sipo->tot.xmin, G.sipo->tot.xmin-1000.0, MAXFRAMEF, 100, 0, "");