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:
authorJoseph Gilbert <ascotan@gmail.com>2004-02-29 16:20:34 +0300
committerJoseph Gilbert <ascotan@gmail.com>2004-02-29 16:20:34 +0300
commit8f3a9815baafb6f8fe00659cf6390a8c4092ef8b (patch)
tree9a69af7bffd6fd0d7da8e998d74a37dc273628a2 /source/blender/python/api2_2x/euler.c
parent2255ac3b19ec3b2aa0e884ad5960f34c9c0efa23 (diff)
Mathutils library for the python API
- support for quaternions, euler, vector, matrix operations. - euler supports unique rotation calculation - new matrix memory construction and internal functions - quaternion slerp and diff calculation - 2d, 3d, 4d vector construction and handling - full conversion support between types - update to object/window to reflect to matrix type - update to types/blender/module to reflect new module
Diffstat (limited to 'source/blender/python/api2_2x/euler.c')
-rw-r--r--source/blender/python/api2_2x/euler.c331
1 files changed, 331 insertions, 0 deletions
diff --git a/source/blender/python/api2_2x/euler.c b/source/blender/python/api2_2x/euler.c
new file mode 100644
index 00000000000..c6c8d61f9f3
--- /dev/null
+++ b/source/blender/python/api2_2x/euler.c
@@ -0,0 +1,331 @@
+/*
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Joseph Gilbert
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "euler.h"
+
+//doc strings
+char Euler_Zero_doc[] =
+"() - set all values in the euler to 0";
+char Euler_Unique_doc[] =
+"() - sets the euler rotation a unique shortest arc rotation - tests for gimbal lock";
+char Euler_ToMatrix_doc[] =
+"() - returns a rotation matrix representing the euler rotation";
+char Euler_ToQuat_doc[] =
+"() - returns a quaternion representing the euler rotation";
+
+//methods table
+struct PyMethodDef Euler_methods[] = {
+ {"zero",(PyCFunction)Euler_Zero, METH_NOARGS,
+ Euler_Zero_doc},
+ {"unique",(PyCFunction)Euler_Unique, METH_NOARGS,
+ Euler_Unique_doc},
+ {"toMatrix",(PyCFunction)Euler_ToMatrix, METH_NOARGS,
+ Euler_ToMatrix_doc},
+ {"toQuat",(PyCFunction)Euler_ToQuat, METH_NOARGS,
+ Euler_ToQuat_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*****************************/
+// Euler Python Object
+/*****************************/
+
+//euler methods
+PyObject *Euler_ToQuat(EulerObject *self)
+{
+ float *quat;
+ int x;
+
+ for(x = 0; x < 3; x++){
+ self->eul[x] *= (float)(Py_PI/180);
+ }
+ quat = PyMem_Malloc(4*sizeof(float));
+ EulToQuat(self->eul, quat);
+ for(x = 0; x < 3; x++){
+ self->eul[x] *= (float)(180/Py_PI);
+ }
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+PyObject *Euler_ToMatrix(EulerObject *self)
+{
+ float *mat;
+ int x;
+
+ for(x = 0; x < 3; x++){
+ self->eul[x] *= (float)(Py_PI/180);
+ }
+ mat = PyMem_Malloc(3*3*sizeof(float));
+ EulToMat3(self->eul, (float(*)[3])mat);
+ for(x = 0; x < 3; x++){
+ self->eul[x] *= (float)(180/Py_PI);
+ }
+ return (PyObject*)newMatrixObject(mat,3,3);
+}
+
+PyObject *Euler_Unique(EulerObject *self)
+{
+ float heading, pitch, bank;
+ float pi2 = (float)Py_PI * 2.0f;
+ float piO2 = (float)Py_PI / 2.0f;
+ float Opi2 = 1.0f / pi2;
+
+ //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);
+
+ //wrap heading in +180 / -180
+ pitch += (float)Py_PI;
+ pitch -= (float)floor(pitch * Opi2) * pi2;
+ pitch -= (float)Py_PI;
+
+
+ if(pitch < -piO2){
+ pitch = (float)-Py_PI - pitch;
+ heading += (float)Py_PI;
+ bank += (float)Py_PI;
+ }else if (pitch > piO2){
+ pitch = (float)Py_PI - pitch;
+ heading += (float)Py_PI;
+ bank += (float)Py_PI;
+ }
+
+ //gimbal lock test
+ if(fabs(pitch) > piO2 - 1e-4){
+ heading += bank;
+ bank = 0.0f;
+ }else{
+ bank += (float)Py_PI;
+ bank -= (float)(floor(bank * Opi2)) * pi2;
+ bank -= (float)Py_PI;
+ }
+
+ heading += (float)Py_PI;
+ heading -= (float)(floor(heading * Opi2)) * pi2;
+ heading -= (float)Py_PI;
+
+ //back to degrees
+ self->eul[0] = heading * (float)(180/Py_PI);
+ self->eul[1] = pitch * (float)(180/Py_PI);
+ self->eul[2] = bank * (float)(180/Py_PI);
+
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Euler_Zero(EulerObject *self)
+{
+ self->eul[0] = 0.0;
+ self->eul[1] = 0.0;
+ self->eul[2] = 0.0;
+
+ return EXPP_incr_ret(Py_None);
+}
+
+static void Euler_dealloc(EulerObject *self)
+{
+ PyObject_DEL (self);
+}
+
+static PyObject *Euler_getattr(EulerObject *self, char *name)
+{
+ if (ELEM3(name[0], 'x', 'y', 'z') && name[1]==0){
+ return PyFloat_FromDouble(self->eul[name[0]-'x']);
+ }
+ return Py_FindMethod(Euler_methods, (PyObject*)self, name);
+}
+
+static int Euler_setattr(EulerObject *self, char *name, PyObject *e)
+{
+ float val;
+
+ if (!PyArg_Parse(e, "f", &val))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "unable to parse float argument\n");
+
+ if (ELEM3(name[0], 'x', 'y', 'z') && name[1]==0){
+ self->eul[name[0]-'x']= val;
+ return 0;
+ }
+ else return -1;
+}
+
+/* Eulers Sequence methods */
+static PyObject *Euler_item(EulerObject *self, int i)
+{
+ if (i < 0 || i >= 3)
+ return EXPP_ReturnPyObjError (PyExc_IndexError, "array index out of range\n");
+
+ return Py_BuildValue("f", self->eul[i]);
+}
+
+static PyObject *Euler_slice(EulerObject *self, int begin, int end)
+{
+ PyObject *list;
+ int count;
+
+ if (begin < 0) begin= 0;
+ if (end > 3) end= 3;
+ if (begin > end) begin= end;
+
+ list= PyList_New(end-begin);
+
+ for (count = begin; count < end; count++){
+ PyList_SetItem(list, count-begin, PyFloat_FromDouble(self->eul[count]));
+ }
+ return list;
+}
+
+static int Euler_ass_item(EulerObject *self, int i, PyObject *ob)
+{
+ if (i < 0 || i >= 3)
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "array assignment index out of range\n");
+
+ if (!PyNumber_Check(ob))
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "Euler member must be a number\n");
+
+ if(!PyFloat_Check(ob) && !PyInt_Check(ob)){
+ return EXPP_ReturnIntError(PyExc_TypeError,"int or float expected\n");
+ }else{
+ self->eul[i]= (float)PyFloat_AsDouble(ob);
+ }
+ return 0;
+}
+
+static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq)
+{
+ int count, z;
+
+ if (begin < 0) begin= 0;
+ if (end > 3) end= 3;
+ if (begin > end) begin= end;
+
+ if (!PySequence_Check(seq))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "illegal argument type for built-in operation\n");
+ if (PySequence_Length(seq) != (end - begin))
+ return EXPP_ReturnIntError(PyExc_TypeError,
+ "size mismatch in slice assignment\n");
+
+ z = 0;
+ for (count = begin; count < end; count++) {
+ PyObject *ob = PySequence_GetItem(seq, z); z++;
+
+ if(!PyFloat_Check(ob) && !PyInt_Check(ob)){
+ Py_DECREF(ob);
+ return -1;
+ }else{
+ if (!PyArg_Parse(ob, "f", &self->eul[count])) {
+ Py_DECREF(ob);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static PyObject *Euler_repr (EulerObject *self)
+{
+ int i, maxindex = 3 - 1;
+ char ftoa[24];
+ PyObject *str1, *str2;
+
+ str1 = PyString_FromString ("[");
+
+ for (i = 0; i < maxindex; i++) {
+ sprintf(ftoa, "%.4f, ", self->eul[i]);
+ str2 = PyString_FromString (ftoa);
+ if (!str1 || !str2) goto error;
+ PyString_ConcatAndDel (&str1, str2);
+ }
+
+ sprintf(ftoa, "%.4f]\n", self->eul[maxindex]);
+ str2 = PyString_FromString (ftoa);
+ if (!str1 || !str2) goto error;
+ PyString_ConcatAndDel (&str1, str2);
+
+ if (str1) return str1;
+
+error:
+ Py_XDECREF (str1);
+ Py_XDECREF (str2);
+ return EXPP_ReturnPyObjError (PyExc_MemoryError,
+ "couldn't create PyString!\n");
+}
+
+static PySequenceMethods Euler_SeqMethods =
+{
+ (inquiry) 0, /* sq_length */
+ (binaryfunc) 0, /* sq_concat */
+ (intargfunc) 0, /* sq_repeat */
+ (intargfunc) Euler_item, /* sq_item */
+ (intintargfunc) Euler_slice, /* sq_slice */
+ (intobjargproc) Euler_ass_item, /* sq_ass_item */
+ (intintobjargproc) Euler_ass_slice, /* sq_ass_slice */
+};
+
+PyTypeObject euler_Type =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "euler", /*tp_name*/
+ sizeof(EulerObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor) Euler_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) Euler_getattr, /*tp_getattr*/
+ (setattrfunc) Euler_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ (reprfunc) Euler_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &Euler_SeqMethods, /*tp_as_sequence*/
+};
+
+PyObject *newEulerObject(float *eul)
+{
+ EulerObject *self;
+ int x;
+
+ euler_Type.ob_type = &PyType_Type;
+
+ self = PyObject_NEW(EulerObject, &euler_Type);
+
+ if(!eul){
+ self->eul = PyMem_Malloc (3*sizeof (float));
+ for(x = 0; x < 3; x++){
+ self->eul[x] = 0.0f;
+ }
+ }else self->eul = eul;
+
+ return (PyObject*) self;
+}
+