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