py api
[blender.git] / source / blender / python / generic / mathutils_quat.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Joseph Gilbert
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "mathutils.h"
30
31 #include "BLI_math.h"
32 #include "BKE_utildefines.h"
33
34 //-----------------------------METHODS------------------------------
35
36 /* note: BaseMath_ReadCallback must be called beforehand */
37 static PyObject *Quaternion_ToTupleExt(QuaternionObject *self, int ndigits)
38 {
39         PyObject *ret;
40         int i;
41
42         ret= PyTuple_New(4);
43
44         if(ndigits >= 0) {
45                 for(i= 0; i < 4; i++) {
46                         PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->quat[i], ndigits)));
47                 }
48         }
49         else {
50                 for(i= 0; i < 4; i++) {
51                         PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->quat[i]));
52                 }
53         }
54
55         return ret;
56 }
57
58 static char Quaternion_ToEuler_doc[] =
59 ".. method:: to_euler(order, euler_compat)\n"
60 "\n"
61 "   Return Euler representation of the quaternion.\n"
62 "\n"
63 "   :arg order: Optional rotation order argument in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
64 "   :type order: string\n"
65 "   :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"
66 "   :type euler_compat: :class:`Euler`\n"
67 "   :return: Euler representation of the quaternion.\n"
68 "   :rtype: :class:`Euler`\n";
69
70 static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args)
71 {
72         float eul[3];
73         char *order_str= NULL;
74         short order= 0;
75         EulerObject *eul_compat = NULL;
76         
77         if(!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
78                 return NULL;
79         
80         if(!BaseMath_ReadCallback(self))
81                 return NULL;
82
83         if(order_str) {
84                 order= euler_order_from_string(order_str, "Matrix.to_euler()");
85
86                 if(order < 0)
87                         return NULL;
88         }
89
90         if(eul_compat) {
91                 float mat[3][3];
92                 
93                 if(!BaseMath_ReadCallback(eul_compat))
94                         return NULL;
95                 
96                 quat_to_mat3(mat, self->quat);
97
98                 if(order == 0)  mat3_to_compatible_eul(eul, eul_compat->eul, mat);
99                 else                    mat3_to_compatible_eulO(eul, eul_compat->eul, order, mat);
100         }
101         else {
102                 if(order == 0)  quat_to_eul(eul, self->quat);
103                 else                    quat_to_eulO(eul, order, self->quat);
104         }
105         
106         return newEulerObject(eul, order, Py_NEW, NULL);
107 }
108 //----------------------------Quaternion.toMatrix()------------------
109 static char Quaternion_ToMatrix_doc[] =
110 ".. method:: to_matrix(other)\n"
111 "\n"
112 "   Return a matrix representation of the quaternion.\n"
113 "\n"
114 "   :return: A 3x3 rotation matrix representation of the quaternion.\n"
115 "   :rtype: :class:`Matrix`\n";
116
117 static PyObject *Quaternion_ToMatrix(QuaternionObject * self)
118 {
119         float mat[9]; /* all values are set */
120
121         if(!BaseMath_ReadCallback(self))
122                 return NULL;
123
124         quat_to_mat3( (float (*)[3]) mat,self->quat);
125         return newMatrixObject(mat, 3, 3, Py_NEW, NULL);
126 }
127
128 //----------------------------Quaternion.cross(other)------------------
129 static char Quaternion_Cross_doc[] =
130 ".. method:: cross(other)\n"
131 "\n"
132 "   Return the cross product of this quaternion and another.\n"
133 "\n"
134 "   :arg other: The other quaternion to perform the cross product with.\n"
135 "   :type other: :class:`Quaternion`\n"
136 "   :return: The cross product.\n"
137 "   :rtype: :class:`Quaternion`\n";
138
139 static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * value)
140 {
141         float quat[4];
142         
143         if (!QuaternionObject_Check(value)) {
144                 PyErr_SetString( PyExc_TypeError, "quat.cross(value): expected a quaternion argument" );
145                 return NULL;
146         }
147         
148         if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
149                 return NULL;
150
151         mul_qt_qtqt(quat, self->quat, value->quat);
152         return newQuaternionObject(quat, Py_NEW, NULL);
153 }
154
155 //----------------------------Quaternion.dot(other)------------------
156 static char Quaternion_Dot_doc[] =
157 ".. method:: dot(other)\n"
158 "\n"
159 "   Return the dot product of this quaternion and another.\n"
160 "\n"
161 "   :arg other: The other quaternion to perform the dot product with.\n"
162 "   :type other: :class:`Quaternion`\n"
163 "   :return: The dot product.\n"
164 "   :rtype: :class:`Quaternion`\n";
165
166 static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
167 {
168         if (!QuaternionObject_Check(value)) {
169                 PyErr_SetString( PyExc_TypeError, "quat.dot(value): expected a quaternion argument" );
170                 return NULL;
171         }
172
173         if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
174                 return NULL;
175
176         return PyFloat_FromDouble(dot_qtqt(self->quat, value->quat));
177 }
178
179 static char Quaternion_Difference_doc[] =
180 ".. function:: difference(other)\n"
181 "\n"
182 "   Returns a quaternion representing the rotational difference.\n"
183 "\n"
184 "   :arg other: second quaternion.\n"
185 "   :type other: :class:`Quaternion`\n"
186 "   :return: the rotational difference between the two quat rotations.\n"
187 "   :rtype: :class:`Quaternion`\n";
188
189 static PyObject *Quaternion_Difference(QuaternionObject * self, QuaternionObject * value)
190 {
191         float quat[4], tempQuat[4];
192         double dot = 0.0f;
193         int x;
194
195         if (!QuaternionObject_Check(value)) {
196                 PyErr_SetString( PyExc_TypeError, "quat.difference(value): expected a quaternion argument" );
197                 return NULL;
198         }
199
200         if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
201                 return NULL;
202
203         tempQuat[0] = self->quat[0];
204         tempQuat[1] = - self->quat[1];
205         tempQuat[2] = - self->quat[2];
206         tempQuat[3] = - self->quat[3];
207
208         dot = sqrt(tempQuat[0] * tempQuat[0] + tempQuat[1] *  tempQuat[1] +
209                                    tempQuat[2] * tempQuat[2] + tempQuat[3] * tempQuat[3]);
210
211         for(x = 0; x < 4; x++) {
212                 tempQuat[x] /= (float)(dot * dot);
213         }
214         mul_qt_qtqt(quat, tempQuat, value->quat);
215         return newQuaternionObject(quat, Py_NEW, NULL);
216 }
217
218 static char Quaternion_Slerp_doc[] =
219 ".. function:: slerp(other, factor)\n"
220 "\n"
221 "   Returns the interpolation of two quaternions.\n"
222 "\n"
223 "   :arg other: value to interpolate with.\n"
224 "   :type other: :class:`Quaternion`\n"
225 "   :arg factor: The interpolation value in [0.0, 1.0].\n"
226 "   :type factor: float\n"
227 "   :return: The interpolated rotation.\n"
228 "   :rtype: :class:`Quaternion`\n";
229
230 static PyObject *Quaternion_Slerp(QuaternionObject *self, PyObject *args)
231 {
232         QuaternionObject *value;
233         float quat[4], fac;
234
235         if(!PyArg_ParseTuple(args, "O!f:slerp", &quaternion_Type, &value, &fac)) {
236                 PyErr_SetString(PyExc_TypeError, "quat.slerp(): expected Quaternion types and float");
237                 return NULL;
238         }
239
240         if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
241                 return NULL;
242
243         if(fac > 1.0f || fac < 0.0f) {
244                 PyErr_SetString(PyExc_AttributeError, "quat.slerp(): interpolation factor must be between 0.0 and 1.0");
245                 return NULL;
246         }
247
248         interp_qt_qtqt(quat, self->quat, value->quat, fac);
249
250         return newQuaternionObject(quat, Py_NEW, NULL);
251 }
252
253 //----------------------------Quaternion.normalize()----------------
254 //normalize the axis of rotation of [theta,vector]
255 static char Quaternion_Normalize_doc[] =
256 ".. function:: normalize()\n"
257 "\n"
258 "   Normalize the quaternion.\n"
259 "\n"
260 "   :return: an instance of itself.\n"
261 "   :rtype: :class:`Quaternion`\n";
262
263 static PyObject *Quaternion_Normalize(QuaternionObject * self)
264 {
265         if(!BaseMath_ReadCallback(self))
266                 return NULL;
267
268         normalize_qt(self->quat);
269
270         BaseMath_WriteCallback(self);
271         Py_INCREF(self);
272         return (PyObject*)self;
273 }
274 //----------------------------Quaternion.inverse()------------------
275 static char Quaternion_Inverse_doc[] =
276 ".. function:: inverse()\n"
277 "\n"
278 "   Set the quaternion to its inverse.\n"
279 "\n"
280 "   :return: an instance of itself.\n"
281 "   :rtype: :class:`Quaternion`\n";
282
283 static PyObject *Quaternion_Inverse(QuaternionObject * self)
284 {
285         if(!BaseMath_ReadCallback(self))
286                 return NULL;
287
288         invert_qt(self->quat);
289
290         BaseMath_WriteCallback(self);
291         Py_INCREF(self);
292         return (PyObject*)self;
293 }
294 //----------------------------Quaternion.identity()-----------------
295 static char Quaternion_Identity_doc[] =
296 ".. function:: identity()\n"
297 "\n"
298 "   Set the quaternion to an identity quaternion.\n"
299 "\n"
300 "   :return: an instance of itself.\n"
301 "   :rtype: :class:`Quaternion`\n";
302
303 static PyObject *Quaternion_Identity(QuaternionObject * self)
304 {
305         if(!BaseMath_ReadCallback(self))
306                 return NULL;
307
308         unit_qt(self->quat);
309
310         BaseMath_WriteCallback(self);
311         Py_INCREF(self);
312         return (PyObject*)self;
313 }
314 //----------------------------Quaternion.negate()-------------------
315 static char Quaternion_Negate_doc[] =
316 ".. function:: negate()\n"
317 "\n"
318 "   Set the quaternion to its negative.\n"
319 "\n"
320 "   :return: an instance of itself.\n"
321 "   :rtype: :class:`Quaternion`\n";
322
323 static PyObject *Quaternion_Negate(QuaternionObject * self)
324 {
325         if(!BaseMath_ReadCallback(self))
326                 return NULL;
327
328         mul_qt_fl(self->quat, -1.0f);
329
330         BaseMath_WriteCallback(self);
331         Py_INCREF(self);
332         return (PyObject*)self;
333 }
334 //----------------------------Quaternion.conjugate()----------------
335 static char Quaternion_Conjugate_doc[] =
336 ".. function:: conjugate()\n"
337 "\n"
338 "   Set the quaternion to its conjugate (negate x, y, z).\n"
339 "\n"
340 "   :return: an instance of itself.\n"
341 "   :rtype: :class:`Quaternion`\n";
342
343 static PyObject *Quaternion_Conjugate(QuaternionObject * self)
344 {
345         if(!BaseMath_ReadCallback(self))
346                 return NULL;
347
348         conjugate_qt(self->quat);
349
350         BaseMath_WriteCallback(self);
351         Py_INCREF(self);
352         return (PyObject*)self;
353 }
354 //----------------------------Quaternion.copy()----------------
355 static char Quaternion_copy_doc[] =
356 ".. function:: copy()\n"
357 "\n"
358 "   Returns a copy of this quaternion.\n"
359 "\n"
360 "   :return: A copy of the quaternion.\n"
361 "   :rtype: :class:`Quaternion`\n"
362 "\n"
363 "   .. note:: use this to get a copy of a wrapped quaternion with no reference to the original data.\n";
364
365 static PyObject *Quaternion_copy(QuaternionObject * self)
366 {
367         if(!BaseMath_ReadCallback(self))
368                 return NULL;
369
370         return newQuaternionObject(self->quat, Py_NEW, Py_TYPE(self));
371 }
372
373 //----------------------------print object (internal)--------------
374 //print the object to screen
375 static PyObject *Quaternion_repr(QuaternionObject * self)
376 {
377         PyObject *ret, *tuple;
378         
379         if(!BaseMath_ReadCallback(self))
380                 return NULL;
381
382         tuple= Quaternion_ToTupleExt(self, -1);
383
384         ret= PyUnicode_FromFormat("Quaternion(%R)", tuple);
385
386         Py_DECREF(tuple);
387         return ret;
388 }
389
390 //------------------------tp_richcmpr
391 //returns -1 execption, 0 false, 1 true
392 static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
393 {
394         QuaternionObject *quatA = NULL, *quatB = NULL;
395         int result = 0;
396
397         if(QuaternionObject_Check(objectA)) {
398                 quatA = (QuaternionObject*)objectA;
399                 if(!BaseMath_ReadCallback(quatA))
400                         return NULL;
401         }
402         if(QuaternionObject_Check(objectB)) {
403                 quatB = (QuaternionObject*)objectB;
404                 if(!BaseMath_ReadCallback(quatB))
405                         return NULL;
406         }
407
408         if (!quatA || !quatB){
409                 if (comparison_type == Py_NE){
410                         Py_RETURN_TRUE;
411                 }else{
412                         Py_RETURN_FALSE;
413                 }
414         }
415
416         switch (comparison_type){
417                 case Py_EQ:
418                         result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, 4, 1);
419                         break;
420                 case Py_NE:
421                         result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, 4, 1);
422                         if (result == 0){
423                                 result = 1;
424                         }else{
425                                 result = 0;
426                         }
427                         break;
428                 default:
429                         printf("The result of the comparison could not be evaluated");
430                         break;
431         }
432         if (result == 1){
433                 Py_RETURN_TRUE;
434         }else{
435                 Py_RETURN_FALSE;
436         }
437 }
438
439 //---------------------SEQUENCE PROTOCOLS------------------------
440 //----------------------------len(object)------------------------
441 //sequence length
442 static int Quaternion_len(QuaternionObject * self)
443 {
444         return 4;
445 }
446 //----------------------------object[]---------------------------
447 //sequence accessor (get)
448 static PyObject *Quaternion_item(QuaternionObject * self, int i)
449 {
450         if(i<0) i= 4-i;
451
452         if(i < 0 || i >= 4) {
453                 PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range\n");
454                 return NULL;
455         }
456
457         if(!BaseMath_ReadIndexCallback(self, i))
458                 return NULL;
459
460         return PyFloat_FromDouble(self->quat[i]);
461
462 }
463 //----------------------------object[]-------------------------
464 //sequence accessor (set)
465 static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob)
466 {
467         float scalar= (float)PyFloat_AsDouble(ob);
468         if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
469                 PyErr_SetString(PyExc_TypeError, "quaternion[index] = x: index argument not a number\n");
470                 return -1;
471         }
472
473         if(i<0) i= 4-i;
474
475         if(i < 0 || i >= 4){
476                 PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range\n");
477                 return -1;
478         }
479         self->quat[i] = scalar;
480
481         if(!BaseMath_WriteIndexCallback(self, i))
482                 return -1;
483
484         return 0;
485 }
486 //----------------------------object[z:y]------------------------
487 //sequence slice (get)
488 static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
489 {
490         PyObject *list = NULL;
491         int count;
492
493         if(!BaseMath_ReadCallback(self))
494                 return NULL;
495
496         CLAMP(begin, 0, 4);
497         if (end<0) end= 5+end;
498         CLAMP(end, 0, 4);
499         begin = MIN2(begin,end);
500
501         list = PyList_New(end - begin);
502         for(count = begin; count < end; count++) {
503                 PyList_SetItem(list, count - begin,
504                                 PyFloat_FromDouble(self->quat[count]));
505         }
506
507         return list;
508 }
509 //----------------------------object[z:y]------------------------
510 //sequence slice (set)
511 static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyObject * seq)
512 {
513         int i, y, size = 0;
514         float quat[4];
515         PyObject *q;
516
517         if(!BaseMath_ReadCallback(self))
518                 return -1;
519
520         CLAMP(begin, 0, 4);
521         if (end<0) end= 5+end;
522         CLAMP(end, 0, 4);
523         begin = MIN2(begin,end);
524
525         size = PySequence_Length(seq);
526         if(size != (end - begin)){
527                 PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: size mismatch in slice assignment\n");
528                 return -1;
529         }
530
531         for (i = 0; i < size; i++) {
532                 q = PySequence_GetItem(seq, i);
533                 if (q == NULL) { // Failed to read sequence
534                         PyErr_SetString(PyExc_RuntimeError, "quaternion[begin:end] = []: unable to read sequence\n");
535                         return -1;
536                 }
537
538                 quat[i]= (float)PyFloat_AsDouble(q);
539                 Py_DECREF(q);
540
541                 if(quat[i]==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
542                         PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: sequence argument not a number\n");
543                         return -1;
544                 }
545         }
546         //parsed well - now set in vector
547         for(y = 0; y < size; y++)
548                 self->quat[begin + y] = quat[y];
549
550         BaseMath_WriteCallback(self);
551         return 0;
552 }
553 //------------------------NUMERIC PROTOCOLS----------------------
554 //------------------------obj + obj------------------------------
555 //addition
556 static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
557 {
558         float quat[4];
559         QuaternionObject *quat1 = NULL, *quat2 = NULL;
560
561         if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
562                 PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
563                 return NULL;
564         }
565         quat1 = (QuaternionObject*)q1;
566         quat2 = (QuaternionObject*)q2;
567         
568         if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
569                 return NULL;
570
571         add_qt_qtqt(quat, quat1->quat, quat2->quat, 1.0f);
572         return newQuaternionObject(quat, Py_NEW, NULL);
573 }
574 //------------------------obj - obj------------------------------
575 //subtraction
576 static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
577 {
578         int x;
579         float quat[4];
580         QuaternionObject *quat1 = NULL, *quat2 = NULL;
581
582         if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
583                 PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
584                 return NULL;
585         }
586         
587         quat1 = (QuaternionObject*)q1;
588         quat2 = (QuaternionObject*)q2;
589         
590         if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
591                 return NULL;
592
593         for(x = 0; x < 4; x++) {
594                 quat[x] = quat1->quat[x] - quat2->quat[x];
595         }
596
597         return newQuaternionObject(quat, Py_NEW, NULL);
598 }
599 //------------------------obj * obj------------------------------
600 //mulplication
601 static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
602 {
603         float quat[4], scalar;
604         QuaternionObject *quat1 = NULL, *quat2 = NULL;
605         VectorObject *vec = NULL;
606
607         if(QuaternionObject_Check(q1)) {
608                 quat1 = (QuaternionObject*)q1;
609                 if(!BaseMath_ReadCallback(quat1))
610                         return NULL;
611         }
612         if(QuaternionObject_Check(q2)) {
613                 quat2 = (QuaternionObject*)q2;
614                 if(!BaseMath_ReadCallback(quat2))
615                         return NULL;
616         }
617
618         if(quat1 && quat2) { /* QUAT*QUAT (dot product) */
619                 return PyFloat_FromDouble(dot_qtqt(quat1->quat, quat2->quat));
620         }
621         
622         /* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */
623         if(!QuaternionObject_Check(q1)) {
624                 scalar= PyFloat_AsDouble(q1);
625                 if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */
626                         QUATCOPY(quat, quat2->quat);
627                         mul_qt_fl(quat, scalar);
628                         return newQuaternionObject(quat, Py_NEW, NULL);
629                 }
630                 PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: val * quat, val is not an acceptable type");
631                 return NULL;
632         }
633         else { /* QUAT*SOMETHING */
634                 if(VectorObject_Check(q2)){  /* QUAT*VEC */
635                         vec = (VectorObject*)q2;
636                         if(vec->size != 3){
637                                 PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: only 3D vector rotations currently supported\n");
638                                 return NULL;
639                         }
640                         return quat_rotation((PyObject*)quat1, (PyObject*)vec); /* vector updating done inside the func */
641                 }
642                 
643                 scalar= PyFloat_AsDouble(q2);
644                 if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */
645                         QUATCOPY(quat, quat1->quat);
646                         mul_qt_fl(quat, scalar);
647                         return newQuaternionObject(quat, Py_NEW, NULL);
648                 }
649         }
650         
651         PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: arguments not acceptable for this operation\n");
652         return NULL;
653 }
654
655 //-----------------PROTOCOL DECLARATIONS--------------------------
656 static PySequenceMethods Quaternion_SeqMethods = {
657         (lenfunc) Quaternion_len,                                       /* sq_length */
658         (binaryfunc) 0,                                                         /* sq_concat */
659         (ssizeargfunc) 0,                                                               /* sq_repeat */
660         (ssizeargfunc) Quaternion_item,                         /* sq_item */
661         (ssizessizeargfunc) Quaternion_slice,                   /* sq_slice */
662         (ssizeobjargproc) Quaternion_ass_item,          /* sq_ass_item */
663         (ssizessizeobjargproc) Quaternion_ass_slice,    /* sq_ass_slice */
664 };
665
666 static PyNumberMethods Quaternion_NumMethods = {
667                 (binaryfunc)    Quaternion_add, /*nb_add*/
668                 (binaryfunc)    Quaternion_sub, /*nb_subtract*/
669                 (binaryfunc)    Quaternion_mul, /*nb_multiply*/
670                 0,                                                      /*nb_remainder*/
671                 0,                                                      /*nb_divmod*/
672                 0,                                                      /*nb_power*/
673                 (unaryfunc)     0,      /*nb_negative*/
674                 (unaryfunc)     0,      /*tp_positive*/
675                 (unaryfunc)     0,      /*tp_absolute*/
676                 (inquiry)       0,      /*tp_bool*/
677                 (unaryfunc)     0,      /*nb_invert*/
678                 0,                              /*nb_lshift*/
679                 (binaryfunc)0,  /*nb_rshift*/
680                 0,                              /*nb_and*/
681                 0,                              /*nb_xor*/
682                 0,                              /*nb_or*/
683                 0,                              /*nb_int*/
684                 0,                              /*nb_reserved*/
685                 0,                              /*nb_float*/
686                 0,                              /* nb_inplace_add */
687                 0,                              /* nb_inplace_subtract */
688                 0,                              /* nb_inplace_multiply */
689                 0,                              /* nb_inplace_remainder */
690                 0,                              /* nb_inplace_power */
691                 0,                              /* nb_inplace_lshift */
692                 0,                              /* nb_inplace_rshift */
693                 0,                              /* nb_inplace_and */
694                 0,                              /* nb_inplace_xor */
695                 0,                              /* nb_inplace_or */
696                 0,                              /* nb_floor_divide */
697                 0,                              /* nb_true_divide */
698                 0,                              /* nb_inplace_floor_divide */
699                 0,                              /* nb_inplace_true_divide */
700                 0,                              /* nb_index */
701 };
702
703 static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type )
704 {
705         return Quaternion_item(self, GET_INT_FROM_POINTER(type));
706 }
707
708 static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type )
709 {
710         return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), value);
711 }
712
713 static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type )
714 {
715         return PyFloat_FromDouble(sqrt(dot_qtqt(self->quat, self->quat)));
716 }
717
718 static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type )
719 {
720         return PyFloat_FromDouble(2.0 * (saacos(self->quat[0])));
721 }
722
723 static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
724 {
725         int i;
726         float vec[3];
727         double mag = self->quat[0] * (Py_PI / 180);
728         mag = 2 * (saacos(mag));
729         mag = sin(mag / 2);
730         for(i = 0; i < 3; i++)
731                 vec[i] = (float)(self->quat[i + 1] / mag);
732         
733         normalize_v3(vec);
734         //If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations
735         if( EXPP_FloatsAreEqual(vec[0], 0.0f, 10) &&
736                 EXPP_FloatsAreEqual(vec[1], 0.0f, 10) &&
737                 EXPP_FloatsAreEqual(vec[2], 0.0f, 10) ){
738                 vec[0] = 1.0f;
739         }
740         return (PyObject *) newVectorObject(vec, 3, Py_NEW, NULL);
741 }
742
743 //----------------------------------mathutils.Quaternion() --------------
744 static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
745 {
746         PyObject *seq= NULL;
747         double angle = 0.0f;
748         float quat[4]= {0.0f, 0.0f, 0.0f, 0.0f};
749
750         if(!PyArg_ParseTuple(args, "|Of:mathutils.Quaternion", &seq, &angle))
751                 return NULL;
752
753         switch(PyTuple_GET_SIZE(args)) {
754         case 0:
755                 break;
756         case 1:
757                 if (mathutils_array_parse(quat, 4, 4, seq, "mathutils.Quaternion()") == -1)
758                         return NULL;
759                 break;
760         case 2:
761                 if (mathutils_array_parse(quat, 3, 3, seq, "mathutils.Quaternion()") == -1)
762                         return NULL;
763                 axis_angle_to_quat(quat, quat, angle);
764                 break;
765         /* PyArg_ParseTuple assures no more then 2 */
766         }
767         return newQuaternionObject(quat, Py_NEW, NULL);
768 }
769
770
771 //-----------------------METHOD DEFINITIONS ----------------------
772 static struct PyMethodDef Quaternion_methods[] = {
773         {"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, Quaternion_Identity_doc},
774         {"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, Quaternion_Negate_doc},
775         {"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, Quaternion_Conjugate_doc},
776         {"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, Quaternion_Inverse_doc},
777         {"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, Quaternion_Normalize_doc},
778         {"to_euler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, Quaternion_ToEuler_doc},
779         {"to_matrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, Quaternion_ToMatrix_doc},
780         {"cross", (PyCFunction) Quaternion_Cross, METH_O, Quaternion_Cross_doc},
781         {"dot", (PyCFunction) Quaternion_Dot, METH_O, Quaternion_Dot_doc},
782         {"difference", (PyCFunction) Quaternion_Difference, METH_O, Quaternion_Difference_doc},
783         {"slerp", (PyCFunction) Quaternion_Slerp, METH_VARARGS, Quaternion_Slerp_doc},
784         {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
785         {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
786         {NULL, NULL, 0, NULL}
787 };
788
789 /*****************************************************************************/
790 /* Python attributes get/set structure:                                      */
791 /*****************************************************************************/
792 static PyGetSetDef Quaternion_getseters[] = {
793         {"w", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion W value. **type** float", (void *)0},
794         {"x", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion X axis. **type** float", (void *)1},
795         {"y", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Y axis. **type** float", (void *)2},
796         {"z", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Z axis. **type** float", (void *)3},
797         {"magnitude", (getter)Quaternion_getMagnitude, (setter)NULL, "Size of the quaternion (readonly). **type** float", NULL},
798         {"angle", (getter)Quaternion_getAngle, (setter)NULL, "angle of the quaternion (readonly). **type** float", NULL},
799         {"axis",(getter)Quaternion_getAxisVec, (setter)NULL, "quaternion axis as a vector (readonly). **type** :class:`Vector`", NULL},
800         {"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
801         {"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
802         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
803 };
804
805 //------------------PY_OBECT DEFINITION--------------------------
806 static char quaternion_doc[] =
807 "This object gives access to Quaternions in Blender.";
808
809 PyTypeObject quaternion_Type = {
810         PyVarObject_HEAD_INIT(NULL, 0)
811         "quaternion",                                           //tp_name
812         sizeof(QuaternionObject),                       //tp_basicsize
813         0,                                                              //tp_itemsize
814         (destructor)BaseMathObject_dealloc,             //tp_dealloc
815         0,                                                              //tp_print
816         0,                                                              //tp_getattr
817         0,                                                              //tp_setattr
818         0,                                                              //tp_compare
819         (reprfunc) Quaternion_repr,                     //tp_repr
820         &Quaternion_NumMethods,                         //tp_as_number
821         &Quaternion_SeqMethods,                         //tp_as_sequence
822         0,                                                              //tp_as_mapping
823         0,                                                              //tp_hash
824         0,                                                              //tp_call
825         0,                                                              //tp_str
826         0,                                                              //tp_getattro
827         0,                                                              //tp_setattro
828         0,                                                              //tp_as_buffer
829         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
830         quaternion_doc, //tp_doc
831         0,                                                              //tp_traverse
832         0,                                                              //tp_clear
833         (richcmpfunc)Quaternion_richcmpr,       //tp_richcompare
834         0,                                                              //tp_weaklistoffset
835         0,                                                              //tp_iter
836         0,                                                              //tp_iternext
837         Quaternion_methods,                             //tp_methods
838         0,                                                              //tp_members
839         Quaternion_getseters,                   //tp_getset
840         0,                                                              //tp_base
841         0,                                                              //tp_dict
842         0,                                                              //tp_descr_get
843         0,                                                              //tp_descr_set
844         0,                                                              //tp_dictoffset
845         0,                                                              //tp_init
846         0,                                                              //tp_alloc
847         Quaternion_new,                                 //tp_new
848         0,                                                              //tp_free
849         0,                                                              //tp_is_gc
850         0,                                                              //tp_bases
851         0,                                                              //tp_mro
852         0,                                                              //tp_cache
853         0,                                                              //tp_subclasses
854         0,                                                              //tp_weaklist
855         0                                                               //tp_del
856 };
857 //------------------------newQuaternionObject (internal)-------------
858 //creates a new quaternion object
859 /*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
860  (i.e. it was allocated elsewhere by MEM_mallocN())
861   pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
862  (i.e. it must be created here with PyMEM_malloc())*/
863 PyObject *newQuaternionObject(float *quat, int type, PyTypeObject *base_type)
864 {
865         QuaternionObject *self;
866         
867         if(base_type)   self = (QuaternionObject *)base_type->tp_alloc(base_type, 0);
868         else                    self = PyObject_NEW(QuaternionObject, &quaternion_Type);
869
870         /* init callbacks as NULL */
871         self->cb_user= NULL;
872         self->cb_type= self->cb_subtype= 0;
873
874         if(type == Py_WRAP){
875                 self->quat = quat;
876                 self->wrapped = Py_WRAP;
877         }else if (type == Py_NEW){
878                 self->quat = PyMem_Malloc(4 * sizeof(float));
879                 if(!quat) { //new empty
880                         unit_qt(self->quat);
881                 }else{
882                         QUATCOPY(self->quat, quat);
883                 }
884                 self->wrapped = Py_NEW;
885         }else{ //bad type
886                 return NULL;
887         }
888         return (PyObject *) self;
889 }
890
891 PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
892 {
893         QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW, NULL);
894         if(self) {
895                 Py_INCREF(cb_user);
896                 self->cb_user=                  cb_user;
897                 self->cb_type=                  (unsigned char)cb_type;
898                 self->cb_subtype=               (unsigned char)cb_subtype;
899         }
900
901         return (PyObject *)self;
902 }
903