bugfix [#22163] Add->mesh->torus is broken
[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) 0,                                                         /* sq_concat */
712         (ssizeargfunc) 0,                                                               /* 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 };
718
719 static PyMappingMethods Quaternion_AsMapping = {
720         (lenfunc)Quaternion_len,
721         (binaryfunc)Quaternion_subscript,
722         (objobjargproc)Quaternion_ass_subscript
723 };
724
725 static PyNumberMethods Quaternion_NumMethods = {
726         (binaryfunc)    Quaternion_add, /*nb_add*/
727         (binaryfunc)    Quaternion_sub, /*nb_subtract*/
728         (binaryfunc)    Quaternion_mul, /*nb_multiply*/
729         0,                                                      /*nb_remainder*/
730         0,                                                      /*nb_divmod*/
731         0,                                                      /*nb_power*/
732         (unaryfunc)     0,      /*nb_negative*/
733         (unaryfunc)     0,      /*tp_positive*/
734         (unaryfunc)     0,      /*tp_absolute*/
735         (inquiry)       0,      /*tp_bool*/
736         (unaryfunc)     0,      /*nb_invert*/
737         0,                              /*nb_lshift*/
738         (binaryfunc)0,  /*nb_rshift*/
739         0,                              /*nb_and*/
740         0,                              /*nb_xor*/
741         0,                              /*nb_or*/
742         0,                              /*nb_int*/
743         0,                              /*nb_reserved*/
744         0,                              /*nb_float*/
745         0,                              /* nb_inplace_add */
746         0,                              /* nb_inplace_subtract */
747         0,                              /* nb_inplace_multiply */
748         0,                              /* nb_inplace_remainder */
749         0,                              /* nb_inplace_power */
750         0,                              /* nb_inplace_lshift */
751         0,                              /* nb_inplace_rshift */
752         0,                              /* nb_inplace_and */
753         0,                              /* nb_inplace_xor */
754         0,                              /* nb_inplace_or */
755         0,                              /* nb_floor_divide */
756         0,                              /* nb_true_divide */
757         0,                              /* nb_inplace_floor_divide */
758         0,                              /* nb_inplace_true_divide */
759         0,                              /* nb_index */
760 };
761
762 static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type )
763 {
764         return Quaternion_item(self, GET_INT_FROM_POINTER(type));
765 }
766
767 static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type )
768 {
769         return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), value);
770 }
771
772 static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type )
773 {
774         return PyFloat_FromDouble(sqrt(dot_qtqt(self->quat, self->quat)));
775 }
776
777 static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type )
778 {
779         return PyFloat_FromDouble(2.0 * (saacos(self->quat[0])));
780 }
781
782 static PyObject *Quaternion_getAxisVec( QuaternionObject * self, void *type )
783 {
784         float vec[3];
785
786         normalize_v3_v3(vec, self->quat+1);
787
788         /* If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations */
789         if( EXPP_FloatsAreEqual(vec[0], 0.0f, 10) &&
790                 EXPP_FloatsAreEqual(vec[1], 0.0f, 10) &&
791                 EXPP_FloatsAreEqual(vec[2], 0.0f, 10) ){
792                 vec[0] = 1.0f;
793         }
794         return (PyObject *) newVectorObject(vec, 3, Py_NEW, NULL);
795 }
796
797 //----------------------------------mathutils.Quaternion() --------------
798 static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
799 {
800         PyObject *seq= NULL;
801         float angle = 0.0f;
802         float quat[QUAT_SIZE]= {0.0f, 0.0f, 0.0f, 0.0f};
803
804         if(!PyArg_ParseTuple(args, "|Of:mathutils.Quaternion", &seq, &angle))
805                 return NULL;
806
807         switch(PyTuple_GET_SIZE(args)) {
808         case 0:
809                 break;
810         case 1:
811                 if (mathutils_array_parse(quat, QUAT_SIZE, QUAT_SIZE, seq, "mathutils.Quaternion()") == -1)
812                         return NULL;
813                 break;
814         case 2:
815                 if (mathutils_array_parse(quat, 3, 3, seq, "mathutils.Quaternion()") == -1)
816                         return NULL;
817
818                 axis_angle_to_quat(quat, quat, angle);
819                 break;
820         /* PyArg_ParseTuple assures no more then 2 */
821         }
822         return newQuaternionObject(quat, Py_NEW, NULL);
823 }
824
825
826 //-----------------------METHOD DEFINITIONS ----------------------
827 static struct PyMethodDef Quaternion_methods[] = {
828         {"identity", (PyCFunction) Quaternion_Identity, METH_NOARGS, Quaternion_Identity_doc},
829         {"negate", (PyCFunction) Quaternion_Negate, METH_NOARGS, Quaternion_Negate_doc},
830         {"conjugate", (PyCFunction) Quaternion_Conjugate, METH_NOARGS, Quaternion_Conjugate_doc},
831         {"inverse", (PyCFunction) Quaternion_Inverse, METH_NOARGS, Quaternion_Inverse_doc},
832         {"normalize", (PyCFunction) Quaternion_Normalize, METH_NOARGS, Quaternion_Normalize_doc},
833         {"to_euler", (PyCFunction) Quaternion_ToEuler, METH_VARARGS, Quaternion_ToEuler_doc},
834         {"to_matrix", (PyCFunction) Quaternion_ToMatrix, METH_NOARGS, Quaternion_ToMatrix_doc},
835         {"cross", (PyCFunction) Quaternion_Cross, METH_O, Quaternion_Cross_doc},
836         {"dot", (PyCFunction) Quaternion_Dot, METH_O, Quaternion_Dot_doc},
837         {"difference", (PyCFunction) Quaternion_Difference, METH_O, Quaternion_Difference_doc},
838         {"slerp", (PyCFunction) Quaternion_Slerp, METH_VARARGS, Quaternion_Slerp_doc},
839         {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
840         {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
841         {NULL, NULL, 0, NULL}
842 };
843
844 /*****************************************************************************/
845 /* Python attributes get/set structure:                                      */
846 /*****************************************************************************/
847 static PyGetSetDef Quaternion_getseters[] = {
848         {"w", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion W value. **type** float", (void *)0},
849         {"x", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion X axis. **type** float", (void *)1},
850         {"y", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Y axis. **type** float", (void *)2},
851         {"z", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Z axis. **type** float", (void *)3},
852         {"magnitude", (getter)Quaternion_getMagnitude, (setter)NULL, "Size of the quaternion (readonly). **type** float", NULL},
853         {"angle", (getter)Quaternion_getAngle, (setter)NULL, "angle of the quaternion (readonly). **type** float", NULL},
854         {"axis",(getter)Quaternion_getAxisVec, (setter)NULL, "quaternion axis as a vector (readonly). **type** :class:`Vector`", NULL},
855         {"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
856         {"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
857         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
858 };
859
860 //------------------PY_OBECT DEFINITION--------------------------
861 static char quaternion_doc[] =
862 "This object gives access to Quaternions in Blender.";
863
864 PyTypeObject quaternion_Type = {
865         PyVarObject_HEAD_INIT(NULL, 0)
866         "quaternion",                                           //tp_name
867         sizeof(QuaternionObject),                       //tp_basicsize
868         0,                                                              //tp_itemsize
869         (destructor)BaseMathObject_dealloc,             //tp_dealloc
870         0,                                                              //tp_print
871         0,                                                              //tp_getattr
872         0,                                                              //tp_setattr
873         0,                                                              //tp_compare
874         (reprfunc) Quaternion_repr,             //tp_repr
875         &Quaternion_NumMethods,                 //tp_as_number
876         &Quaternion_SeqMethods,                 //tp_as_sequence
877         &Quaternion_AsMapping,                  //tp_as_mapping
878         0,                                                              //tp_hash
879         0,                                                              //tp_call
880         0,                                                              //tp_str
881         0,                                                              //tp_getattro
882         0,                                                              //tp_setattro
883         0,                                                              //tp_as_buffer
884         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
885         quaternion_doc, //tp_doc
886         0,                                                              //tp_traverse
887         0,                                                              //tp_clear
888         (richcmpfunc)Quaternion_richcmpr,       //tp_richcompare
889         0,                                                              //tp_weaklistoffset
890         0,                                                              //tp_iter
891         0,                                                              //tp_iternext
892         Quaternion_methods,                             //tp_methods
893         0,                                                              //tp_members
894         Quaternion_getseters,                   //tp_getset
895         0,                                                              //tp_base
896         0,                                                              //tp_dict
897         0,                                                              //tp_descr_get
898         0,                                                              //tp_descr_set
899         0,                                                              //tp_dictoffset
900         0,                                                              //tp_init
901         0,                                                              //tp_alloc
902         Quaternion_new,                                 //tp_new
903         0,                                                              //tp_free
904         0,                                                              //tp_is_gc
905         0,                                                              //tp_bases
906         0,                                                              //tp_mro
907         0,                                                              //tp_cache
908         0,                                                              //tp_subclasses
909         0,                                                              //tp_weaklist
910         0                                                               //tp_del
911 };
912 //------------------------newQuaternionObject (internal)-------------
913 //creates a new quaternion object
914 /*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
915  (i.e. it was allocated elsewhere by MEM_mallocN())
916   pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
917  (i.e. it must be created here with PyMEM_malloc())*/
918 PyObject *newQuaternionObject(float *quat, int type, PyTypeObject *base_type)
919 {
920         QuaternionObject *self;
921         
922         if(base_type)   self = (QuaternionObject *)base_type->tp_alloc(base_type, 0);
923         else                    self = PyObject_NEW(QuaternionObject, &quaternion_Type);
924
925         /* init callbacks as NULL */
926         self->cb_user= NULL;
927         self->cb_type= self->cb_subtype= 0;
928
929         if(type == Py_WRAP){
930                 self->quat = quat;
931                 self->wrapped = Py_WRAP;
932         }else if (type == Py_NEW){
933                 self->quat = PyMem_Malloc(QUAT_SIZE * sizeof(float));
934                 if(!quat) { //new empty
935                         unit_qt(self->quat);
936                 }else{
937                         QUATCOPY(self->quat, quat);
938                 }
939                 self->wrapped = Py_NEW;
940         }else{ //bad type
941                 return NULL;
942         }
943         return (PyObject *) self;
944 }
945
946 PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
947 {
948         QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW, NULL);
949         if(self) {
950                 Py_INCREF(cb_user);
951                 self->cb_user=                  cb_user;
952                 self->cb_type=                  (unsigned char)cb_type;
953                 self->cb_subtype=               (unsigned char)cb_subtype;
954         }
955
956         return (PyObject *)self;
957 }
958