[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [27029] trunk/blender: Mathutils API: Euler support for rotation order.
Campbell Barton
ideasman42 at gmail.com
Sat Feb 20 20:49:05 CET 2010
Revision: 27029
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=27029
Author: campbellbarton
Date: 2010-02-20 20:49:04 +0100 (Sat, 20 Feb 2010)
Log Message:
-----------
Mathutils API: Euler support for rotation order.
Examples.
euler = Euler(1, 2, 3)
euler.order = 'ZXY'
euler = matrix.to_euler('XZY')
Still missing rna support. this still wont give the right order, defaulting to XYZ.
eul = object.rotation_euler
Modified Paths:
--------------
trunk/blender/release/scripts/io/export_fbx.py
trunk/blender/source/blender/blenlib/intern/math_rotation.c
trunk/blender/source/blender/python/generic/Mathutils.c
trunk/blender/source/blender/python/generic/Mathutils.h
trunk/blender/source/blender/python/generic/euler.c
trunk/blender/source/blender/python/generic/euler.h
trunk/blender/source/blender/python/generic/matrix.c
trunk/blender/source/blender/python/generic/quat.c
trunk/blender/source/blender/python/generic/vector.c
trunk/blender/source/blender/python/intern/bpy_rna.c
Modified: trunk/blender/release/scripts/io/export_fbx.py
===================================================================
--- trunk/blender/release/scripts/io/export_fbx.py 2010-02-20 15:27:38 UTC (rev 27028)
+++ trunk/blender/release/scripts/io/export_fbx.py 2010-02-20 19:49:04 UTC (rev 27029)
@@ -2876,7 +2876,7 @@
context_bone_anim_vecs = []
prev_eul = None
for mtx in context_bone_anim_mats:
- if prev_eul: prev_eul = mtx[1].to_euler(prev_eul)
+ if prev_eul: prev_eul = mtx[1].to_euler('XYZ', prev_eul)
else: prev_eul = mtx[1].to_euler()
context_bone_anim_vecs.append(eulerRadToDeg(prev_eul))
# context_bone_anim_vecs.append(prev_eul)
Modified: trunk/blender/source/blender/blenlib/intern/math_rotation.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_rotation.c 2010-02-20 15:27:38 UTC (rev 27028)
+++ trunk/blender/source/blender/blenlib/intern/math_rotation.c 2010-02-20 19:49:04 UTC (rev 27029)
@@ -1052,7 +1052,7 @@
{{1, 0, 2}, 1}, // YXZ
{{1, 2, 0}, 0}, // YZX
{{2, 0, 1}, 0}, // ZXY
- {{2, 1, 0}, 1} // ZYZ
+ {{2, 1, 0}, 1} // ZYX
};
/* Get relevant pointer to rotation order set from the array
Modified: trunk/blender/source/blender/python/generic/Mathutils.c
===================================================================
--- trunk/blender/source/blender/python/generic/Mathutils.c 2010-02-20 15:27:38 UTC (rev 27028)
+++ trunk/blender/source/blender/python/generic/Mathutils.c 2010-02-20 19:49:04 UTC (rev 27029)
@@ -170,18 +170,10 @@
}
}
-#ifdef USE_MATHUTILS_DEG
- /* Clamp to -360:360 */
- while (angle<-360.0f)
- angle+=360.0;
- while (angle>360.0f)
- angle-=360.0;
-#else
while (angle<-(Py_PI*2))
angle+=(Py_PI*2);
while (angle>(Py_PI*2))
angle-=(Py_PI*2);
-#endif
if(matSize != 2 && matSize != 3 && matSize != 4) {
PyErr_SetString(PyExc_AttributeError, "Mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n");
@@ -205,10 +197,6 @@
return NULL;
}
-#ifdef USE_MATHUTILS_DEG
- //convert to radians
- angle = angle * (float) (Py_PI / 180);
-#endif
/* check for valid vector/axis above */
if(vec) {
Modified: trunk/blender/source/blender/python/generic/Mathutils.h
===================================================================
--- trunk/blender/source/blender/python/generic/Mathutils.h 2010-02-20 15:27:38 UTC (rev 27028)
+++ trunk/blender/source/blender/python/generic/Mathutils.h 2010-02-20 19:49:04 UTC (rev 27029)
@@ -37,8 +37,6 @@
#include "quat.h"
#include "euler.h"
-/* #define USE_MATHUTILS_DEG - for backwards compat */
-
/* Can cast different mathutils types to this, use for generic funcs */
extern char BaseMathObject_Wrapped_doc[];
Modified: trunk/blender/source/blender/python/generic/euler.c
===================================================================
--- trunk/blender/source/blender/python/generic/euler.c 2010-02-20 15:27:38 UTC (rev 27028)
+++ trunk/blender/source/blender/python/generic/euler.c 2010-02-20 19:49:04 UTC (rev 27029)
@@ -41,6 +41,7 @@
int size, i;
float eul[3];
PyObject *e;
+ short order= 0; // TODO, add order option
size = PyTuple_GET_SIZE(args);
if (size == 1) {
@@ -53,7 +54,7 @@
}
} else if (size == 0) {
//returns a new empty 3d euler
- return newEulerObject(NULL, Py_NEW, NULL);
+ return newEulerObject(NULL, order, Py_NEW, NULL);
} else {
listObject = args;
}
@@ -79,9 +80,26 @@
return NULL;
}
}
- return newEulerObject(eul, Py_NEW, NULL);
+ return newEulerObject(eul, order, Py_NEW, NULL);
}
+short euler_order_from_string(const char *str, const char *error_prefix)
+{
+ if((str[0] && str[1] && str[2] && str[3]=='\0')) {
+ switch(*((int32_t *)str)) {
+ case 'X'|'Y'<<8|'Z'<<16: return 0;
+ case 'X'|'Z'<<8|'Y'<<16: return 1;
+ case 'Y'|'X'<<8|'Z'<<16: return 2;
+ case 'Y'|'Z'<<8|'X'<<16: return 3;
+ case 'Z'|'X'<<8|'Y'<<16: return 4;
+ case 'Z'|'Y'<<8|'X'<<16: return 5;
+ }
+ }
+
+ PyErr_Format(PyExc_TypeError, "%s: invalid euler order '%s'", error_prefix, str);
+ return -1;
+}
+
//-----------------------------METHODS----------------------------
//----------------------------Euler.toQuat()----------------------
//return a quaternion representation of the euler
@@ -97,22 +115,12 @@
static PyObject *Euler_ToQuat(EulerObject * self)
{
float quat[4];
-#ifdef USE_MATHUTILS_DEG
- float eul[3];
- int x;
-#endif
if(!BaseMath_ReadCallback(self))
return NULL;
-#ifdef USE_MATHUTILS_DEG
- for(x = 0; x < 3; x++) {
- eul[x] = self->eul[x] * ((float)Py_PI / 180);
- }
- eul_to_quat( quat,eul);
-#else
- eul_to_quat( quat,self->eul);
-#endif
+ if(self->order==0) eul_to_quat(quat, self->eul);
+ else eulO_to_quat(quat, self->eul, self->order);
return newQuaternionObject(quat, Py_NEW, NULL);
}
@@ -133,24 +141,14 @@
if(!BaseMath_ReadCallback(self))
return NULL;
-#ifdef USE_MATHUTILS_DEG
- {
- float eul[3];
- int x;
-
- for(x = 0; x < 3; x++) {
- eul[x] = self->eul[x] * ((float)Py_PI / 180);
- }
- eul_to_mat3( (float (*)[3]) mat,eul);
- }
-#else
- eul_to_mat3( (float (*)[3]) mat,self->eul);
-#endif
+ if(self->order==0) eul_to_mat3((float (*)[3])mat, self->eul);
+ else eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
+
return newMatrixObject(mat, 3, 3 , Py_NEW, NULL);
}
//----------------------------Euler.unique()-----------------------
//sets the x,y,z values to a unique euler rotation
-
+// TODO, check if this works with rotation order!!!
static char Euler_Unique_doc[] =
".. method:: unique()\n"
"\n"
@@ -170,16 +168,9 @@
if(!BaseMath_ReadCallback(self))
return NULL;
-#ifdef USE_MATHUTILS_DEG
- //radians
- heading = self->eul[0] * (float)Py_PI / 180;
- pitch = self->eul[1] * (float)Py_PI / 180;
- bank = self->eul[2] * (float)Py_PI / 180;
-#else
heading = self->eul[0];
pitch = self->eul[1];
bank = self->eul[2];
-#endif
//wrap heading in +180 / -180
pitch += Py_PI;
@@ -210,13 +201,6 @@
heading -= (floor(heading * PI_INV)) * PI_2;
heading -= Py_PI;
-#ifdef USE_MATHUTILS_DEG
- //back to degrees
- self->eul[0] = (float)(heading * 180 / (float)Py_PI);
- self->eul[1] = (float)(pitch * 180 / (float)Py_PI);
- self->eul[2] = (float)(bank * 180 / (float)Py_PI);
-#endif
-
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
@@ -261,29 +245,9 @@
if(!BaseMath_ReadCallback(self))
return NULL;
-#ifdef USE_MATHUTILS_DEG
- {
- int x;
+ if(self->order == 0) rotate_eul(self->eul, *axis, angle);
+ else rotate_eulO(self->eul, self->order, *axis, angle);
- //covert to radians
- angle *= ((float)Py_PI / 180);
- for(x = 0; x < 3; x++) {
- self->eul[x] *= ((float)Py_PI / 180);
- }
- }
-#endif
- rotate_eul(self->eul, *axis, angle);
-
-#ifdef USE_MATHUTILS_DEG
- {
- int x;
- //convert back from radians
- for(x = 0; x < 3; x++) {
- self->eul[x] *= (180 / (float)Py_PI);
- }
- }
-#endif
-
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
@@ -297,40 +261,27 @@
" :arg other: make compatible with this rotation.\n"
" :type other: :class:`Euler`\n"
" :return: an instance of itself.\n"
-" :rtype: :class:`Euler`\n";
+" :rtype: :class:`Euler`\n"
+"\n"
+" .. note:: the order of eulers must match or an exception is raised.\n";
static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
{
-#ifdef USE_MATHUTILS_DEG
- float eul_from_rad[3];
- int x;
-#endif
-
if(!EulerObject_Check(value)) {
- PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
+ PyErr_SetString(PyExc_TypeError, "euler.make_compatible(euler): expected a single euler argument.");
return NULL;
}
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL;
-#ifdef USE_MATHUTILS_DEG
- //covert to radians
- for(x = 0; x < 3; x++) {
- self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
- eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
+ if(self->order != value->order) {
+ PyErr_SetString(PyExc_ValueError, "euler.make_compatible(euler): rotation orders don't match\n");
+ return NULL;
}
- compatible_eul(self->eul, eul_from_rad);
-#else
+
compatible_eul(self->eul, value->eul);
-#endif
-#ifdef USE_MATHUTILS_DEG
- //convert back from radians
- for(x = 0; x < 3; x++) {
- self->eul[x] *= (180 / (float)Py_PI);
- }
-#endif
BaseMath_WriteCallback(self);
Py_INCREF(self);
return (PyObject *)self;
@@ -354,7 +305,7 @@
if(!BaseMath_ReadCallback(self))
return NULL;
- return newEulerObject(self->eul, Py_NEW, Py_TYPE(self));
+ return newEulerObject(self->eul, self->order, Py_NEW, Py_TYPE(self));
}
//----------------------------print object (internal)--------------
@@ -402,12 +353,7 @@
result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
break;
case Py_NE:
- result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
- if (result == 0){
- result = 1;
- }else{
- result = 0;
- }
+ result = !EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
break;
default:
printf("The result of the comparison could not be evaluated");
@@ -563,6 +509,30 @@
return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
}
+/* rotation order */
+static PyObject *Euler_getOrder(EulerObject *self, void *type)
+{
+ static char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"};
+ return PyUnicode_FromString(order[self->order]);
+}
+
+static int Euler_setOrder( EulerObject * self, PyObject * value, void * type )
+{
+ char *order_str= _PyUnicode_AsString(value);
+ short order= euler_order_from_string(order_str, "euler.order");
+
+ if(order < 0)
+ return -1;
+
+ if(self->cb_user) {
+ PyErr_SetString(PyExc_TypeError, "euler.order: assignment is not allowed on eulers with an owner");
+ return -1;
+ }
+
+ self->order= order;
+ return 0;
+}
+
/*****************************************************************************/
/* Python attributes get/set structure: */
/*****************************************************************************/
@@ -570,6 +540,7 @@
{"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis in radians. **type** float", (void *)0},
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list