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:
Diffstat (limited to 'source/blender/blenlib/intern/arithb.c')
-rw-r--r--source/blender/blenlib/intern/arithb.c74
1 files changed, 67 insertions, 7 deletions
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;