diff options
author | Joshua Leung <aligorith@gmail.com> | 2009-09-02 04:42:12 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2009-09-02 04:42:12 +0400 |
commit | bd7d26993f32bda6f0c0ca81e1455fb9f55418e3 (patch) | |
tree | 855f02594014c28fd056b388ad033ffa2402099b | |
parent | f77fc5c3c9461dce9c694e35db736777214f8b2d (diff) |
2.5 - Rotation Order Tweaks for Armature Bones
* All tools where rotation order matters for armature bones have now been adjusted to use the new code
* Transform now uses the new code for bones too. However, there are some jumping issues here that I'm not too sure how to solve yet. Help fixing this is welcome.
-rw-r--r-- | source/blender/blenlib/BLI_arithb.h | 3 | ||||
-rw-r--r-- | source/blender/blenlib/intern/arithb.c | 74 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframing.c | 2 | ||||
-rw-r--r-- | source/blender/editors/armature/poseobject.c | 20 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_buttons.c | 4 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 16 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.h | 1 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 31 |
8 files changed, 113 insertions, 38 deletions
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 4156e3c52ec..5f3622e8aa5 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -193,6 +193,7 @@ typedef enum eEulerRotationOrders { } eEulerRotationOrders; void EulOToQuat(float eul[3], short order, float quat[4]); +void QuatToEulO(float quat[4], float eul[3], short order); void EulOToMat3(float eul[3], short order, float Mat[3][3]); void EulOToMat4(float eul[3], short order, float Mat[4][4]); @@ -200,7 +201,7 @@ void EulOToMat4(float eul[3], short order, float Mat[4][4]); void Mat3ToEulO(float Mat[3][3], float eul[3], short order); void Mat4ToEulO(float Mat[4][4], float eul[3], short order); -void QuatToEulO(float quat[4], float eul[3], short order); +void Mat3ToCompatibleEulO(float mat[3][3], float eul[3], float oldrot[3], short order); /** * @section Euler conversion routines (Blender XYZ) diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index e0f17864d73..64fb7d78ef1 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -2825,7 +2825,8 @@ static RotOrderInfo rotOrders[]= { * NOTE: since we start at 1 for the values, but arrays index from 0, * there is -1 factor involved in this process... */ -#define GET_ROTATIONORDER_INFO(order) (&rotOrders[(order)-1]) +// FIXME: what happens when invalid order given +#define GET_ROTATIONORDER_INFO(order) (((order)>=1) ? &rotOrders[(order)-1] : &rotOrders[0]) /* Construct quaternion from Euler angles (in radians). */ void EulOToQuat(float e[3], short order, float q[4]) @@ -2857,6 +2858,15 @@ void EulOToQuat(float e[3], short order, float q[4]) if (R->parity) q[j] = -q[j]; } +/* Convert quaternion to Euler angles (in radians). */ +void QuatToEulO(float q[4], float e[3], short order) +{ + float M[3][3]; + + QuatToMat3(q, M); + Mat3ToEulO(M, e, order); +} + /* Construct 3x3 matrix from Euler angles (in radians). */ void EulOToMat3(float e[3], short order, float M[3][3]) { @@ -2929,15 +2939,65 @@ void Mat4ToEulO(float M[4][4], float e[3], short order) Mat3ToEulO(m, e, order); } -/* Convert quaternion to Euler angles (in radians). */ -void QuatToEulO(float q[4], float e[3], short order) +/* returns two euler calculation methods, so we can pick the best */ +static void mat3_to_eulo2(float M[3][3], float *e1, float *e2, short order) { - float M[3][3]; + RotOrderInfo *R= GET_ROTATIONORDER_INFO(order); + short i=R->i, j=R->j, k=R->k; + double cy = sqrt(M[i][i]*M[i][i] + M[j][i]*M[j][i]); - QuatToMat3(q, M); - Mat3ToEulO(M, e, order); + if (cy > 16*FLT_EPSILON) { + e1[0] = atan2(M[j][k], M[k][k]); + e1[1] = atan2(-M[i][k], cy); + e1[2] = atan2(M[i][j], M[i][i]); + + e2[0] = atan2(-M[j][k], -M[k][k]); + e2[1] = atan2(-M[i][k], -cy); + e2[2] = atan2(-M[i][j], -M[i][i]); + } + else { + e1[0] = atan2(-M[k][j], M[j][j]); + e1[1] = atan2(-M[i][k], cy); + e1[2] = 0; + + VecCopyf(e2, e1); + } + + if (R->parity) { + e1[0] = -e1[0]; + e1[1] = -e1[1]; + e1[2] = -e1[2]; + + e2[0] = -e2[0]; + e2[1] = -e2[1]; + e2[2] = -e2[2]; + } +} + +/* uses 2 methods to retrieve eulers, and picks the closest */ +// FIXME: this does not work well with the other rotation modes... +void Mat3ToCompatibleEulO(float mat[3][3], float eul[3], float oldrot[3], short order) +{ + float eul1[3], eul2[3]; + float d1, d2; + + mat3_to_eulo2(mat, eul1, eul2, order); + + compatible_eul(eul1, oldrot); + compatible_eul(eul2, oldrot); + + d1= (float)fabs(eul1[0]-oldrot[0]) + (float)fabs(eul1[1]-oldrot[1]) + (float)fabs(eul1[2]-oldrot[2]); + d2= (float)fabs(eul2[0]-oldrot[0]) + (float)fabs(eul2[1]-oldrot[1]) + (float)fabs(eul2[2]-oldrot[2]); + + /* return best, which is just the one with lowest difference */ + if (d1 > d2) + VecCopyf(eul, eul2); + else + VecCopyf(eul, eul1); } + + /* ************ EULER (old XYZ) *************** */ /* XYZ order */ @@ -3102,7 +3162,7 @@ void euler_rot(float *beul, float ang, char axis) } /* exported to transform.c */ -/* XYZ order */ +/* order independent! */ void compatible_eul(float *eul, float *oldrot) { float dx, dy, dz; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index dc73011549c..5f444609baa 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -704,7 +704,7 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_ float eul[3]; /* euler-rotation test before standard rotation, as standard rotation does quats */ - Mat4ToEul(tmat, eul); + Mat4ToEulO(tmat, eul, pchan->rotmode); return eul[array_index]; } else if (strstr(identifier, "rotation")) { diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 5b378878f91..9a72fce2bcf 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -760,6 +760,7 @@ void pose_copy_menu(Scene *scene) break; case 2: /* Local Rotation */ QUATCOPY(pchan->quat, pchanact->quat); + VECCOPY(pchan->eul, pchanact->eul); break; case 3: /* Local Size */ VECCOPY(pchan->size, pchanact->size); @@ -808,11 +809,14 @@ void pose_copy_menu(Scene *scene) break; case 10: /* Visual Rotation */ { - float delta_mat[4][4], quat[4]; + float delta_mat[4][4]; armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat); - Mat4ToQuat(delta_mat, quat); - QUATCOPY(pchan->quat, quat); + + if (pchan->rotmode > 0) + Mat4ToEulO(delta_mat, pchan->eul, pchan->rotmode); + else + Mat4ToQuat(delta_mat, pchan->quat); } break; case 11: /* Visual Size */ @@ -990,20 +994,20 @@ static int pose_paste_exec (bContext *C, wmOperator *op) /* check if rotation modes are compatible (i.e. do they need any conversions) */ if (pchan->rotmode == chan->rotmode) { /* copy the type of rotation in use */ - if (pchan->rotmode) { + if (pchan->rotmode > 0) { VECCOPY(pchan->eul, chan->eul); } else { QUATCOPY(pchan->quat, chan->quat); } } - else if (pchan->rotmode) { + else if (pchan->rotmode > 0) { /* quat to euler */ - QuatToEul(chan->quat, pchan->eul); + QuatToEulO(chan->quat, pchan->eul, pchan->rotmode); } else { /* euler to quat */ - EulToQuat(chan->eul, pchan->quat); + EulOToQuat(chan->eul, chan->rotmode, pchan->quat); } /* paste flipped pose? */ @@ -1011,7 +1015,7 @@ static int pose_paste_exec (bContext *C, wmOperator *op) pchan->loc[0]*= -1; /* has to be done as eulers... */ - if (pchan->rotmode) { + if (pchan->rotmode > 0) { pchan->eul[1] *= -1; pchan->eul[2] *= -1; } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 2fbe7e5db79..7c305d59866 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -512,7 +512,7 @@ static void v3d_posearmature_buts(uiBlock *block, View3D *v3d, Object *ob, float uiButSetFunc(but, validate_bonebutton_cb, bone, NULL); uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob); - QuatToEul(pchan->quat, tfp->ob_eul); + QuatToEulO(pchan->quat, tfp->ob_eul, pchan->rotmode); // XXX? tfp->ob_eul[0]*= 180.0/M_PI; tfp->ob_eul[1]*= 180.0/M_PI; tfp->ob_eul[2]*= 180.0/M_PI; @@ -841,7 +841,7 @@ static void do_view3d_region_buttons(bContext *C, void *arg, int event) eul[0]= M_PI*tfp->ob_eul[0]/180.0; eul[1]= M_PI*tfp->ob_eul[1]/180.0; eul[2]= M_PI*tfp->ob_eul[2]/180.0; - EulToQuat(eul, pchan->quat); + EulOToQuat(eul, pchan->rotmode, pchan->quat); // xxx? } /* no break, pass on */ case B_ARMATUREPANEL2: diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 4a376f35552..f0de28476f0 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2670,21 +2670,21 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short /* this function works on end result */ protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); } - else { // TODO: need some methods for the new euler types... + else { float eulmat[3][3]; - + Mat3MulMat3(totmat, mat, td->mtx); Mat3MulMat3(smat, td->smtx, totmat); - + /* calculate the total rotatation in eulers */ VECCOPY(eul, td->ext->irot); - EulToMat3(eul, eulmat); - + EulOToMat3(eul, td->rotOrder, eulmat); + /* mat = transform, obmat = bone rotation */ Mat3MulMat3(fmat, smat, eulmat); - - Mat3ToCompatibleEul(fmat, eul, td->ext->rot); - + + Mat3ToCompatibleEulO(fmat, eul, td->ext->rot, td->rotOrder); + /* and apply (to end result only) */ protectedRotateBits(td->protectflag, eul, td->ext->irot); VECCOPY(td->ext->rot, eul); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index efa60b15293..e5bd405c0cd 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -199,6 +199,7 @@ typedef struct TransData { void *extra; /* extra data (mirrored element pointer, in editmode mesh to EditVert) (editbone for roll fixing) (...) */ short flag; /* Various flags */ short protectflag; /* If set, copy of Object or PoseChannel protection */ + int rotOrder; /* rotation order (for eulers), as defined in BLI_arithb.h */ } TransData; typedef struct MouseInput { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 86d3af31c85..e0dfd90a3d1 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -502,22 +502,29 @@ static short apply_targetless_ik(Object *ob) /* apply and decompose, doesn't work for constraints or non-uniform scale well */ { - float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3]; + float rmat3[3][3], qrmat[3][3], imat[3][3], smat[3][3]; Mat3CpyMat4(rmat3, rmat); - - /* quaternion */ - Mat3ToQuat(rmat3, parchan->quat); - + + /* rotation */ + if (parchan->rotmode > 0) + Mat3ToEulO(rmat3, parchan->eul, parchan->rotmode); + else + Mat3ToQuat(rmat3, parchan->quat); + /* for size, remove rotation */ /* causes problems with some constraints (so apply only if needed) */ if (data->flag & CONSTRAINT_IK_STRETCH) { - QuatToMat3(parchan->quat, qmat); - Mat3Inv(imat, qmat); + if (parchan->rotmode > 0) + EulOToMat3(parchan->eul, parchan->rotmode, qrmat); + else + QuatToMat3(parchan->quat, qrmat); + + Mat3Inv(imat, qrmat); Mat3MulMat3(smat, rmat3, imat); Mat3ToSize(smat, parchan->size); } - + /* causes problems with some constraints (e.g. childof), so disable this */ /* as it is IK shouldn't affect location directly */ /* VECCOPY(parchan->loc, rmat[3]); */ @@ -568,18 +575,20 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr td->ext->size= pchan->size; VECCOPY(td->ext->isize, pchan->size); - if (pchan->rotmode) { + if (pchan->rotmode > 0) { td->ext->rot= pchan->eul; td->ext->quat= NULL; - + VECCOPY(td->ext->irot, pchan->eul); + td->rotOrder= pchan->rotmode; } else { td->ext->rot= NULL; td->ext->quat= pchan->quat; - + QUATCOPY(td->ext->iquat, pchan->quat); } + /* proper way to get parent transform + own transform + constraints transform */ Mat3CpyMat4(omat, ob->obmat); |