Made Mathutils use radians rather then degrees. defining USE_MATHUTILS_DEG for testin...
[blender.git] / source / blender / python / generic / euler.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Joseph Gilbert
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "Mathutils.h"
30
31 #include "BLI_arithb.h"
32 #include "BKE_utildefines.h"
33 #include "BLI_blenlib.h"
34
35
36 //-------------------------DOC STRINGS ---------------------------
37 static char Euler_Zero_doc[] = "() - set all values in the euler to 0";
38 static char Euler_Unique_doc[] ="() - sets the euler rotation a unique shortest arc rotation - tests for gimbal lock";
39 static char Euler_ToMatrix_doc[] =      "() - returns a rotation matrix representing the euler rotation";
40 static char Euler_ToQuat_doc[] = "() - returns a quaternion representing the euler rotation";
41 static char Euler_Rotate_doc[] = "() - rotate a euler by certain amount around an axis of rotation";
42 static char Euler_copy_doc[] = "() - returns a copy of the euler.";
43 static char Euler_MakeCompatible_doc[] = "(euler) - Make this user compatible with another (no axis flipping).";
44
45 static PyObject *Euler_Zero( EulerObject * self );
46 static PyObject *Euler_Unique( EulerObject * self );
47 static PyObject *Euler_ToMatrix( EulerObject * self );
48 static PyObject *Euler_ToQuat( EulerObject * self );
49 static PyObject *Euler_Rotate( EulerObject * self, PyObject *args );
50 static PyObject *Euler_MakeCompatible( EulerObject * self, EulerObject *value );
51 static PyObject *Euler_copy( EulerObject * self, PyObject *args );
52
53 //-----------------------METHOD DEFINITIONS ----------------------
54 static struct PyMethodDef Euler_methods[] = {
55         {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc},
56         {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, Euler_Unique_doc},
57         {"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc},
58         {"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc},
59         {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, Euler_Rotate_doc},
60         {"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc},
61         {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
62         {"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
63         {NULL, NULL, 0, NULL}
64 };
65
66 //----------------------------------Mathutils.Euler() -------------------
67 //makes a new euler for you to play with
68 static PyObject *Euler_new(PyObject * self, PyObject * args)
69 {
70
71         PyObject *listObject = NULL;
72         int size, i;
73         float eul[3];
74         PyObject *e;
75
76         size = PyTuple_GET_SIZE(args);
77         if (size == 1) {
78                 listObject = PyTuple_GET_ITEM(args, 0);
79                 if (PySequence_Check(listObject)) {
80                         size = PySequence_Length(listObject);
81                 } else { // Single argument was not a sequence
82                         PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
83                         return NULL;
84                 }
85         } else if (size == 0) {
86                 //returns a new empty 3d euler
87                 return newEulerObject(NULL, Py_NEW); 
88         } else {
89                 listObject = args;
90         }
91
92         if (size != 3) { // Invalid euler size
93                 PyErr_SetString(PyExc_AttributeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
94                 return NULL;
95         }
96
97         for (i=0; i<size; i++) {
98                 e = PySequence_GetItem(listObject, i);
99                 if (e == NULL) { // Failed to read sequence
100                         Py_DECREF(listObject);
101                         PyErr_SetString(PyExc_RuntimeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
102                         return NULL;
103                 }
104
105                 eul[i]= (float)PyFloat_AsDouble(e);
106                 Py_DECREF(e);
107                 
108                 if(eul[i]==-1 && PyErr_Occurred()) { // parsed item is not a number
109                         PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
110                         return NULL;
111                 }
112         }
113         return newEulerObject(eul, Py_NEW);
114 }
115
116 //-----------------------------METHODS----------------------------
117 //----------------------------Euler.toQuat()----------------------
118 //return a quaternion representation of the euler
119 static PyObject *Euler_ToQuat(EulerObject * self)
120 {
121         float eul[3], quat[4];
122         int x;
123
124         if(!BaseMath_ReadCallback(self))
125                 return NULL;
126
127 #ifdef USE_MATHUTILS_DEG
128         for(x = 0; x < 3; x++) {
129                 eul[x] = self->eul[x] * ((float)Py_PI / 180);
130         }
131         EulToQuat(eul, quat);
132 #else
133         EulToQuat(self->eul, quat);
134 #endif
135
136         return newQuaternionObject(quat, Py_NEW);
137 }
138 //----------------------------Euler.toMatrix()---------------------
139 //return a matrix representation of the euler
140 static PyObject *Euler_ToMatrix(EulerObject * self)
141 {
142         float eul[3];
143         float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
144         int x;
145
146         if(!BaseMath_ReadCallback(self))
147                 return NULL;
148
149 #ifdef USE_MATHUTILS_DEG
150         for(x = 0; x < 3; x++) {
151                 eul[x] = self->eul[x] * ((float)Py_PI / 180);
152         }
153         EulToMat3(eul, (float (*)[3]) mat);
154 #else
155         EulToMat3(self->eul, (float (*)[3]) mat);
156 #endif
157         return newMatrixObject(mat, 3, 3 , Py_NEW);
158 }
159 //----------------------------Euler.unique()-----------------------
160 //sets the x,y,z values to a unique euler rotation
161 static PyObject *Euler_Unique(EulerObject * self)
162 {
163         double heading, pitch, bank;
164         double pi2 =  Py_PI * 2.0f;
165         double piO2 = Py_PI / 2.0f;
166         double Opi2 = 1.0f / pi2;
167
168         if(!BaseMath_ReadCallback(self))
169                 return NULL;
170
171 #ifdef USE_MATHUTILS_DEG
172         //radians
173         heading = self->eul[0] * (float)Py_PI / 180;
174         pitch = self->eul[1] * (float)Py_PI / 180;
175         bank = self->eul[2] * (float)Py_PI / 180;
176 #endif
177
178         //wrap heading in +180 / -180
179         pitch += Py_PI;
180         pitch -= floor(pitch * Opi2) * pi2;
181         pitch -= Py_PI;
182
183
184         if(pitch < -piO2) {
185                 pitch = -Py_PI - pitch;
186                 heading += Py_PI;
187                 bank += Py_PI;
188         } else if(pitch > piO2) {
189                 pitch = Py_PI - pitch;
190                 heading += Py_PI;
191                 bank += Py_PI;
192         }
193         //gimbal lock test
194         if(fabs(pitch) > piO2 - 1e-4) {
195                 heading += bank;
196                 bank = 0.0f;
197         } else {
198                 bank += Py_PI;
199                 bank -= (floor(bank * Opi2)) * pi2;
200                 bank -= Py_PI;
201         }
202
203         heading += Py_PI;
204         heading -= (floor(heading * Opi2)) * pi2;
205         heading -= Py_PI;
206
207 #ifdef USE_MATHUTILS_DEG
208         //back to degrees
209         self->eul[0] = (float)(heading * 180 / (float)Py_PI);
210         self->eul[1] = (float)(pitch * 180 / (float)Py_PI);
211         self->eul[2] = (float)(bank * 180 / (float)Py_PI);
212 #endif
213
214         BaseMath_WriteCallback(self);
215         Py_INCREF(self);
216         return (PyObject *)self;
217 }
218 //----------------------------Euler.zero()-------------------------
219 //sets the euler to 0,0,0
220 static PyObject *Euler_Zero(EulerObject * self)
221 {
222         self->eul[0] = 0.0;
223         self->eul[1] = 0.0;
224         self->eul[2] = 0.0;
225
226         BaseMath_WriteCallback(self);
227         Py_INCREF(self);
228         return (PyObject *)self;
229 }
230 //----------------------------Euler.rotate()-----------------------
231 //rotates a euler a certain amount and returns the result
232 //should return a unique euler rotation (i.e. no 720 degree pitches :)
233 static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
234 {
235         float angle = 0.0f;
236         char *axis;
237         int x;
238
239         if(!PyArg_ParseTuple(args, "fs", &angle, &axis)){
240                 PyErr_SetString(PyExc_TypeError, "euler.rotate():expected angle (float) and axis (x,y,z)");
241                 return NULL;
242         }
243         if(!STREQ3(axis,"x","y","z")){
244                 PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected axis to be 'x', 'y' or 'z'");
245                 return NULL;
246         }
247
248         if(!BaseMath_ReadCallback(self))
249                 return NULL;
250
251 #ifdef USE_MATHUTILS_DEG
252         //covert to radians
253         angle *= ((float)Py_PI / 180);
254         for(x = 0; x < 3; x++) {
255                 self->eul[x] *= ((float)Py_PI / 180);
256         }
257 #endif
258         euler_rot(self->eul, angle, *axis);
259
260 #ifdef USE_MATHUTILS_DEG
261         //convert back from radians
262         for(x = 0; x < 3; x++) {
263                 self->eul[x] *= (180 / (float)Py_PI);
264         }
265 #endif
266
267         BaseMath_WriteCallback(self);
268         Py_INCREF(self);
269         return (PyObject *)self;
270 }
271
272 static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
273 {
274         float eul_from_rad[3];
275         int x;
276         
277         if(!EulerObject_Check(value)) {
278                 PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
279                 return NULL;
280         }
281         
282         if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
283                 return NULL;
284
285 #ifdef USE_MATHUTILS_DEG
286         //covert to radians
287         for(x = 0; x < 3; x++) {
288                 self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
289                 eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
290         }
291         compatible_eul(self->eul, eul_from_rad);
292 #else
293         compatible_eul(self->eul, value->eul);
294 #endif
295
296 #ifdef USE_MATHUTILS_DEG
297         //convert back from radians
298         for(x = 0; x < 3; x++) {
299                 self->eul[x] *= (180 / (float)Py_PI);
300         }
301 #endif
302         BaseMath_WriteCallback(self);
303         Py_INCREF(self);
304         return (PyObject *)self;
305 }
306
307 //----------------------------Euler.rotate()-----------------------
308 // return a copy of the euler
309 static PyObject *Euler_copy(EulerObject * self, PyObject *args)
310 {
311         if(!BaseMath_ReadCallback(self))
312                 return NULL;
313
314         return newEulerObject(self->eul, Py_NEW);
315 }
316
317 //----------------------------print object (internal)--------------
318 //print the object to screen
319 static PyObject *Euler_repr(EulerObject * self)
320 {
321         char str[64];
322
323         if(!BaseMath_ReadCallback(self))
324                 return NULL;
325
326         sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]);
327         return PyUnicode_FromString(str);
328 }
329 //------------------------tp_richcmpr
330 //returns -1 execption, 0 false, 1 true
331 static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
332 {
333         EulerObject *eulA = NULL, *eulB = NULL;
334         int result = 0;
335
336         if(EulerObject_Check(objectA)) {
337                 eulA = (EulerObject*)objectA;
338                 if(!BaseMath_ReadCallback(eulA))
339                         return NULL;
340         }
341         if(EulerObject_Check(objectB)) {
342                 eulB = (EulerObject*)objectB;
343                 if(!BaseMath_ReadCallback(eulB))
344                         return NULL;
345         }
346
347         if (!eulA || !eulB){
348                 if (comparison_type == Py_NE){
349                         Py_RETURN_TRUE;
350                 }else{
351                         Py_RETURN_FALSE;
352                 }
353         }
354         eulA = (EulerObject*)objectA;
355         eulB = (EulerObject*)objectB;
356
357         switch (comparison_type){
358                 case Py_EQ:
359                         result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
360                         break;
361                 case Py_NE:
362                         result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
363                         if (result == 0){
364                                 result = 1;
365                         }else{
366                                 result = 0;
367                         }
368                         break;
369                 default:
370                         printf("The result of the comparison could not be evaluated");
371                         break;
372         }
373         if (result == 1){
374                 Py_RETURN_TRUE;
375         }else{
376                 Py_RETURN_FALSE;
377         }
378 }
379 //------------------------tp_doc
380 static char EulerObject_doc[] = "This is a wrapper for euler objects.";
381 //---------------------SEQUENCE PROTOCOLS------------------------
382 //----------------------------len(object)------------------------
383 //sequence length
384 static int Euler_len(EulerObject * self)
385 {
386         return 3;
387 }
388 //----------------------------object[]---------------------------
389 //sequence accessor (get)
390 static PyObject *Euler_item(EulerObject * self, int i)
391 {
392         if(i<0) i= 3-i;
393         
394         if(i < 0 || i >= 3) {
395                 PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
396                 return NULL;
397         }
398
399         if(!BaseMath_ReadIndexCallback(self, i))
400                 return NULL;
401
402         return PyFloat_FromDouble(self->eul[i]);
403
404 }
405 //----------------------------object[]-------------------------
406 //sequence accessor (set)
407 static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
408 {
409         float f = PyFloat_AsDouble(value);
410
411         if(f == -1 && PyErr_Occurred()) { // parsed item not a number
412                 PyErr_SetString(PyExc_TypeError, "euler[attribute] = x: argument not a number");
413                 return -1;
414         }
415
416         if(i<0) i= 3-i;
417         
418         if(i < 0 || i >= 3){
419                 PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n");
420                 return -1;
421         }
422         
423         self->eul[i] = f;
424
425         if(!BaseMath_WriteIndexCallback(self, i))
426                 return -1;
427
428         return 0;
429 }
430 //----------------------------object[z:y]------------------------
431 //sequence slice (get)
432 static PyObject *Euler_slice(EulerObject * self, int begin, int end)
433 {
434         PyObject *list = NULL;
435         int count;
436
437         if(!BaseMath_ReadCallback(self))
438                 return NULL;
439
440         CLAMP(begin, 0, 3);
441         if (end<0) end= 4+end;
442         CLAMP(end, 0, 3);
443         begin = MIN2(begin,end);
444
445         list = PyList_New(end - begin);
446         for(count = begin; count < end; count++) {
447                 PyList_SetItem(list, count - begin,
448                                 PyFloat_FromDouble(self->eul[count]));
449         }
450
451         return list;
452 }
453 //----------------------------object[z:y]------------------------
454 //sequence slice (set)
455 static int Euler_ass_slice(EulerObject * self, int begin, int end,
456                              PyObject * seq)
457 {
458         int i, y, size = 0;
459         float eul[3];
460         PyObject *e;
461
462         if(!BaseMath_ReadCallback(self))
463                 return NULL;
464
465         CLAMP(begin, 0, 3);
466         if (end<0) end= 4+end;
467         CLAMP(end, 0, 3);
468         begin = MIN2(begin,end);
469
470         size = PySequence_Length(seq);
471         if(size != (end - begin)){
472                 PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: size mismatch in slice assignment");
473                 return -1;
474         }
475
476         for (i = 0; i < size; i++) {
477                 e = PySequence_GetItem(seq, i);
478                 if (e == NULL) { // Failed to read sequence
479                         PyErr_SetString(PyExc_RuntimeError, "euler[begin:end] = []: unable to read sequence");
480                         return -1;
481                 }
482
483                 eul[i] = (float)PyFloat_AsDouble(e);
484                 Py_DECREF(e);
485
486                 if(eul[i]==-1 && PyErr_Occurred()) { // parsed item not a number
487                         PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number");
488                         return -1;
489                 }
490         }
491         //parsed well - now set in vector
492         for(y = 0; y < 3; y++){
493                 self->eul[begin + y] = eul[y];
494         }
495
496         BaseMath_WriteCallback(self);
497         return 0;
498 }
499 //-----------------PROTCOL DECLARATIONS--------------------------
500 static PySequenceMethods Euler_SeqMethods = {
501         (inquiry) Euler_len,                                            /* sq_length */
502         (binaryfunc) 0,                                                         /* sq_concat */
503         (ssizeargfunc) 0,                                                               /* sq_repeat */
504         (ssizeargfunc) Euler_item,                                      /* sq_item */
505         (ssizessizeargfunc) Euler_slice,                                /* sq_slice */
506         (ssizeobjargproc) Euler_ass_item,                               /* sq_ass_item */
507         (ssizessizeobjargproc) Euler_ass_slice,                 /* sq_ass_slice */
508 };
509
510
511 /*
512  * vector axis, vector.x/y/z/w
513  */
514         
515 static PyObject *Euler_getAxis( EulerObject * self, void *type )
516 {
517         return Euler_item(self, GET_INT_FROM_POINTER(type));
518 }
519
520 static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
521 {
522         return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
523 }
524
525 /*****************************************************************************/
526 /* Python attributes get/set structure:                                      */
527 /*****************************************************************************/
528 static PyGetSetDef Euler_getseters[] = {
529         {"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis", (void *)0},
530         {"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis", (void *)1},
531         {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2},
532
533         {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL},
534         {"__owner__", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL},
535         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
536 };
537
538 //------------------PY_OBECT DEFINITION--------------------------
539 PyTypeObject euler_Type = {
540 #if (PY_VERSION_HEX >= 0x02060000)
541         PyVarObject_HEAD_INIT(NULL, 0)
542 #else
543         /* python 2.5 and below */
544         PyObject_HEAD_INIT( NULL )  /* required py macro */
545         0,                          /* ob_size */
546 #endif
547         "euler",                                                //tp_name
548         sizeof(EulerObject),                    //tp_basicsize
549         0,                                                              //tp_itemsize
550         (destructor)BaseMathObject_dealloc,             //tp_dealloc
551         0,                                                              //tp_print
552         0,                                                              //tp_getattr
553         0,                                                              //tp_setattr
554         0,                                                              //tp_compare
555         (reprfunc) Euler_repr,                  //tp_repr
556         0,                              //tp_as_number
557         &Euler_SeqMethods,                              //tp_as_sequence
558         0,                                                              //tp_as_mapping
559         0,                                                              //tp_hash
560         0,                                                              //tp_call
561         0,                                                              //tp_str
562         0,                                                              //tp_getattro
563         0,                                                              //tp_setattro
564         0,                                                              //tp_as_buffer
565         Py_TPFLAGS_DEFAULT,                             //tp_flags
566         EulerObject_doc,                                //tp_doc
567         0,                                                              //tp_traverse
568         0,                                                              //tp_clear
569         (richcmpfunc)Euler_richcmpr,    //tp_richcompare
570         0,                                                              //tp_weaklistoffset
571         0,                                                              //tp_iter
572         0,                                                              //tp_iternext
573         Euler_methods,                                  //tp_methods
574         0,                                                              //tp_members
575         Euler_getseters,                                //tp_getset
576         0,                                                              //tp_base
577         0,                                                              //tp_dict
578         0,                                                              //tp_descr_get
579         0,                                                              //tp_descr_set
580         0,                                                              //tp_dictoffset
581         0,                                                              //tp_init
582         0,                                                              //tp_alloc
583         Euler_new,                                              //tp_new
584         0,                                                              //tp_free
585         0,                                                              //tp_is_gc
586         0,                                                              //tp_bases
587         0,                                                              //tp_mro
588         0,                                                              //tp_cache
589         0,                                                              //tp_subclasses
590         0,                                                              //tp_weaklist
591         0                                                               //tp_del
592 };
593 //------------------------newEulerObject (internal)-------------
594 //creates a new euler object
595 /*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
596  (i.e. it was allocated elsewhere by MEM_mallocN())
597   pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
598  (i.e. it must be created here with PyMEM_malloc())*/
599 PyObject *newEulerObject(float *eul, int type)
600 {
601         EulerObject *self;
602         int x;
603
604         self = PyObject_NEW(EulerObject, &euler_Type);
605
606         /* init callbacks as NULL */
607         self->cb_user= NULL;
608         self->cb_type= self->cb_subtype= 0;
609
610         if(type == Py_WRAP){
611                 self->eul = eul;
612                 self->wrapped = Py_WRAP;
613         }else if (type == Py_NEW){
614                 self->eul = PyMem_Malloc(3 * sizeof(float));
615                 if(!eul) { //new empty
616                         for(x = 0; x < 3; x++) {
617                                 self->eul[x] = 0.0f;
618                         }
619                 }else{
620                         VECCOPY(self->eul, eul);
621                 }
622                 self->wrapped = Py_NEW;
623         }else{ //bad type
624                 return NULL;
625         }
626         return (PyObject *)self;
627 }
628
629 PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
630 {
631         EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW);
632         if(self) {
633                 Py_INCREF(cb_user);
634                 self->cb_user=                  cb_user;
635                 self->cb_type=                  (unsigned char)cb_type;
636                 self->cb_subtype=               (unsigned char)cb_subtype;
637         }
638
639         return self;
640 }