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/quat.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/quat.c')
-rw-r--r--source/blender/python/api2_2x/quat.c504
1 files changed, 504 insertions, 0 deletions
diff --git a/source/blender/python/api2_2x/quat.c b/source/blender/python/api2_2x/quat.c
new file mode 100644
index 00000000000..3d785570027
--- /dev/null
+++ b/source/blender/python/api2_2x/quat.c
@@ -0,0 +1,504 @@
+/*
+ * ***** 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 "quat.h"
+
+//doc strings
+char Quaternion_Identity_doc[] =
+"() - set the quaternion to it's identity (1, vector)";
+char Quaternion_Negate_doc[] =
+"() - set all values in the quaternion to their negative";
+char Quaternion_Conjugate_doc[] =
+"() - set the quaternion to it's conjugate";
+char Quaternion_Inverse_doc[] =
+"() - set the quaternion to it's inverse";
+char Quaternion_Normalize_doc[] =
+"() - normalize the vector portion of the quaternion";
+char Quaternion_ToEuler_doc[] =
+"() - return a euler rotation representing the quaternion";
+char Quaternion_ToMatrix_doc[] =
+"() - return a rotation matrix representing the quaternion";
+
+//methods table
+struct PyMethodDef Quaternion_methods[] = {
+ {"identity",(PyCFunction)Quaternion_Identity, METH_NOARGS,
+ Quaternion_Identity_doc},
+ {"negate",(PyCFunction)Quaternion_Negate, METH_NOARGS,
+ Quaternion_Negate_doc},
+ {"conjugate",(PyCFunction)Quaternion_Conjugate, METH_NOARGS,
+ Quaternion_Conjugate_doc},
+ {"inverse",(PyCFunction)Quaternion_Inverse, METH_NOARGS,
+ Quaternion_Inverse_doc},
+ {"normalize",(PyCFunction)Quaternion_Normalize, METH_NOARGS,
+ Quaternion_Normalize_doc},
+ {"toEuler",(PyCFunction)Quaternion_ToEuler, METH_NOARGS,
+ Quaternion_ToEuler_doc},
+ {"toMatrix",(PyCFunction)Quaternion_ToMatrix, METH_NOARGS,
+ Quaternion_ToMatrix_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/*****************************/
+// Quaternion Python Object
+/*****************************/
+
+PyObject *Quaternion_ToEuler(QuaternionObject *self)
+{
+ float *eul;
+ int x;
+
+ eul = PyMem_Malloc(3*sizeof(float));
+ QuatToEul(self->quat, eul);
+
+ for(x = 0; x < 3; x++){
+ eul[x] *= (float)(180/Py_PI);
+ }
+ return (PyObject*)newEulerObject(eul);
+}
+
+PyObject *Quaternion_ToMatrix(QuaternionObject *self)
+{
+ float *mat;
+
+ mat = PyMem_Malloc(3*3*sizeof(float));
+ QuatToMat3(self->quat, (float(*)[3])mat);
+
+ return (PyObject*)newMatrixObject(mat, 3,3);
+}
+
+//normalize the axis of rotation of [theta,vector]
+PyObject *Quaternion_Normalize(QuaternionObject *self)
+{
+ NormalQuat(self->quat);
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Quaternion_Inverse(QuaternionObject *self)
+{
+ float mag = 0.0f;
+ int x;
+
+ for(x = 1; x < 4; x++){
+ self->quat[x] = -self->quat[x];
+ }
+ for(x = 0; x < 4; x++){
+ mag += (self->quat[x] * self->quat[x]);
+ }
+ mag = (float)sqrt(mag);
+ for(x = 0; x < 4; x++){
+ self->quat[x] /= (mag * mag);
+ }
+
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Quaternion_Identity(QuaternionObject *self)
+{
+ self->quat[0] = 1.0;
+ self->quat[1] = 0.0; self->quat[2] = 0.0; self->quat[3] = 0.0;
+
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Quaternion_Negate(QuaternionObject *self)
+{
+ int x;
+
+ for(x = 0; x < 4; x++){
+ self->quat[x] = -self->quat[x];
+ }
+ return EXPP_incr_ret(Py_None);
+}
+
+PyObject *Quaternion_Conjugate(QuaternionObject *self)
+{
+ int x;
+
+ for(x = 1; x < 4; x++){
+ self->quat[x] = -self->quat[x];
+ }
+ return EXPP_incr_ret(Py_None);
+}
+
+static void Quaternion_dealloc(QuaternionObject *self)
+{
+ PyObject_DEL (self);
+}
+
+static PyObject *Quaternion_getattr(QuaternionObject *self, char *name)
+{
+ double mag = 0.0f;
+ float *vec;
+ int x;
+
+ if (ELEM4(name[0], 'w', 'x', 'y', 'z') && name[1]==0){
+ return PyFloat_FromDouble(self->quat[name[0]-'w']);
+ }
+ if(strcmp(name,"magnitude") == 0){
+ for(x = 0; x < 4; x++){
+ mag += self->quat[x] * self->quat[x];
+ }
+ mag = (float)sqrt(mag);
+ return PyFloat_FromDouble(mag);
+ }
+ if(strcmp(name,"angle") == 0){
+
+ mag = self->quat[0];
+ mag = 2 * (acos(mag));
+ mag *= (180/Py_PI);
+ return PyFloat_FromDouble(mag);
+ }
+ if(strcmp(name,"axis") == 0){
+
+ mag = (double)(self->quat[0] * (Py_PI/180));
+ mag = 2 * (acos(mag));
+ mag = sin(mag/2);
+ vec = PyMem_Malloc(3*sizeof(float));
+ for(x = 0; x < 3; x++){
+ vec[x] = (self->quat[x + 1]/((float)(mag)));
+ }
+ Normalise(vec);
+ return (PyObject*)newVectorObject(vec,3);
+ }
+ return Py_FindMethod(Quaternion_methods, (PyObject*)self, name);
+}
+
+static int Quaternion_setattr(QuaternionObject *self, char *name, PyObject *v)
+{
+ float val;
+
+ if(!PyFloat_Check(v) && !PyInt_Check(v)){
+ return EXPP_ReturnIntError(PyExc_TypeError,"int or float expected\n");
+ }else{
+ if (!PyArg_Parse(v, "f", &val))
+ return EXPP_ReturnIntError(PyExc_TypeError, "unable to parse float argument\n");
+ }
+ if (ELEM4(name[0], 'w', 'x', 'y', 'z') && name[1]==0){
+ self->quat[name[0]-'w']= val;
+ }else return -1;
+
+ return 0;
+}
+
+/* Quaternions Sequence methods */
+static PyObject *Quaternion_item(QuaternionObject *self, int i)
+{
+ if (i < 0 || i >= 4)
+ return EXPP_ReturnPyObjError (PyExc_IndexError, "array index out of range\n");
+
+ return Py_BuildValue("f", self->quat[i]);
+}
+
+static PyObject *Quaternion_slice(QuaternionObject *self, int begin, int end)
+{
+ PyObject *list;
+ int count;
+
+ if (begin < 0) begin= 0;
+ if (end > 4) end= 4;
+ if (begin > end) begin= end;
+
+ list= PyList_New(end-begin);
+
+ for (count = begin; count < end; count++){
+ PyList_SetItem(list, count-begin, PyFloat_FromDouble(self->quat[count]));
+ }
+ return list;
+}
+
+static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob)
+{
+ if (i < 0 || i >= 4)
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "array assignment index out of range\n");
+ if (!PyNumber_Check(ob))
+ return EXPP_ReturnIntError(PyExc_IndexError,
+ "Quaternion 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->quat[i]= (float)PyFloat_AsDouble(ob);
+ }
+ return 0;
+}
+
+static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyObject *seq)
+{
+ int count, z;
+
+ if (begin < 0) begin= 0;
+ if (end > 4) end= 4;
+ 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->quat[count])) {
+ Py_DECREF(ob);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static PyObject *Quaternion_repr (QuaternionObject *self)
+{
+ int i, maxindex = 4 - 1;
+ char ftoa[24];
+ PyObject *str1, *str2;
+
+ str1 = PyString_FromString ("[");
+
+ for (i = 0; i < maxindex; i++) {
+ sprintf(ftoa, "%.4f, ", self->quat[i]);
+ str2 = PyString_FromString (ftoa);
+ if (!str1 || !str2) goto error;
+ PyString_ConcatAndDel (&str1, str2);
+ }
+
+ sprintf(ftoa, "%.4f]\n", self->quat[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");
+}
+
+
+PyObject * Quaternion_add(PyObject *q1, PyObject *q2)
+{
+ float * quat;
+ int x;
+
+ if((!QuaternionObject_Check(q1)) || (!QuaternionObject_Check(q2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+ if(((QuaternionObject*)q1)->flag > 0 || ((QuaternionObject*)q2)->flag > 0)
+ return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
+ "cannot add a scalar and a quat\n");
+
+ quat = PyMem_Malloc (4*sizeof(float));
+ for(x = 0; x < 4; x++){
+ quat[x] = (((QuaternionObject*)q1)->quat[x]) + (((QuaternionObject*)q2)->quat[x]);
+ }
+
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+PyObject * Quaternion_sub(PyObject *q1, PyObject *q2)
+{
+ float * quat;
+ int x;
+
+ if((!QuaternionObject_Check(q1)) || (!QuaternionObject_Check(q2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+ if(((QuaternionObject*)q1)->flag > 0 || ((QuaternionObject*)q2)->flag > 0)
+ return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
+ "cannot subtract a scalar and a quat\n");
+
+ quat = PyMem_Malloc (4*sizeof(float));
+ for(x = 0; x < 4; x++){
+ quat[x] = (((QuaternionObject*)q1)->quat[x]) - (((QuaternionObject*)q2)->quat[x]);
+ }
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+PyObject * Quaternion_mul(PyObject *q1, PyObject * q2)
+{
+ float * quat;
+ int x;
+
+ if((!QuaternionObject_Check(q1)) || (!QuaternionObject_Check(q2)))
+ return EXPP_ReturnPyObjError (PyExc_TypeError,
+ "unsupported type for this operation\n");
+ if(((QuaternionObject*)q1)->flag == 0 && ((QuaternionObject*)q2)->flag == 0)
+ return EXPP_ReturnPyObjError (PyExc_ArithmeticError,
+ "please use the dot or cross product to multiply quaternions\n");
+
+ quat = PyMem_Malloc (4*sizeof(float));
+ //scalar mult by quat
+ for(x = 0; x < 4; x++){
+ quat[x] = ((QuaternionObject*)q1)->quat[x] * ((QuaternionObject*)q2)->quat[x];
+ }
+ return (PyObject*)newQuaternionObject(quat);
+}
+
+//coercion of unknown types to type QuaternionObject for numeric protocols
+int Quaternion_coerce(PyObject **q1, PyObject **q2)
+{
+ long *tempI;
+ double *tempF;
+ float *quat;
+ int x;
+
+ if (QuaternionObject_Check(*q1)) {
+ if (QuaternionObject_Check(*q2)) { //two Quaternions
+ Py_INCREF(*q1);
+ Py_INCREF(*q2);
+ return 0;
+ }else{
+ if(PyNumber_Check(*q2)){
+ if(PyInt_Check(*q2)){ //cast scalar to Quaternion
+ tempI = PyMem_Malloc(1*sizeof(long));
+ *tempI = PyInt_AsLong(*q2);
+ quat = PyMem_Malloc (4*sizeof (float));
+ for(x = 0; x < 4; x++){
+ quat[x] = (float)*tempI;
+ }
+ PyMem_Free(tempI);
+ *q2 = newQuaternionObject(quat);
+ ((QuaternionObject*)*q2)->flag = 1; //int coercion
+ Py_INCREF(*q1);
+ return 0;
+ }else if(PyFloat_Check(*q2)){ //cast scalar to Quaternion
+ tempF = PyMem_Malloc(1*sizeof(double));
+ *tempF = PyFloat_AsDouble(*q2);
+ quat = PyMem_Malloc (4*sizeof (float));
+ for(x = 0; x < 4; x++){
+ quat[x] = (float)*tempF;
+ }
+ PyMem_Free(tempF);
+ *q2 = newQuaternionObject(quat);
+ ((QuaternionObject*)*q2)->flag = 2; //float coercion
+ Py_INCREF(*q1);
+ return 0;
+ }
+ }
+ //unknown type or numeric cast failure
+ printf("attempting quaternion operation with unsupported type...\n");
+ Py_INCREF(*q1);
+ return 0; //operation will type check
+ }
+ }else{
+ printf("numeric protocol failure...\n");
+ return -1; //this should not occur - fail
+ }
+ return -1;
+}
+
+static PySequenceMethods Quaternion_SeqMethods =
+{
+ (inquiry) 0, /* sq_length */
+ (binaryfunc) 0, /* sq_concat */
+ (intargfunc) 0, /* sq_repeat */
+ (intargfunc) Quaternion_item, /* sq_item */
+ (intintargfunc) Quaternion_slice, /* sq_slice */
+ (intobjargproc) Quaternion_ass_item, /* sq_ass_item */
+ (intintobjargproc) Quaternion_ass_slice, /* sq_ass_slice */
+};
+
+static PyNumberMethods Quaternion_NumMethods =
+{
+ (binaryfunc) Quaternion_add, /* __add__ */
+ (binaryfunc) Quaternion_sub, /* __sub__ */
+ (binaryfunc) Quaternion_mul, /* __mul__ */
+ (binaryfunc) 0, /* __div__ */
+ (binaryfunc) 0, /* __mod__ */
+ (binaryfunc) 0, /* __divmod__ */
+ (ternaryfunc) 0, /* __pow__ */
+ (unaryfunc) 0, /* __neg__ */
+ (unaryfunc) 0, /* __pos__ */
+ (unaryfunc) 0, /* __abs__ */
+ (inquiry) 0, /* __nonzero__ */
+ (unaryfunc) 0, /* __invert__ */
+ (binaryfunc) 0, /* __lshift__ */
+ (binaryfunc) 0, /* __rshift__ */
+ (binaryfunc) 0, /* __and__ */
+ (binaryfunc) 0, /* __xor__ */
+ (binaryfunc) 0, /* __or__ */
+ (coercion) Quaternion_coerce, /* __coerce__ */
+ (unaryfunc) 0, /* __int__ */
+ (unaryfunc) 0, /* __long__ */
+ (unaryfunc) 0, /* __float__ */
+ (unaryfunc) 0, /* __oct__ */
+ (unaryfunc) 0, /* __hex__ */
+
+};
+
+PyTypeObject quaternion_Type =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "quaternion", /*tp_name*/
+ sizeof(QuaternionObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor) Quaternion_dealloc, /*tp_dealloc*/
+ (printfunc) 0, /*tp_print*/
+ (getattrfunc) Quaternion_getattr, /*tp_getattr*/
+ (setattrfunc) Quaternion_setattr, /*tp_setattr*/
+ 0, /*tp_compare*/
+ (reprfunc) Quaternion_repr, /*tp_repr*/
+ &Quaternion_NumMethods, /*tp_as_number*/
+ &Quaternion_SeqMethods, /*tp_as_sequence*/
+};
+
+PyObject *newQuaternionObject(float *quat)
+{
+ QuaternionObject *self;
+ int x;
+
+ quaternion_Type.ob_type = &PyType_Type;
+
+ self = PyObject_NEW(QuaternionObject, &quaternion_Type);
+
+ if(!quat){
+ self->quat = PyMem_Malloc (4 *sizeof (float));
+ for(x = 0; x < 4; x++){
+ self->quat[x] = 0.0f;
+ }
+ self->quat[3] = 1.0f;
+ }else{
+ self->quat = quat;
+ }
+ self->flag = 0;
+
+ return (PyObject*) self;
+}
+