diff options
author | Ton Roosendaal <ton@blender.org> | 2007-11-04 20:14:39 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2007-11-04 20:14:39 +0300 |
commit | f996607632e08b7545f61b36ebc651c0ecff75ae (patch) | |
tree | 595f75b0b5edb4a341a62744eda68857b79e72ee /source/blender | |
parent | 034138b597f206aa6cc0c03872597e09b0d84b1f (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!
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/intern/ipo.c | 119 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_curve_types.h | 5 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_ipo_types.h | 2 | ||||
-rw-r--r-- | source/blender/src/drawipo.c | 7 |
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, ""); |