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:
authorCampbell Barton <ideasman42@gmail.com>2010-02-20 22:49:04 +0300
committerCampbell Barton <ideasman42@gmail.com>2010-02-20 22:49:04 +0300
commit02e7871149fb369a12725a319cb09accad7790b9 (patch)
treea089869d8044c79f3d3031923492393961eef53a /source
parent65a4dafcff41f8575263095b62437f854bdeb2b4 (diff)
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
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenlib/intern/math_rotation.c2
-rw-r--r--source/blender/python/generic/Mathutils.c12
-rw-r--r--source/blender/python/generic/Mathutils.h2
-rw-r--r--source/blender/python/generic/euler.c163
-rw-r--r--source/blender/python/generic/euler.h9
-rw-r--r--source/blender/python/generic/matrix.c73
-rw-r--r--source/blender/python/generic/quat.c63
-rw-r--r--source/blender/python/generic/vector.c30
-rw-r--r--source/blender/python/intern/bpy_rna.c13
9 files changed, 157 insertions, 210 deletions
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 8d0130a52c2..8d5684a3ac8 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -1052,7 +1052,7 @@ static RotOrderInfo rotOrders[]= {
{{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
diff --git a/source/blender/python/generic/Mathutils.c b/source/blender/python/generic/Mathutils.c
index 3675c5946de..0ded2b18264 100644
--- a/source/blender/python/generic/Mathutils.c
+++ b/source/blender/python/generic/Mathutils.c
@@ -170,18 +170,10 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
}
}
-#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 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
return NULL;
}
-#ifdef USE_MATHUTILS_DEG
- //convert to radians
- angle = angle * (float) (Py_PI / 180);
-#endif
/* check for valid vector/axis above */
if(vec) {
diff --git a/source/blender/python/generic/Mathutils.h b/source/blender/python/generic/Mathutils.h
index e8b1fc2ed28..d0b90341cd2 100644
--- a/source/blender/python/generic/Mathutils.h
+++ b/source/blender/python/generic/Mathutils.h
@@ -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[];
diff --git a/source/blender/python/generic/euler.c b/source/blender/python/generic/euler.c
index bbfd6cb43cf..7e5be428868 100644
--- a/source/blender/python/generic/euler.c
+++ b/source/blender/python/generic/euler.c
@@ -41,6 +41,7 @@ static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwar
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 @@ static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwar
}
} 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,7 +80,24 @@ static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwar
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----------------------------
@@ -97,22 +115,12 @@ static char Euler_ToQuat_doc[] =
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 @@ static PyObject *Euler_ToMatrix(EulerObject * self)
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 @@ static PyObject *Euler_Unique(EulerObject * self)
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 @@ static PyObject *Euler_Unique(EulerObject * self)
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,28 +245,8 @@ static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
if(!BaseMath_ReadCallback(self))
return NULL;
-#ifdef USE_MATHUTILS_DEG
- {
- int x;
-
- //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
+ if(self->order == 0) rotate_eul(self->eul, *axis, angle);
+ else rotate_eulO(self->eul, self->order, *axis, angle);
BaseMath_WriteCallback(self);
Py_INCREF(self);
@@ -297,40 +261,27 @@ static char Euler_MakeCompatible_doc[] =
" :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 @@ static PyObject *Euler_copy(EulerObject * self, PyObject *args)
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 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar
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 @@ static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
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 @@ static PyGetSetDef Euler_getseters[] = {
{"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis in radians. **type** float", (void *)0},
{"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis in radians. **type** float", (void *)1},
{"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis in radians. **type** float", (void *)2},
+ {"order", (getter)Euler_getOrder, (setter)Euler_setOrder, "Euler rotation order. **type** string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']", (void *)NULL},
{"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
{"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
@@ -650,7 +621,7 @@ PyTypeObject euler_Type = {
(i.e. it was allocated elsewhere by MEM_mallocN())
pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
(i.e. it must be created here with PyMEM_malloc())*/
-PyObject *newEulerObject(float *eul, int type, PyTypeObject *base_type)
+PyObject *newEulerObject(float *eul, short order, int type, PyTypeObject *base_type)
{
EulerObject *self;
int x;
@@ -678,12 +649,14 @@ PyObject *newEulerObject(float *eul, int type, PyTypeObject *base_type)
}else{ //bad type
return NULL;
}
+
+ self->order= order;
return (PyObject *)self;
}
-PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
+PyObject *newEulerObject_cb(PyObject *cb_user, short order, int cb_type, int cb_subtype)
{
- EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW, NULL);
+ EulerObject *self= (EulerObject *)newEulerObject(NULL, order, Py_NEW, NULL);
if(self) {
Py_INCREF(cb_user);
self->cb_user= cb_user;
diff --git a/source/blender/python/generic/euler.h b/source/blender/python/generic/euler.h
index e9826814165..994a5f1780e 100644
--- a/source/blender/python/generic/euler.h
+++ b/source/blender/python/generic/euler.h
@@ -45,6 +45,8 @@ typedef struct {
unsigned char wrapped; /* wrapped data type? */
/* end BaseMathObject */
+ unsigned char order; /* rotation order */
+
} EulerObject;
/*struct data contains a pointer to the actual data that the
@@ -53,7 +55,10 @@ be stored in py_data) or be a wrapper for data allocated through
blender (stored in blend_data). This is an either/or struct not both*/
//prototypes
-PyObject *newEulerObject( float *eul, int type, PyTypeObject *base_type);
-PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
+PyObject *newEulerObject( float *eul, short order, int type, PyTypeObject *base_type);
+PyObject *newEulerObject_cb(PyObject *cb_user, short order, int cb_type, int cb_subtype);
+
+short euler_order_from_string(const char *str, const char *error_prefix);
+
#endif /* EXPP_euler_h */
diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c
index 23906161db2..71b471c61ed 100644
--- a/source/blender/python/generic/matrix.c
+++ b/source/blender/python/generic/matrix.c
@@ -217,7 +217,7 @@ static PyObject *Matrix_toQuat(MatrixObject * self)
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->colSize < 3 || self->rowSize < 3 || (self->colSize != self->rowSize)) {
- PyErr_SetString(PyExc_AttributeError, "Matrix.toQuat(): inappropriate matrix size - expects 3x3 or 4x4 matrix");
+ PyErr_SetString(PyExc_AttributeError, "Matrix.to_quat(): inappropriate matrix size - expects 3x3 or 4x4 matrix");
return NULL;
}
if(self->colSize == 3){
@@ -228,12 +228,15 @@ static PyObject *Matrix_toQuat(MatrixObject * self)
return newQuaternionObject(quat, Py_NEW, NULL);
}
+
/*---------------------------Matrix.toEuler() --------------------*/
static char Matrix_toEuler_doc[] =
-".. method:: to_euler(euler_compat)\n"
+".. method:: to_euler(order, euler_compat)\n"
"\n"
" Return an Euler representation of the rotation matrix (3x3 or 4x4 matrix only).\n"
"\n"
+" :arg order: Optional rotation order argument in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
+" :type order: string\n"
" :arg euler_compat: Optional euler argument the new euler will be made compatible with (no axis flipping between them). Useful for converting a series of matrices to animation curves.\n"
" :type euler_compat: :class:`Euler`\n"
" :return: Euler representation of the matrix.\n"
@@ -241,53 +244,55 @@ static char Matrix_toEuler_doc[] =
PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args)
{
+ char *order_str= NULL;
+ short order= 0;
float eul[3], eul_compatf[3];
EulerObject *eul_compat = NULL;
-#ifdef USE_MATHUTILS_DEG
- int x;
-#endif
+
+ float tmat[3][3];
+ float (*mat)[3];
if(!BaseMath_ReadCallback(self))
return NULL;
- if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
+ if(!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
return NULL;
if(eul_compat) {
if(!BaseMath_ReadCallback(eul_compat))
return NULL;
-#ifdef USE_MATHUTILS_DEG
- for(x = 0; x < 3; x++) {
- eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
- }
-#else
VECCOPY(eul_compatf, eul_compat->eul);
-#endif
}
/*must be 3-4 cols, 3-4 rows, square matrix*/
if(self->colSize ==3 && self->rowSize ==3) {
- if(eul_compat) mat3_to_compatible_eul( eul, eul_compatf,(float (*)[3])*self->matrix);
- else mat3_to_eul( eul,(float (*)[3])*self->matrix);
+ mat= (float (*)[3])self->matrix;
}else if (self->colSize ==4 && self->rowSize ==4) {
- float tempmat3[3][3];
- copy_m3_m4(tempmat3, (float (*)[4])*self->matrix);
- mat3_to_eul( eul,tempmat3);
- if(eul_compat) mat3_to_compatible_eul( eul, eul_compatf,tempmat3);
- else mat3_to_eul( eul,tempmat3);
-
+ copy_m3_m4(tmat, (float (*)[4])*self->matrix);
+ mat= tmat;
}else {
- PyErr_SetString(PyExc_AttributeError, "Matrix.toEuler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
+ PyErr_SetString(PyExc_AttributeError, "Matrix.to_euler(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
return NULL;
}
-#ifdef USE_MATHUTILS_DEG
- /*have to convert to degrees*/
- for(x = 0; x < 3; x++) {
- eul[x] *= (float) (180 / Py_PI);
+
+ if(order_str) {
+ order= euler_order_from_string(order_str, "Matrix.to_euler()");
+
+ if(order < 0)
+ return NULL;
+ }
+
+ if(eul_compat) {
+ if(order == 0) mat3_to_compatible_eul( eul, eul_compatf, mat);
+ else mat3_to_compatible_eulO(eul, eul_compatf, order, mat);
+ }
+ else {
+ if(order == 0) mat3_to_eul(eul, mat);
+ else mat3_to_eulO(eul, order, mat);
}
-#endif
- return newEulerObject(eul, Py_NEW, NULL);
+
+ return newEulerObject(eul, order, Py_NEW, NULL);
}
/*---------------------------Matrix.resize4x4() ------------------*/
static char Matrix_Resize4x4_doc[] =
@@ -367,21 +372,15 @@ static char Matrix_TranslationPart_doc[] =
PyObject *Matrix_TranslationPart(MatrixObject * self)
{
- float vec[4];
-
if(!BaseMath_ReadCallback(self))
return NULL;
if(self->colSize < 3 || self->rowSize < 4){
- PyErr_SetString(PyExc_AttributeError, "Matrix.translationPart: inappropriate matrix size");
+ PyErr_SetString(PyExc_AttributeError, "Matrix.translation_part(): inappropriate matrix size");
return NULL;
}
- vec[0] = self->matrix[3][0];
- vec[1] = self->matrix[3][1];
- vec[2] = self->matrix[3][2];
-
- return newVectorObject(vec, 3, Py_NEW, NULL);
+ return newVectorObject(self->matrix[3], 3, Py_NEW, NULL);
}
/*---------------------------Matrix.rotationPart() ---------------*/
static char Matrix_RotationPart_doc[] =
@@ -403,7 +402,7 @@ PyObject *Matrix_RotationPart(MatrixObject * self)
return NULL;
if(self->colSize < 3 || self->rowSize < 3){
- PyErr_SetString(PyExc_AttributeError, "Matrix.rotationPart: inappropriate matrix size\n");
+ PyErr_SetString(PyExc_AttributeError, "Matrix.rotation_part(): inappropriate matrix size\n");
return NULL;
}
@@ -444,7 +443,7 @@ PyObject *Matrix_scalePart(MatrixObject * self)
else if(self->colSize == 3 && self->rowSize == 3)
copy_m3_m3(mat, (float (*)[3])*self->matrix);
else {
- PyErr_SetString(PyExc_AttributeError, "Matrix.scalePart(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
+ PyErr_SetString(PyExc_AttributeError, "Matrix.scale_part(): inappropriate matrix size - expects 3x3 or 4x4 matrix\n");
return NULL;
}
/* functionality copied from editobject.c apply_obmat */
diff --git a/source/blender/python/generic/quat.c b/source/blender/python/generic/quat.c
index ee9dd6606ac..7a8733c970f 100644
--- a/source/blender/python/generic/quat.c
+++ b/source/blender/python/generic/quat.c
@@ -34,10 +34,12 @@
//-----------------------------METHODS------------------------------
static char Quaternion_ToEuler_doc[] =
-".. method:: to_euler(euler_compat)\n"
+".. method:: to_euler(order, euler_compat)\n"
"\n"
" Return Euler representation of the quaternion.\n"
"\n"
+" :arg order: Optional rotation order argument in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
+" :type order: string\n"
" :arg euler_compat: Optional euler argument the new euler will be made compatible with (no axis flipping between them). Useful for converting a series of matrices to animation curves.\n"
" :type euler_compat: :class:`Euler`\n"
" :return: Euler representation of the quaternion.\n"
@@ -46,50 +48,40 @@ static char Quaternion_ToEuler_doc[] =
static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
{
float eul[3];
+ char *order_str= NULL;
+ short order= 0;
EulerObject *eul_compat = NULL;
- if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
+ if(!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
return NULL;
if(!BaseMath_ReadCallback(self))
return NULL;
+ if(order_str) {
+ order= euler_order_from_string(order_str, "Matrix.to_euler()");
+
+ if(order < 0)
+ return NULL;
+ }
+
if(eul_compat) {
float mat[3][3];
if(!BaseMath_ReadCallback(eul_compat))
return NULL;
- quat_to_mat3( mat,self->quat);
-
-#ifdef USE_MATHUTILS_DEG
- {
- float eul_compatf[3];
- int x;
+ quat_to_mat3(mat, self->quat);
- for(x = 0; x < 3; x++) {
- eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
- }
- mat3_to_compatible_eul( eul, eul_compatf,mat);
- }
-#else
- mat3_to_compatible_eul( eul, eul_compat->eul,mat);
-#endif
+ if(order == 0) mat3_to_compatible_eul(eul, eul_compat->eul, mat);
+ else mat3_to_compatible_eulO(eul, order, eul_compat->eul, mat);
}
else {
- quat_to_eul( eul,self->quat);
+ if(order == 0) quat_to_eul(eul, self->quat);
+ else quat_to_eulO(eul, order, self->quat);
}
-#ifdef USE_MATHUTILS_DEG
- {
- int x;
-
- for(x = 0; x < 3; x++) {
- eul[x] *= (180 / (float)Py_PI);
- }
- }
-#endif
- return newEulerObject(eul, Py_NEW, NULL);
+ return newEulerObject(eul, order, Py_NEW, NULL);
}
//----------------------------Quaternion.toMatrix()------------------
static char Quaternion_ToMatrix_doc[] =
@@ -218,8 +210,8 @@ static PyObject *Quaternion_Slerp(QuaternionObject *self, PyObject *args)
QuaternionObject *value;
float quat[4], fac;
- if(!PyArg_ParseTuple(args, "O!f", &quaternion_Type, &value, &fac)) {
- PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float");
+ if(!PyArg_ParseTuple(args, "O!f:slerp", &quaternion_Type, &value, &fac)) {
+ PyErr_SetString(PyExc_TypeError, "quat.slerp(): expected Quaternion types and float");
return NULL;
}
@@ -227,7 +219,7 @@ static PyObject *Quaternion_Slerp(QuaternionObject *self, PyObject *args)
return NULL;
if(fac > 1.0f || fac < 0.0f) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0");
+ PyErr_SetString(PyExc_AttributeError, "quat.slerp(): interpolation factor must be between 0.0 and 1.0");
return NULL;
}
@@ -698,12 +690,7 @@ static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type )
static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type )
{
- double ang = self->quat[0];
- ang = 2 * (saacos(ang));
-#ifdef USE_MATHUTILS_DEG
- ang *= (180 / Py_PI);
-#endif
- return PyFloat_FromDouble(ang);
+ return PyFloat_FromDouble(2.0 * (saacos(self->quat[0])));
}
static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
@@ -815,11 +802,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
}
if(size == 3) //calculate the quat based on axis/angle
-#ifdef USE_MATHUTILS_DEG
- axis_angle_to_quat(quat, quat, angle * (Py_PI / 180));
-#else
axis_angle_to_quat(quat, quat, angle);
-#endif
return newQuaternionObject(quat, Py_NEW, NULL);
}
diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c
index 06e0a0480b4..d5ff44ae5ad 100644
--- a/source/blender/python/generic/vector.c
+++ b/source/blender/python/generic/vector.c
@@ -159,17 +159,17 @@ static char Vector_Resize2D_doc[] =
static PyObject *Vector_Resize2D(VectorObject * self)
{
if(self->wrapped==Py_WRAP) {
- PyErr_SetString(PyExc_TypeError, "vector.resize2d(): cannot resize wrapped data - only python vectors\n");
+ PyErr_SetString(PyExc_TypeError, "vector.resize2D(): cannot resize wrapped data - only python vectors\n");
return NULL;
}
if(self->cb_user) {
- PyErr_SetString(PyExc_TypeError, "vector.resize2d(): cannot resize a vector that has an owner");
+ PyErr_SetString(PyExc_TypeError, "vector.resize2D(): cannot resize a vector that has an owner");
return NULL;
}
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2));
if(self->vec == NULL) {
- PyErr_SetString(PyExc_MemoryError, "vector.resize2d(): problem allocating pointer space\n\n");
+ PyErr_SetString(PyExc_MemoryError, "vector.resize2D(): problem allocating pointer space\n\n");
return NULL;
}
@@ -189,17 +189,17 @@ static char Vector_Resize3D_doc[] =
static PyObject *Vector_Resize3D(VectorObject * self)
{
if (self->wrapped==Py_WRAP) {
- PyErr_SetString(PyExc_TypeError, "vector.resize3d(): cannot resize wrapped data - only python vectors\n");
+ PyErr_SetString(PyExc_TypeError, "vector.resize3D(): cannot resize wrapped data - only python vectors\n");
return NULL;
}
if(self->cb_user) {
- PyErr_SetString(PyExc_TypeError, "vector.resize3d(): cannot resize a vector that has an owner");
+ PyErr_SetString(PyExc_TypeError, "vector.resize3D(): cannot resize a vector that has an owner");
return NULL;
}
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3));
if(self->vec == NULL) {
- PyErr_SetString(PyExc_MemoryError, "vector.resize3d(): problem allocating pointer space\n\n");
+ PyErr_SetString(PyExc_MemoryError, "vector.resize3D(): problem allocating pointer space\n\n");
return NULL;
}
@@ -222,17 +222,17 @@ static char Vector_Resize4D_doc[] =
static PyObject *Vector_Resize4D(VectorObject * self)
{
if(self->wrapped==Py_WRAP) {
- PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize wrapped data - only python vectors");
+ PyErr_SetString(PyExc_TypeError, "vector.resize4D(): cannot resize wrapped data - only python vectors");
return NULL;
}
if(self->cb_user) {
- PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner");
+ PyErr_SetString(PyExc_TypeError, "vector.resize4D(): cannot resize a vector that has an owner");
return NULL;
}
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4));
if(self->vec == NULL) {
- PyErr_SetString(PyExc_MemoryError, "vector.resize4d(): problem allocating pointer space\n\n");
+ PyErr_SetString(PyExc_MemoryError, "vector.resize4D(): problem allocating pointer space\n\n");
return NULL;
}
if(self->size == 2){
@@ -265,7 +265,7 @@ static PyObject *Vector_ToTuple(VectorObject * self, PyObject *value)
PyObject *ret;
if(ndigits > 22 || ndigits < 0) { /* accounts for non ints */
- PyErr_SetString(PyExc_TypeError, "vector.key(ndigits): ndigits must be between 0 and 21");
+ PyErr_SetString(PyExc_TypeError, "vector.to_tuple(ndigits): ndigits must be between 0 and 21");
return NULL;
}
@@ -300,7 +300,7 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
char *strack, *sup;
short track = 2, up = 1;
- if( !PyArg_ParseTuple ( args, "|ss", &strack, &sup ) ) {
+ if(!PyArg_ParseTuple( args, "|ss:to_track_quat", &strack, &sup)) {
PyErr_SetString( PyExc_TypeError, "expected optional two strings\n" );
return NULL;
}
@@ -558,11 +558,7 @@ static PyObject *Vector_Angle(VectorObject * self, VectorObject * value)
angleRads = (double)saacos(dot);
-#ifdef USE_MATHUTILS_DEG
- return PyFloat_FromDouble(angleRads * (180/ Py_PI));
-#else
return PyFloat_FromDouble(angleRads);
-#endif
}
static char Vector_Difference_doc[] =
@@ -666,12 +662,12 @@ static PyObject *Vector_Lerp(VectorObject * self, PyObject * args)
float fac, ifac, vec[4];
int x;
- if(!PyArg_ParseTuple(args, "O!f", &vector_Type, &vec2, &fac)) {
+ if(!PyArg_ParseTuple(args, "O!f:lerp", &vector_Type, &vec2, &fac)) {
PyErr_SetString(PyExc_TypeError, "vector.lerp(): expects a vector of the same size and float");
return NULL;
}
if(self->size != vec2->size) {
- PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size");
+ PyErr_SetString(PyExc_AttributeError, "vector.lerp(): expects (2) vector objects of the same size");
return NULL;
}
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 9b754f9e635..31c2f548c85 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -65,6 +65,11 @@ static Py_ssize_t pyrna_prop_collection_length( BPy_PropertyRNA *self );
/* bpyrna vector/euler/quat callbacks */
static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */
+/* not used yet but may want to use the subtype below */
+#define MATHUTILS_CB_SUBTYPE_EUL 0
+#define MATHUTILS_CB_SUBTYPE_VEC 1
+#define MATHUTILS_CB_SUBTYPE_QUAT 2
+
static int mathutils_rna_generic_check(BPy_PropertyRNA *self)
{
return self->prop?1:0;
@@ -181,7 +186,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
RNA_property_float_get_array(ptr, prop, ((VectorObject *)ret)->vec);
}
else {
- PyObject *vec_cb= newVectorObject_cb(ret, len, mathutils_rna_array_cb_index, FALSE);
+ PyObject *vec_cb= newVectorObject_cb(ret, len, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_VEC);
Py_DECREF(ret); /* the vector owns now */
ret= vec_cb; /* return the vector instead */
}
@@ -215,11 +220,11 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
case PROP_QUATERNION:
if(len==3) { /* euler */
if(is_thick) {
- ret= newEulerObject(NULL, Py_NEW, NULL);
+ ret= newEulerObject(NULL, 0, Py_NEW, NULL); // TODO, get order from RNA
RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul);
}
else {
- PyObject *eul_cb= newEulerObject_cb(ret, mathutils_rna_array_cb_index, FALSE);
+ PyObject *eul_cb= newEulerObject_cb(ret, 0, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL); // TODO, get order from RNA
Py_DECREF(ret); /* the matrix owns now */
ret= eul_cb; /* return the matrix instead */
}
@@ -230,7 +235,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
RNA_property_float_get_array(ptr, prop, ((QuaternionObject *)ret)->quat);
}
else {
- PyObject *quat_cb= newQuaternionObject_cb(ret, mathutils_rna_array_cb_index, FALSE);
+ PyObject *quat_cb= newQuaternionObject_cb(ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_QUAT);
Py_DECREF(ret); /* the matrix owns now */
ret= quat_cb; /* return the matrix instead */
}