imbuf, mathutils & readfile: floats were being implicitly promoted to doubles, adjust...
[blender.git] / source / blender / python / generic / mathutils_Quaternion.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 /** \file blender/python/generic/mathutils_Quaternion.c
30  *  \ingroup pygen
31  */
32
33
34 #include <Python.h>
35
36 #include "mathutils.h"
37
38 #include "BLI_math.h"
39 #include "BLI_utildefines.h"
40
41 #define QUAT_SIZE 4
42
43 static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self);
44 static PyObject *Quaternion_copy(QuaternionObject *self);
45
46 //-----------------------------METHODS------------------------------
47
48 /* note: BaseMath_ReadCallback must be called beforehand */
49 static PyObject *Quaternion_to_tuple_ext(QuaternionObject *self, int ndigits)
50 {
51         PyObject *ret;
52         int i;
53
54         ret= PyTuple_New(QUAT_SIZE);
55
56         if(ndigits >= 0) {
57                 for(i= 0; i < QUAT_SIZE; i++) {
58                         PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->quat[i], ndigits)));
59                 }
60         }
61         else {
62                 for(i= 0; i < QUAT_SIZE; i++) {
63                         PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->quat[i]));
64                 }
65         }
66
67         return ret;
68 }
69
70 static char Quaternion_to_euler_doc[] =
71 ".. method:: to_euler(order, euler_compat)\n"
72 "\n"
73 "   Return Euler representation of the quaternion.\n"
74 "\n"
75 "   :arg order: Optional rotation order argument in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
76 "   :type order: string\n"
77 "   :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"
78 "   :type euler_compat: :class:`Euler`\n"
79 "   :return: Euler representation of the quaternion.\n"
80 "   :rtype: :class:`Euler`\n"
81 ;
82 static PyObject *Quaternion_to_euler(QuaternionObject *self, PyObject *args)
83 {
84         float tquat[4];
85         float eul[3];
86         const char *order_str= NULL;
87         short order= EULER_ORDER_XYZ;
88         EulerObject *eul_compat = NULL;
89
90         if(!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
91                 return NULL;
92
93         if(BaseMath_ReadCallback(self) == -1)
94                 return NULL;
95
96         if(order_str) {
97                 order= euler_order_from_string(order_str, "Matrix.to_euler()");
98
99                 if(order == -1)
100                         return NULL;
101         }
102
103         normalize_qt_qt(tquat, self->quat);
104
105         if(eul_compat) {
106                 float mat[3][3];
107
108                 if(BaseMath_ReadCallback(eul_compat) == -1)
109                         return NULL;
110
111                 quat_to_mat3(mat, tquat);
112
113                 if(order == EULER_ORDER_XYZ)    mat3_to_compatible_eul(eul, eul_compat->eul, mat);
114                 else                                                    mat3_to_compatible_eulO(eul, eul_compat->eul, order, mat);
115         }
116         else {
117                 if(order == EULER_ORDER_XYZ)    quat_to_eul(eul, tquat);
118                 else                                                    quat_to_eulO(eul, order, tquat);
119         }
120
121         return newEulerObject(eul, order, Py_NEW, NULL);
122 }
123 //----------------------------Quaternion.toMatrix()------------------
124 static char Quaternion_to_matrix_doc[] =
125 ".. method:: to_matrix()\n"
126 "\n"
127 "   Return a matrix representation of the quaternion.\n"
128 "\n"
129 "   :return: A 3x3 rotation matrix representation of the quaternion.\n"
130 "   :rtype: :class:`Matrix`\n"
131 ;
132 static PyObject *Quaternion_to_matrix(QuaternionObject *self)
133 {
134         float mat[9]; /* all values are set */
135
136         if(BaseMath_ReadCallback(self) == -1)
137                 return NULL;
138
139         quat_to_mat3((float (*)[3])mat, self->quat);
140         return newMatrixObject(mat, 3, 3, Py_NEW, NULL);
141 }
142
143 //----------------------------Quaternion.cross(other)------------------
144 static char Quaternion_cross_doc[] =
145 ".. method:: cross(other)\n"
146 "\n"
147 "   Return the cross product of this quaternion and another.\n"
148 "\n"
149 "   :arg other: The other quaternion to perform the cross product with.\n"
150 "   :type other: :class:`Quaternion`\n"
151 "   :return: The cross product.\n"
152 "   :rtype: :class:`Quaternion`\n"
153 ;
154 static PyObject *Quaternion_cross(QuaternionObject *self, PyObject *value)
155 {
156         float quat[QUAT_SIZE], tquat[QUAT_SIZE];
157
158         if(BaseMath_ReadCallback(self) == -1)
159                 return NULL;
160
161         if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.cross(other), invalid 'other' arg") == -1)
162                 return NULL;
163
164         mul_qt_qtqt(quat, self->quat, tquat);
165         return newQuaternionObject(quat, Py_NEW, Py_TYPE(self));
166 }
167
168 //----------------------------Quaternion.dot(other)------------------
169 static char Quaternion_dot_doc[] =
170 ".. method:: dot(other)\n"
171 "\n"
172 "   Return the dot product of this quaternion and another.\n"
173 "\n"
174 "   :arg other: The other quaternion to perform the dot product with.\n"
175 "   :type other: :class:`Quaternion`\n"
176 "   :return: The dot product.\n"
177 "   :rtype: :class:`Quaternion`\n"
178 ;
179 static PyObject *Quaternion_dot(QuaternionObject *self, PyObject *value)
180 {
181         float tquat[QUAT_SIZE];
182
183         if(BaseMath_ReadCallback(self) == -1)
184                 return NULL;
185
186         if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.dot(other), invalid 'other' arg") == -1)
187                 return NULL;
188
189         return PyFloat_FromDouble(dot_qtqt(self->quat, tquat));
190 }
191
192 static char Quaternion_difference_doc[] =
193 ".. function:: difference(other)\n"
194 "\n"
195 "   Returns a quaternion representing the rotational difference.\n"
196 "\n"
197 "   :arg other: second quaternion.\n"
198 "   :type other: :class:`Quaternion`\n"
199 "   :return: the rotational difference between the two quat rotations.\n"
200 "   :rtype: :class:`Quaternion`\n"
201 ;
202 static PyObject *Quaternion_difference(QuaternionObject *self, PyObject *value)
203 {
204         float tquat[QUAT_SIZE], quat[QUAT_SIZE];
205
206         if(BaseMath_ReadCallback(self) == -1)
207                 return NULL;
208
209         if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.difference(other), invalid 'other' arg") == -1)
210                 return NULL;
211
212         rotation_between_quats_to_quat(quat, self->quat, tquat);
213
214         return newQuaternionObject(quat, Py_NEW, Py_TYPE(self));
215 }
216
217 static char Quaternion_slerp_doc[] =
218 ".. function:: slerp(other, factor)\n"
219 "\n"
220 "   Returns the interpolation of two quaternions.\n"
221 "\n"
222 "   :arg other: value to interpolate with.\n"
223 "   :type other: :class:`Quaternion`\n"
224 "   :arg factor: The interpolation value in [0.0, 1.0].\n"
225 "   :type factor: float\n"
226 "   :return: The interpolated rotation.\n"
227 "   :rtype: :class:`Quaternion`\n"
228 ;
229 static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args)
230 {
231         PyObject *value;
232         float tquat[QUAT_SIZE], quat[QUAT_SIZE], fac;
233
234         if(!PyArg_ParseTuple(args, "Of:slerp", &value, &fac)) {
235                 PyErr_SetString(PyExc_TypeError, "quat.slerp(): expected Quaternion types and float");
236                 return NULL;
237         }
238
239         if(BaseMath_ReadCallback(self) == -1)
240                 return NULL;
241
242         if(mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, "quaternion.slerp(other), invalid 'other' arg") == -1)
243                 return NULL;
244
245         if(fac > 1.0f || fac < 0.0f) {
246                 PyErr_SetString(PyExc_AttributeError, "quat.slerp(): interpolation factor must be between 0.0 and 1.0");
247                 return NULL;
248         }
249
250         interp_qt_qtqt(quat, self->quat, tquat, fac);
251
252         return newQuaternionObject(quat, Py_NEW, Py_TYPE(self));
253 }
254
255 static char Quaternion_rotate_doc[] =
256 ".. method:: rotate(other)\n"
257 "\n"
258 "   Rotates the quaternion a by another mathutils value.\n"
259 "\n"
260 "   :arg other: rotation component of mathutils value\n"
261 "   :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
262 ;
263 static PyObject *Quaternion_rotate(QuaternionObject *self, PyObject *value)
264 {
265         float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
266         float tquat[4], length;
267
268         if(BaseMath_ReadCallback(self) == -1)
269                 return NULL;
270
271         if(mathutils_any_to_rotmat(other_rmat, value, "quaternion.rotate(value)") == -1)
272                 return NULL;
273
274         length= normalize_qt_qt(tquat, self->quat);
275         quat_to_mat3(self_rmat, tquat);
276         mul_m3_m3m3(rmat, self_rmat, other_rmat);
277
278         mat3_to_quat(self->quat, rmat);
279         mul_qt_fl(self->quat, length); /* maintain length after rotating */
280
281         (void)BaseMath_WriteCallback(self);
282         Py_RETURN_NONE;
283 }
284
285 //----------------------------Quaternion.normalize()----------------
286 //normalize the axis of rotation of [theta, vector]
287 static char Quaternion_normalize_doc[] =
288 ".. function:: normalize()\n"
289 "\n"
290 "   Normalize the quaternion.\n"
291 ;
292 static PyObject *Quaternion_normalize(QuaternionObject *self)
293 {
294         if(BaseMath_ReadCallback(self) == -1)
295                 return NULL;
296
297         normalize_qt(self->quat);
298
299         (void)BaseMath_WriteCallback(self);
300         Py_RETURN_NONE;
301 }
302 static char Quaternion_normalized_doc[] =
303 ".. function:: normalized()\n"
304 "\n"
305 "   Return a new normalized quaternion.\n"
306 "\n"
307 "   :return: a normalized copy.\n"
308 "   :rtype: :class:`Quaternion`\n"
309 ;
310 static PyObject *Quaternion_normalized(QuaternionObject *self)
311 {
312         return quat__apply_to_copy((PyNoArgsFunction)Quaternion_normalize, self);
313 }
314
315 //----------------------------Quaternion.invert()------------------
316 static char Quaternion_invert_doc[] =
317 ".. function:: invert()\n"
318 "\n"
319 "   Set the quaternion to its inverse.\n"
320 ;
321 static PyObject *Quaternion_invert(QuaternionObject *self)
322 {
323         if(BaseMath_ReadCallback(self) == -1)
324                 return NULL;
325
326         invert_qt(self->quat);
327
328         (void)BaseMath_WriteCallback(self);
329         Py_RETURN_NONE;
330 }
331 static char Quaternion_inverted_doc[] =
332 ".. function:: inverted()\n"
333 "\n"
334 "   Return a new, inverted quaternion.\n"
335 "\n"
336 "   :return: the inverted value.\n"
337 "   :rtype: :class:`Quaternion`\n"
338 ;
339 static PyObject *Quaternion_inverted(QuaternionObject *self)
340 {
341         return quat__apply_to_copy((PyNoArgsFunction)Quaternion_invert, self);
342 }
343
344 //----------------------------Quaternion.identity()-----------------
345 static char Quaternion_identity_doc[] =
346 ".. function:: identity()\n"
347 "\n"
348 "   Set the quaternion to an identity quaternion.\n"
349 "\n"
350 "   :return: an instance of itself.\n"
351 "   :rtype: :class:`Quaternion`\n"
352 ;
353 static PyObject *Quaternion_identity(QuaternionObject *self)
354 {
355         if(BaseMath_ReadCallback(self) == -1)
356                 return NULL;
357
358         unit_qt(self->quat);
359
360         (void)BaseMath_WriteCallback(self);
361         Py_RETURN_NONE;
362 }
363 //----------------------------Quaternion.negate()-------------------
364 static char Quaternion_negate_doc[] =
365 ".. function:: negate()\n"
366 "\n"
367 "   Set the quaternion to its negative.\n"
368 "\n"
369 "   :return: an instance of itself.\n"
370 "   :rtype: :class:`Quaternion`\n"
371 ;
372 static PyObject *Quaternion_negate(QuaternionObject *self)
373 {
374         if(BaseMath_ReadCallback(self) == -1)
375                 return NULL;
376
377         mul_qt_fl(self->quat, -1.0f);
378
379         (void)BaseMath_WriteCallback(self);
380         Py_RETURN_NONE;
381 }
382 //----------------------------Quaternion.conjugate()----------------
383 static char Quaternion_conjugate_doc[] =
384 ".. function:: conjugate()\n"
385 "\n"
386 "   Set the quaternion to its conjugate (negate x, y, z).\n"
387 ;
388 static PyObject *Quaternion_conjugate(QuaternionObject *self)
389 {
390         if(BaseMath_ReadCallback(self) == -1)
391                 return NULL;
392
393         conjugate_qt(self->quat);
394
395         (void)BaseMath_WriteCallback(self);
396         Py_RETURN_NONE;
397 }
398 static char Quaternion_conjugated_doc[] =
399 ".. function:: conjugated()\n"
400 "\n"
401 "   Return a new conjugated quaternion.\n"
402 "\n"
403 "   :return: a new quaternion.\n"
404 "   :rtype: :class:`Quaternion`\n"
405 ;
406 static PyObject *Quaternion_conjugated(QuaternionObject *self)
407 {
408         return quat__apply_to_copy((PyNoArgsFunction)Quaternion_conjugate, self);
409 }
410
411 //----------------------------Quaternion.copy()----------------
412 static char Quaternion_copy_doc[] =
413 ".. function:: copy()\n"
414 "\n"
415 "   Returns a copy of this quaternion.\n"
416 "\n"
417 "   :return: A copy of the quaternion.\n"
418 "   :rtype: :class:`Quaternion`\n"
419 "\n"
420 "   .. note:: use this to get a copy of a wrapped quaternion with no reference to the original data.\n"
421 ;
422 static PyObject *Quaternion_copy(QuaternionObject *self)
423 {
424         if(BaseMath_ReadCallback(self) == -1)
425                 return NULL;
426
427         return newQuaternionObject(self->quat, Py_NEW, Py_TYPE(self));
428 }
429
430 //----------------------------print object (internal)--------------
431 //print the object to screen
432 static PyObject *Quaternion_repr(QuaternionObject *self)
433 {
434         PyObject *ret, *tuple;
435
436         if(BaseMath_ReadCallback(self) == -1)
437                 return NULL;
438
439         tuple= Quaternion_to_tuple_ext(self, -1);
440
441         ret= PyUnicode_FromFormat("Quaternion(%R)", tuple);
442
443         Py_DECREF(tuple);
444         return ret;
445 }
446
447 static PyObject* Quaternion_richcmpr(PyObject *a, PyObject *b, int op)
448 {
449         PyObject *res;
450         int ok= -1; /* zero is true */
451
452         if (QuaternionObject_Check(a) && QuaternionObject_Check(b)) {
453                 QuaternionObject *quatA= (QuaternionObject *)a;
454                 QuaternionObject *quatB= (QuaternionObject *)b;
455
456                 if(BaseMath_ReadCallback(quatA) == -1 || BaseMath_ReadCallback(quatB) == -1)
457                         return NULL;
458
459                 ok= (EXPP_VectorsAreEqual(quatA->quat, quatB->quat, QUAT_SIZE, 1)) ? 0 : -1;
460         }
461
462         switch (op) {
463         case Py_NE:
464                 ok = !ok; /* pass through */
465         case Py_EQ:
466                 res = ok ? Py_False : Py_True;
467                 break;
468
469         case Py_LT:
470         case Py_LE:
471         case Py_GT:
472         case Py_GE:
473                 res = Py_NotImplemented;
474                 break;
475         default:
476                 PyErr_BadArgument();
477                 return NULL;
478         }
479
480         return Py_INCREF(res), res;
481 }
482
483 //---------------------SEQUENCE PROTOCOLS------------------------
484 //----------------------------len(object)------------------------
485 //sequence length
486 static int Quaternion_len(QuaternionObject *UNUSED(self))
487 {
488         return QUAT_SIZE;
489 }
490 //----------------------------object[]---------------------------
491 //sequence accessor (get)
492 static PyObject *Quaternion_item(QuaternionObject *self, int i)
493 {
494         if(i<0) i= QUAT_SIZE-i;
495
496         if(i < 0 || i >= QUAT_SIZE) {
497                 PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range");
498                 return NULL;
499         }
500
501         if(BaseMath_ReadIndexCallback(self, i) == -1)
502                 return NULL;
503
504         return PyFloat_FromDouble(self->quat[i]);
505
506 }
507 //----------------------------object[]-------------------------
508 //sequence accessor (set)
509 static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob)
510 {
511         float scalar= (float)PyFloat_AsDouble(ob);
512         if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
513                 PyErr_SetString(PyExc_TypeError, "quaternion[index] = x: index argument not a number");
514                 return -1;
515         }
516
517         if(i<0) i= QUAT_SIZE-i;
518
519         if(i < 0 || i >= QUAT_SIZE){
520                 PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range");
521                 return -1;
522         }
523         self->quat[i] = scalar;
524
525         if(BaseMath_WriteIndexCallback(self, i) == -1)
526                 return -1;
527
528         return 0;
529 }
530 //----------------------------object[z:y]------------------------
531 //sequence slice (get)
532 static PyObject *Quaternion_slice(QuaternionObject *self, int begin, int end)
533 {
534         PyObject *tuple;
535         int count;
536
537         if(BaseMath_ReadCallback(self) == -1)
538                 return NULL;
539
540         CLAMP(begin, 0, QUAT_SIZE);
541         if (end<0) end= (QUAT_SIZE + 1) + end;
542         CLAMP(end, 0, QUAT_SIZE);
543         begin= MIN2(begin, end);
544
545         tuple= PyTuple_New(end - begin);
546         for(count= begin; count < end; count++) {
547                 PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->quat[count]));
548         }
549
550         return tuple;
551 }
552 //----------------------------object[z:y]------------------------
553 //sequence slice (set)
554 static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyObject *seq)
555 {
556         int i, size;
557         float quat[QUAT_SIZE];
558
559         if(BaseMath_ReadCallback(self) == -1)
560                 return -1;
561
562         CLAMP(begin, 0, QUAT_SIZE);
563         if (end<0) end= (QUAT_SIZE + 1) + end;
564         CLAMP(end, 0, QUAT_SIZE);
565         begin = MIN2(begin, end);
566
567         if((size=mathutils_array_parse(quat, 0, QUAT_SIZE, seq, "mathutils.Quaternion[begin:end] = []")) == -1)
568                 return -1;
569
570         if(size != (end - begin)){
571                 PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: size mismatch in slice assignment");
572                 return -1;
573         }
574
575         /* parsed well - now set in vector */
576         for(i= 0; i < size; i++)
577                 self->quat[begin + i] = quat[i];
578
579         (void)BaseMath_WriteCallback(self);
580         return 0;
581 }
582
583
584 static PyObject *Quaternion_subscript(QuaternionObject *self, PyObject *item)
585 {
586         if (PyIndex_Check(item)) {
587                 Py_ssize_t i;
588                 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
589                 if (i == -1 && PyErr_Occurred())
590                         return NULL;
591                 if (i < 0)
592                         i += QUAT_SIZE;
593                 return Quaternion_item(self, i);
594         } else if (PySlice_Check(item)) {
595                 Py_ssize_t start, stop, step, slicelength;
596
597                 if (PySlice_GetIndicesEx((void *)item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0)
598                         return NULL;
599
600                 if (slicelength <= 0) {
601                         return PyTuple_New(0);
602                 }
603                 else if (step == 1) {
604                         return Quaternion_slice(self, start, stop);
605                 }
606                 else {
607                         PyErr_SetString(PyExc_TypeError, "slice steps not supported with quaternions");
608                         return NULL;
609                 }
610         }
611         else {
612                 PyErr_Format(PyExc_TypeError, "quaternion indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
613                 return NULL;
614         }
615 }
616
617
618 static int Quaternion_ass_subscript(QuaternionObject *self, PyObject *item, PyObject *value)
619 {
620         if (PyIndex_Check(item)) {
621                 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
622                 if (i == -1 && PyErr_Occurred())
623                         return -1;
624                 if (i < 0)
625                         i += QUAT_SIZE;
626                 return Quaternion_ass_item(self, i, value);
627         }
628         else if (PySlice_Check(item)) {
629                 Py_ssize_t start, stop, step, slicelength;
630
631                 if (PySlice_GetIndicesEx((void *)item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0)
632                         return -1;
633
634                 if (step == 1)
635                         return Quaternion_ass_slice(self, start, stop, value);
636                 else {
637                         PyErr_SetString(PyExc_TypeError, "slice steps not supported with quaternion");
638                         return -1;
639                 }
640         }
641         else {
642                 PyErr_Format(PyExc_TypeError, "quaternion indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
643                 return -1;
644         }
645 }
646
647 //------------------------NUMERIC PROTOCOLS----------------------
648 //------------------------obj + obj------------------------------
649 //addition
650 static PyObject *Quaternion_add(PyObject *q1, PyObject *q2)
651 {
652         float quat[QUAT_SIZE];
653         QuaternionObject *quat1 = NULL, *quat2 = NULL;
654
655         if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
656                 PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation");
657                 return NULL;
658         }
659         quat1 = (QuaternionObject*)q1;
660         quat2 = (QuaternionObject*)q2;
661
662         if(BaseMath_ReadCallback(quat1) == -1 || BaseMath_ReadCallback(quat2) == -1)
663                 return NULL;
664
665         add_qt_qtqt(quat, quat1->quat, quat2->quat, 1.0f);
666         return newQuaternionObject(quat, Py_NEW, Py_TYPE(q1));
667 }
668 //------------------------obj - obj------------------------------
669 //subtraction
670 static PyObject *Quaternion_sub(PyObject *q1, PyObject *q2)
671 {
672         int x;
673         float quat[QUAT_SIZE];
674         QuaternionObject *quat1 = NULL, *quat2 = NULL;
675
676         if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) {
677                 PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation");
678                 return NULL;
679         }
680
681         quat1 = (QuaternionObject*)q1;
682         quat2 = (QuaternionObject*)q2;
683
684         if(BaseMath_ReadCallback(quat1) == -1 || BaseMath_ReadCallback(quat2) == -1)
685                 return NULL;
686
687         for(x = 0; x < QUAT_SIZE; x++) {
688                 quat[x] = quat1->quat[x] - quat2->quat[x];
689         }
690
691         return newQuaternionObject(quat, Py_NEW, Py_TYPE(q1));
692 }
693
694 static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar)
695 {
696         float tquat[4];
697         copy_qt_qt(tquat, quat->quat);
698         mul_qt_fl(tquat, scalar);
699         return newQuaternionObject(tquat, Py_NEW, Py_TYPE(quat));
700 }
701
702 //------------------------obj * obj------------------------------
703 //mulplication
704 static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2)
705 {
706         float quat[QUAT_SIZE], scalar;
707         QuaternionObject *quat1 = NULL, *quat2 = NULL;
708
709         if(QuaternionObject_Check(q1)) {
710                 quat1 = (QuaternionObject*)q1;
711                 if(BaseMath_ReadCallback(quat1) == -1)
712                         return NULL;
713         }
714         if(QuaternionObject_Check(q2)) {
715                 quat2 = (QuaternionObject*)q2;
716                 if(BaseMath_ReadCallback(quat2) == -1)
717                         return NULL;
718         }
719
720         if(quat1 && quat2) { /* QUAT*QUAT (cross product) */
721                 mul_qt_qtqt(quat, quat1->quat, quat2->quat);
722                 return newQuaternionObject(quat, Py_NEW, Py_TYPE(q1));
723         }
724         /* the only case this can happen (for a supported type is "FLOAT*QUAT") */
725         else if(quat2) { /* FLOAT*QUAT */
726                 if(((scalar= PyFloat_AsDouble(q1)) == -1.0f && PyErr_Occurred())==0) {
727                         return quat_mul_float(quat2, scalar);
728                 }
729         }
730         else if (quat1) { /* QUAT*FLOAT */
731                 if((((scalar= PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred())==0)) {
732                         return quat_mul_float(quat1, scalar);
733                 }
734         }
735         else {
736                 BLI_assert(!"internal error");
737         }
738
739         PyErr_Format(PyExc_TypeError, "Quaternion multiplication: not supported between '%.200s' and '%.200s' types", Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name);
740         return NULL;
741 }
742
743 /* -obj
744   returns the negative of this object*/
745 static PyObject *Quaternion_neg(QuaternionObject *self)
746 {
747         float tquat[QUAT_SIZE];
748
749         if(BaseMath_ReadCallback(self) == -1)
750                 return NULL;
751
752         negate_v4_v4(tquat, self->quat);
753         return newQuaternionObject(tquat, Py_NEW, Py_TYPE(self));
754 }
755
756
757 //-----------------PROTOCOL DECLARATIONS--------------------------
758 static PySequenceMethods Quaternion_SeqMethods = {
759         (lenfunc) Quaternion_len,                               /* sq_length */
760         (binaryfunc) NULL,                                              /* sq_concat */
761         (ssizeargfunc) NULL,                                    /* sq_repeat */
762         (ssizeargfunc) Quaternion_item,                 /* sq_item */
763         (ssizessizeargfunc) NULL,                               /* sq_slice, deprecated */
764         (ssizeobjargproc) Quaternion_ass_item,  /* sq_ass_item */
765         (ssizessizeobjargproc) NULL,                    /* sq_ass_slice, deprecated */
766         (objobjproc) NULL,                                              /* sq_contains */
767         (binaryfunc) NULL,                                              /* sq_inplace_concat */
768         (ssizeargfunc) NULL,                                    /* sq_inplace_repeat */
769 };
770
771 static PyMappingMethods Quaternion_AsMapping = {
772         (lenfunc)Quaternion_len,
773         (binaryfunc)Quaternion_subscript,
774         (objobjargproc)Quaternion_ass_subscript
775 };
776
777 static PyNumberMethods Quaternion_NumMethods = {
778         (binaryfunc)    Quaternion_add, /*nb_add*/
779         (binaryfunc)    Quaternion_sub, /*nb_subtract*/
780         (binaryfunc)    Quaternion_mul, /*nb_multiply*/
781         NULL,                                                   /*nb_remainder*/
782         NULL,                                                   /*nb_divmod*/
783         NULL,                                                   /*nb_power*/
784         (unaryfunc)     Quaternion_neg, /*nb_negative*/
785         (unaryfunc)     0,      /*tp_positive*/
786         (unaryfunc)     0,      /*tp_absolute*/
787         (inquiry)       0,      /*tp_bool*/
788         (unaryfunc)     0,      /*nb_invert*/
789         NULL,                           /*nb_lshift*/
790         (binaryfunc)0,  /*nb_rshift*/
791         NULL,                           /*nb_and*/
792         NULL,                           /*nb_xor*/
793         NULL,                           /*nb_or*/
794         NULL,                           /*nb_int*/
795         NULL,                           /*nb_reserved*/
796         NULL,                           /*nb_float*/
797         NULL,                           /* nb_inplace_add */
798         NULL,                           /* nb_inplace_subtract */
799         NULL,                           /* nb_inplace_multiply */
800         NULL,                           /* nb_inplace_remainder */
801         NULL,                           /* nb_inplace_power */
802         NULL,                           /* nb_inplace_lshift */
803         NULL,                           /* nb_inplace_rshift */
804         NULL,                           /* nb_inplace_and */
805         NULL,                           /* nb_inplace_xor */
806         NULL,                           /* nb_inplace_or */
807         NULL,                           /* nb_floor_divide */
808         NULL,                           /* nb_true_divide */
809         NULL,                           /* nb_inplace_floor_divide */
810         NULL,                           /* nb_inplace_true_divide */
811         NULL,                           /* nb_index */
812 };
813
814 static PyObject *Quaternion_getAxis(QuaternionObject *self, void *type)
815 {
816         return Quaternion_item(self, GET_INT_FROM_POINTER(type));
817 }
818
819 static int Quaternion_setAxis(QuaternionObject *self, PyObject *value, void *type)
820 {
821         return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), value);
822 }
823
824 static PyObject *Quaternion_getMagnitude(QuaternionObject *self, void *UNUSED(closure))
825 {
826         if(BaseMath_ReadCallback(self) == -1)
827                 return NULL;
828
829         return PyFloat_FromDouble(sqrt(dot_qtqt(self->quat, self->quat)));
830 }
831
832 static PyObject *Quaternion_getAngle(QuaternionObject *self, void *UNUSED(closure))
833 {
834         float tquat[4];
835
836         if(BaseMath_ReadCallback(self) == -1)
837                 return NULL;
838
839         normalize_qt_qt(tquat, self->quat);
840         return PyFloat_FromDouble(2.0f * (saacos(tquat[0])));
841 }
842
843 static int Quaternion_setAngle(QuaternionObject *self, PyObject *value, void *UNUSED(closure))
844 {
845         float tquat[4];
846         float len;
847
848         float axis[3], angle_dummy;
849         double angle;
850
851         if(BaseMath_ReadCallback(self) == -1)
852                 return -1;
853
854         len= normalize_qt_qt(tquat, self->quat);
855         quat_to_axis_angle(axis, &angle_dummy, tquat);
856
857         angle= PyFloat_AsDouble(value);
858
859         if(angle==-1.0 && PyErr_Occurred()) { /* parsed item not a number */
860                 PyErr_SetString(PyExc_TypeError, "quaternion.angle = value: float expected");
861                 return -1;
862         }
863
864         angle= fmod(angle + M_PI*2, M_PI*4) - M_PI*2;
865
866         /* If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations */
867         if(     EXPP_FloatsAreEqual(axis[0], 0.0f, 10) &&
868                 EXPP_FloatsAreEqual(axis[1], 0.0f, 10) &&
869                 EXPP_FloatsAreEqual(axis[2], 0.0f, 10)
870         ) {
871                 axis[0] = 1.0f;
872         }
873
874         axis_angle_to_quat(self->quat, axis, angle);
875         mul_qt_fl(self->quat, len);
876
877         if(BaseMath_WriteCallback(self) == -1)
878                 return -1;
879
880         return 0;
881 }
882
883 static PyObject *Quaternion_getAxisVec(QuaternionObject *self, void *UNUSED(closure))
884 {
885         float tquat[4];
886
887         float axis[3];
888         float angle;
889
890         if(BaseMath_ReadCallback(self) == -1)
891                 return NULL;
892
893         normalize_qt_qt(tquat, self->quat);
894         quat_to_axis_angle(axis, &angle, tquat);
895
896         /* If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations */
897         if(     EXPP_FloatsAreEqual(axis[0], 0.0f, 10) &&
898                 EXPP_FloatsAreEqual(axis[1], 0.0f, 10) &&
899                 EXPP_FloatsAreEqual(axis[2], 0.0f, 10)
900         ) {
901                 axis[0] = 1.0f;
902         }
903
904         return (PyObject *) newVectorObject(axis, 3, Py_NEW, NULL);
905 }
906
907 static int Quaternion_setAxisVec(QuaternionObject *self, PyObject *value, void *UNUSED(closure))
908 {
909         float tquat[4];
910         float len;
911
912         float axis[3];
913         float angle;
914
915         if(BaseMath_ReadCallback(self) == -1)
916                 return -1;
917
918         len= normalize_qt_qt(tquat, self->quat);
919         quat_to_axis_angle(axis, &angle, tquat); /* axis value is unused */
920
921         if (mathutils_array_parse(axis, 3, 3, value, "quat.axis = other") == -1)
922                 return -1;
923
924         axis_angle_to_quat(self->quat, axis, angle);
925         mul_qt_fl(self->quat, len);
926
927         if(BaseMath_WriteCallback(self) == -1)
928                 return -1;
929
930         return 0;
931 }
932
933 //----------------------------------mathutils.Quaternion() --------------
934 static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
935 {
936         PyObject *seq= NULL;
937         double angle = 0.0f;
938         float quat[QUAT_SIZE]= {0.0f, 0.0f, 0.0f, 0.0f};
939
940         if(kwds && PyDict_Size(kwds)) {
941                 PyErr_SetString(PyExc_TypeError, "mathutils.Quaternion(): takes no keyword args");
942                 return NULL;
943         }
944
945         if(!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle))
946                 return NULL;
947
948         switch(PyTuple_GET_SIZE(args)) {
949         case 0:
950                 break;
951         case 1:
952                 if (mathutils_array_parse(quat, QUAT_SIZE, QUAT_SIZE, seq, "mathutils.Quaternion()") == -1)
953                         return NULL;
954                 break;
955         case 2:
956                 if (mathutils_array_parse(quat, 3, 3, seq, "mathutils.Quaternion()") == -1)
957                         return NULL;
958                 angle= fmod(angle + M_PI*2, M_PI*4) - M_PI*2; /* clamp because of precision issues */
959                 axis_angle_to_quat(quat, quat, angle);
960                 break;
961         /* PyArg_ParseTuple assures no more then 2 */
962         }
963         return newQuaternionObject(quat, Py_NEW, type);
964 }
965
966 static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self)
967 {
968         PyObject *ret= Quaternion_copy(self);
969         PyObject *ret_dummy= quat_func(ret);
970         if(ret_dummy) {
971                 Py_DECREF(ret_dummy);
972                 return (PyObject *)ret;
973         }
974         else { /* error */
975                 Py_DECREF(ret);
976                 return NULL;
977         }
978 }
979
980 //-----------------------METHOD DEFINITIONS ----------------------
981 static struct PyMethodDef Quaternion_methods[] = {
982         /* in place only */
983         {"identity", (PyCFunction) Quaternion_identity, METH_NOARGS, Quaternion_identity_doc},
984         {"negate", (PyCFunction) Quaternion_negate, METH_NOARGS, Quaternion_negate_doc},
985
986         /* operate on original or copy */
987         {"conjugate", (PyCFunction) Quaternion_conjugate, METH_NOARGS, Quaternion_conjugate_doc},
988         {"conjugated", (PyCFunction) Quaternion_conjugated, METH_NOARGS, Quaternion_conjugated_doc},
989
990         {"invert", (PyCFunction) Quaternion_invert, METH_NOARGS, Quaternion_invert_doc},
991         {"inverted", (PyCFunction) Quaternion_inverted, METH_NOARGS, Quaternion_inverted_doc},
992
993         {"normalize", (PyCFunction) Quaternion_normalize, METH_NOARGS, Quaternion_normalize_doc},
994         {"normalized", (PyCFunction) Quaternion_normalized, METH_NOARGS, Quaternion_normalized_doc},
995
996         /* return converted representation */
997         {"to_euler", (PyCFunction) Quaternion_to_euler, METH_VARARGS, Quaternion_to_euler_doc},
998         {"to_matrix", (PyCFunction) Quaternion_to_matrix, METH_NOARGS, Quaternion_to_matrix_doc},
999
1000         /* operation between 2 or more types  */
1001         {"cross", (PyCFunction) Quaternion_cross, METH_O, Quaternion_cross_doc},
1002         {"dot", (PyCFunction) Quaternion_dot, METH_O, Quaternion_dot_doc},
1003         {"difference", (PyCFunction) Quaternion_difference, METH_O, Quaternion_difference_doc},
1004         {"slerp", (PyCFunction) Quaternion_slerp, METH_VARARGS, Quaternion_slerp_doc},
1005         {"rotate", (PyCFunction) Quaternion_rotate, METH_O, Quaternion_rotate_doc},
1006
1007         {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
1008         {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc},
1009         {NULL, NULL, 0, NULL}
1010 };
1011
1012 /*****************************************************************************/
1013 /* Python attributes get/set structure:                                      */
1014 /*****************************************************************************/
1015 static PyGetSetDef Quaternion_getseters[] = {
1016         {(char *)"w", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (char *)"Quaternion W value.\n\n:type: float", (void *)0},
1017         {(char *)"x", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (char *)"Quaternion X axis.\n\n:type: float", (void *)1},
1018         {(char *)"y", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (char *)"Quaternion Y axis.\n\n:type: float", (void *)2},
1019         {(char *)"z", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (char *)"Quaternion Z axis.\n\n:type: float", (void *)3},
1020         {(char *)"magnitude", (getter)Quaternion_getMagnitude, (setter)NULL, (char *)"Size of the quaternion (readonly).\n\n:type: float", NULL},
1021         {(char *)"angle", (getter)Quaternion_getAngle, (setter)Quaternion_setAngle, (char *)"angle of the quaternion.\n\n:type: float", NULL},
1022         {(char *)"axis",(getter)Quaternion_getAxisVec, (setter)Quaternion_setAxisVec, (char *)"quaternion axis as a vector.\n\n:type: :class:`Vector`", NULL},
1023         {(char *)"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, (char *)BaseMathObject_Wrapped_doc, NULL},
1024         {(char *)"owner", (getter)BaseMathObject_getOwner, (setter)NULL, (char *)BaseMathObject_Owner_doc, NULL},
1025         {NULL, NULL, NULL, NULL, NULL}  /* Sentinel */
1026 };
1027
1028 //------------------PY_OBECT DEFINITION--------------------------
1029 static char quaternion_doc[] =
1030 "This object gives access to Quaternions in Blender."
1031 ;
1032 PyTypeObject quaternion_Type = {
1033         PyVarObject_HEAD_INIT(NULL, 0)
1034         "mathutils.Quaternion",                                         //tp_name
1035         sizeof(QuaternionObject),                       //tp_basicsize
1036         0,                                                              //tp_itemsize
1037         (destructor)BaseMathObject_dealloc,             //tp_dealloc
1038         NULL,                                                           //tp_print
1039         NULL,                                                           //tp_getattr
1040         NULL,                                                           //tp_setattr
1041         NULL,                                                           //tp_compare
1042         (reprfunc) Quaternion_repr,             //tp_repr
1043         &Quaternion_NumMethods,                 //tp_as_number
1044         &Quaternion_SeqMethods,                 //tp_as_sequence
1045         &Quaternion_AsMapping,                  //tp_as_mapping
1046         NULL,                                                           //tp_hash
1047         NULL,                                                           //tp_call
1048         NULL,                                                           //tp_str
1049         NULL,                                                           //tp_getattro
1050         NULL,                                                           //tp_setattro
1051         NULL,                                                           //tp_as_buffer
1052         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, //tp_flags
1053         quaternion_doc, //tp_doc
1054         (traverseproc)BaseMathObject_traverse,  //tp_traverse
1055         (inquiry)BaseMathObject_clear,  //tp_clear
1056         (richcmpfunc)Quaternion_richcmpr,       //tp_richcompare
1057         0,                                                              //tp_weaklistoffset
1058         NULL,                                                           //tp_iter
1059         NULL,                                                           //tp_iternext
1060         Quaternion_methods,                             //tp_methods
1061         NULL,                                                           //tp_members
1062         Quaternion_getseters,                   //tp_getset
1063         NULL,                                                           //tp_base
1064         NULL,                                                           //tp_dict
1065         NULL,                                                           //tp_descr_get
1066         NULL,                                                           //tp_descr_set
1067         0,                                                              //tp_dictoffset
1068         NULL,                                                           //tp_init
1069         NULL,                                                           //tp_alloc
1070         Quaternion_new,                                 //tp_new
1071         NULL,                                                           //tp_free
1072         NULL,                                                           //tp_is_gc
1073         NULL,                                                           //tp_bases
1074         NULL,                                                           //tp_mro
1075         NULL,                                                           //tp_cache
1076         NULL,                                                           //tp_subclasses
1077         NULL,                                                           //tp_weaklist
1078         NULL,                                                           //tp_del
1079 };
1080 //------------------------newQuaternionObject (internal)-------------
1081 //creates a new quaternion object
1082 /*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
1083  (i.e. it was allocated elsewhere by MEM_mallocN())
1084   pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
1085  (i.e. it must be created here with PyMEM_malloc())*/
1086 PyObject *newQuaternionObject(float *quat, int type, PyTypeObject *base_type)
1087 {
1088         QuaternionObject *self;
1089
1090         self= base_type ?       (QuaternionObject *)base_type->tp_alloc(base_type, 0) :
1091                                                 (QuaternionObject *)PyObject_GC_New(QuaternionObject, &quaternion_Type);
1092
1093         if(self) {
1094                 /* init callbacks as NULL */
1095                 self->cb_user= NULL;
1096                 self->cb_type= self->cb_subtype= 0;
1097
1098                 if(type == Py_WRAP){
1099                         self->quat = quat;
1100                         self->wrapped = Py_WRAP;
1101                 }
1102                 else if (type == Py_NEW){
1103                         self->quat = PyMem_Malloc(QUAT_SIZE * sizeof(float));
1104                         if(!quat) { //new empty
1105                                 unit_qt(self->quat);
1106                         }
1107                         else {
1108                                 QUATCOPY(self->quat, quat);
1109                         }
1110                         self->wrapped = Py_NEW;
1111                 }
1112                 else {
1113                         PyErr_SetString(PyExc_RuntimeError, "Quaternion(): invalid type");
1114                         return NULL;
1115                 }
1116         }
1117         return (PyObject *) self;
1118 }
1119
1120 PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
1121 {
1122         QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW, NULL);
1123         if(self) {
1124                 Py_INCREF(cb_user);
1125                 self->cb_user=                  cb_user;
1126                 self->cb_type=                  (unsigned char)cb_type;
1127                 self->cb_subtype=               (unsigned char)cb_subtype;
1128                 PyObject_GC_Track(self);
1129         }
1130
1131         return (PyObject *)self;
1132 }
1133