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
path: root/source
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2009-09-02 04:42:12 +0400
committerJoshua Leung <aligorith@gmail.com>2009-09-02 04:42:12 +0400
commitbd7d26993f32bda6f0c0ca81e1455fb9f55418e3 (patch)
tree855f02594014c28fd056b388ad033ffa2402099b /source
parentf77fc5c3c9461dce9c694e35db736777214f8b2d (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.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenlib/BLI_arithb.h3
-rw-r--r--source/blender/blenlib/intern/arithb.c74
-rw-r--r--source/blender/editors/animation/keyframing.c2
-rw-r--r--source/blender/editors/armature/poseobject.c20
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c4
-rw-r--r--source/blender/editors/transform/transform.c16
-rw-r--r--source/blender/editors/transform/transform.h1
-rw-r--r--source/blender/editors/transform/transform_conversions.c31
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);