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