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