svn merge -r 21041:21301 https://svn.blender.org/svnroot/bf-blender/branches/blender2...
[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 eul[3];
138         float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
139         int x;
140
141         if(!BaseMath_ReadCallback(self))
142                 return NULL;
143
144 #ifdef USE_MATHUTILS_DEG
145         for(x = 0; x < 3; x++) {
146                 eul[x] = self->eul[x] * ((float)Py_PI / 180);
147         }
148         EulToMat3(eul, (float (*)[3]) mat);
149 #else
150         EulToMat3(self->eul, (float (*)[3]) mat);
151 #endif
152         return newMatrixObject(mat, 3, 3 , Py_NEW, NULL);
153 }
154 //----------------------------Euler.unique()-----------------------
155 //sets the x,y,z values to a unique euler rotation
156 static PyObject *Euler_Unique(EulerObject * self)
157 {
158 #define PI_2            (Py_PI * 2.0)
159 #define PI_HALF         (Py_PI / 2.0)
160 #define PI_INV          (1.0 / Py_PI)
161
162         double heading, pitch, bank;
163
164         if(!BaseMath_ReadCallback(self))
165                 return NULL;
166
167 #ifdef USE_MATHUTILS_DEG
168         //radians
169         heading = self->eul[0] * (float)Py_PI / 180;
170         pitch = self->eul[1] * (float)Py_PI / 180;
171         bank = self->eul[2] * (float)Py_PI / 180;
172 #else
173         heading = self->eul[0];
174         pitch = self->eul[1];
175         bank = self->eul[2];
176 #endif
177
178         //wrap heading in +180 / -180
179         pitch += Py_PI;
180         pitch -= floor(pitch * PI_INV) * PI_2;
181         pitch -= Py_PI;
182
183
184         if(pitch < -PI_HALF) {
185                 pitch = -Py_PI - pitch;
186                 heading += Py_PI;
187                 bank += Py_PI;
188         } else if(pitch > PI_HALF) {
189                 pitch = Py_PI - pitch;
190                 heading += Py_PI;
191                 bank += Py_PI;
192         }
193         //gimbal lock test
194         if(fabs(pitch) > PI_HALF - 1e-4) {
195                 heading += bank;
196                 bank = 0.0f;
197         } else {
198                 bank += Py_PI;
199                 bank -= (floor(bank * PI_INV)) * PI_2;
200                 bank -= Py_PI;
201         }
202
203         heading += Py_PI;
204         heading -= (floor(heading * PI_INV)) * PI_2;
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 #ifdef USE_MATHUTILS_DEG
275         float eul_from_rad[3];
276         int x;
277 #endif
278         
279         if(!EulerObject_Check(value)) {
280                 PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
281                 return NULL;
282         }
283         
284         if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
285                 return NULL;
286
287 #ifdef USE_MATHUTILS_DEG
288         //covert to radians
289         for(x = 0; x < 3; x++) {
290                 self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
291                 eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
292         }
293         compatible_eul(self->eul, eul_from_rad);
294 #else
295         compatible_eul(self->eul, value->eul);
296 #endif
297
298 #ifdef USE_MATHUTILS_DEG
299         //convert back from radians
300         for(x = 0; x < 3; x++) {
301                 self->eul[x] *= (180 / (float)Py_PI);
302         }
303 #endif
304         BaseMath_WriteCallback(self);
305         Py_INCREF(self);
306         return (PyObject *)self;
307 }
308
309 //----------------------------Euler.rotate()-----------------------
310 // return a copy of the euler
311 static PyObject *Euler_copy(EulerObject * self, PyObject *args)
312 {
313         if(!BaseMath_ReadCallback(self))
314                 return NULL;
315
316         return newEulerObject(self->eul, Py_NEW, Py_TYPE(self));
317 }
318
319 //----------------------------print object (internal)--------------
320 //print the object to screen
321 static PyObject *Euler_repr(EulerObject * self)
322 {
323         char str[64];
324
325         if(!BaseMath_ReadCallback(self))
326                 return NULL;
327
328         sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]);
329         return PyUnicode_FromString(str);
330 }
331 //------------------------tp_richcmpr
332 //returns -1 execption, 0 false, 1 true
333 static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
334 {
335         EulerObject *eulA = NULL, *eulB = NULL;
336         int result = 0;
337
338         if(EulerObject_Check(objectA)) {
339                 eulA = (EulerObject*)objectA;
340                 if(!BaseMath_ReadCallback(eulA))
341                         return NULL;
342         }
343         if(EulerObject_Check(objectB)) {
344                 eulB = (EulerObject*)objectB;
345                 if(!BaseMath_ReadCallback(eulB))
346                         return NULL;
347         }
348
349         if (!eulA || !eulB){
350                 if (comparison_type == Py_NE){
351                         Py_RETURN_TRUE;
352                 }else{
353                         Py_RETURN_FALSE;
354                 }
355         }
356         eulA = (EulerObject*)objectA;
357         eulB = (EulerObject*)objectB;
358
359         switch (comparison_type){
360                 case Py_EQ:
361                         result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
362                         break;
363                 case Py_NE:
364                         result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
365                         if (result == 0){
366                                 result = 1;
367                         }else{
368                                 result = 0;
369                         }
370                         break;
371                 default:
372                         printf("The result of the comparison could not be evaluated");
373                         break;
374         }
375         if (result == 1){
376                 Py_RETURN_TRUE;
377         }else{
378                 Py_RETURN_FALSE;
379         }
380 }
381
382 //---------------------SEQUENCE PROTOCOLS------------------------
383 //----------------------------len(object)------------------------
384 //sequence length
385 static int Euler_len(EulerObject * self)
386 {
387         return 3;
388 }
389 //----------------------------object[]---------------------------
390 //sequence accessor (get)
391 static PyObject *Euler_item(EulerObject * self, int i)
392 {
393         if(i<0) i= 3-i;
394         
395         if(i < 0 || i >= 3) {
396                 PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
397                 return NULL;
398         }
399
400         if(!BaseMath_ReadIndexCallback(self, i))
401                 return NULL;
402
403         return PyFloat_FromDouble(self->eul[i]);
404
405 }
406 //----------------------------object[]-------------------------
407 //sequence accessor (set)
408 static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
409 {
410         float f = PyFloat_AsDouble(value);
411
412         if(f == -1 && PyErr_Occurred()) { // parsed item not a number
413                 PyErr_SetString(PyExc_TypeError, "euler[attribute] = x: argument not a number");
414                 return -1;
415         }
416
417         if(i<0) i= 3-i;
418         
419         if(i < 0 || i >= 3){
420                 PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n");
421                 return -1;
422         }
423         
424         self->eul[i] = f;
425
426         if(!BaseMath_WriteIndexCallback(self, i))
427                 return -1;
428
429         return 0;
430 }
431 //----------------------------object[z:y]------------------------
432 //sequence slice (get)
433 static PyObject *Euler_slice(EulerObject * self, int begin, int end)
434 {
435         PyObject *list = NULL;
436         int count;
437
438         if(!BaseMath_ReadCallback(self))
439                 return NULL;
440
441         CLAMP(begin, 0, 3);
442         if (end<0) end= 4+end;
443         CLAMP(end, 0, 3);
444         begin = MIN2(begin,end);
445
446         list = PyList_New(end - begin);
447         for(count = begin; count < end; count++) {
448                 PyList_SetItem(list, count - begin,
449                                 PyFloat_FromDouble(self->eul[count]));
450         }
451
452         return list;
453 }
454 //----------------------------object[z:y]------------------------
455 //sequence slice (set)
456 static int Euler_ass_slice(EulerObject * self, int begin, int end,
457                              PyObject * seq)
458 {
459         int i, y, size = 0;
460         float eul[3];
461         PyObject *e;
462
463         if(!BaseMath_ReadCallback(self))
464                 return -1;
465
466         CLAMP(begin, 0, 3);
467         if (end<0) end= 4+end;
468         CLAMP(end, 0, 3);
469         begin = MIN2(begin,end);
470
471         size = PySequence_Length(seq);
472         if(size != (end - begin)){
473                 PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: size mismatch in slice assignment");
474                 return -1;
475         }
476
477         for (i = 0; i < size; i++) {
478                 e = PySequence_GetItem(seq, i);
479                 if (e == NULL) { // Failed to read sequence
480                         PyErr_SetString(PyExc_RuntimeError, "euler[begin:end] = []: unable to read sequence");
481                         return -1;
482                 }
483
484                 eul[i] = (float)PyFloat_AsDouble(e);
485                 Py_DECREF(e);
486
487                 if(eul[i]==-1 && PyErr_Occurred()) { // parsed item not a number
488                         PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number");
489                         return -1;
490                 }
491         }
492         //parsed well - now set in vector
493         for(y = 0; y < 3; y++){
494                 self->eul[begin + y] = eul[y];
495         }
496
497         BaseMath_WriteCallback(self);
498         return 0;
499 }
500 //-----------------PROTCOL DECLARATIONS--------------------------
501 static PySequenceMethods Euler_SeqMethods = {
502         (inquiry) Euler_len,                                            /* sq_length */
503         (binaryfunc) 0,                                                         /* sq_concat */
504         (ssizeargfunc) 0,                                                               /* sq_repeat */
505         (ssizeargfunc) Euler_item,                                      /* sq_item */
506         (ssizessizeargfunc) Euler_slice,                                /* sq_slice */
507         (ssizeobjargproc) Euler_ass_item,                               /* sq_ass_item */
508         (ssizessizeobjargproc) Euler_ass_slice,                 /* sq_ass_slice */
509 };
510
511
512 /*
513  * vector axis, vector.x/y/z/w
514  */
515         
516 static PyObject *Euler_getAxis( EulerObject * self, void *type )
517 {
518         return Euler_item(self, GET_INT_FROM_POINTER(type));
519 }
520
521 static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
522 {
523         return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
524 }
525
526 /*****************************************************************************/
527 /* Python attributes get/set structure:                                      */
528 /*****************************************************************************/
529 static PyGetSetDef Euler_getseters[] = {
530         {"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis", (void *)0},
531         {"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis", (void *)1},
532         {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2},
533
534         {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL},
535         {"__owner__", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL},
536         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
537 };
538
539 //------------------PY_OBECT DEFINITION--------------------------
540 PyTypeObject euler_Type = {
541 #if (PY_VERSION_HEX >= 0x02060000)
542         PyVarObject_HEAD_INIT(NULL, 0)
543 #else
544         /* python 2.5 and below */
545         PyObject_HEAD_INIT( NULL )  /* required py macro */
546         0,                          /* ob_size */
547 #endif
548         "euler",                                                //tp_name
549         sizeof(EulerObject),                    //tp_basicsize
550         0,                                                              //tp_itemsize
551         (destructor)BaseMathObject_dealloc,             //tp_dealloc
552         0,                                                              //tp_print
553         0,                                                              //tp_getattr
554         0,                                                              //tp_setattr
555         0,                                                              //tp_compare
556         (reprfunc) Euler_repr,                  //tp_repr
557         0,                              //tp_as_number
558         &Euler_SeqMethods,                              //tp_as_sequence
559         0,                                                              //tp_as_mapping
560         0,                                                              //tp_hash
561         0,                                                              //tp_call
562         0,                                                              //tp_str
563         0,                                                              //tp_getattro
564         0,                                                              //tp_setattro
565         0,                                                              //tp_as_buffer
566         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
567         0,                                                              //tp_doc
568         0,                                                              //tp_traverse
569         0,                                                              //tp_clear
570         (richcmpfunc)Euler_richcmpr,    //tp_richcompare
571         0,                                                              //tp_weaklistoffset
572         0,                                                              //tp_iter
573         0,                                                              //tp_iternext
574         Euler_methods,                                  //tp_methods
575         0,                                                              //tp_members
576         Euler_getseters,                                //tp_getset
577         0,                                                              //tp_base
578         0,                                                              //tp_dict
579         0,                                                              //tp_descr_get
580         0,                                                              //tp_descr_set
581         0,                                                              //tp_dictoffset
582         0,                                                              //tp_init
583         0,                                                              //tp_alloc
584         Euler_new,                                              //tp_new
585         0,                                                              //tp_free
586         0,                                                              //tp_is_gc
587         0,                                                              //tp_bases
588         0,                                                              //tp_mro
589         0,                                                              //tp_cache
590         0,                                                              //tp_subclasses
591         0,                                                              //tp_weaklist
592         0                                                               //tp_del
593 };
594 //------------------------newEulerObject (internal)-------------
595 //creates a new euler object
596 /*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
597  (i.e. it was allocated elsewhere by MEM_mallocN())
598   pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
599  (i.e. it must be created here with PyMEM_malloc())*/
600 PyObject *newEulerObject(float *eul, int type, PyTypeObject *base_type)
601 {
602         EulerObject *self;
603         int x;
604
605         if(base_type)   self = base_type->tp_alloc(base_type, 0);
606         else                    self = PyObject_NEW(EulerObject, &euler_Type);
607
608         /* init callbacks as NULL */
609         self->cb_user= NULL;
610         self->cb_type= self->cb_subtype= 0;
611
612         if(type == Py_WRAP){
613                 self->eul = eul;
614                 self->wrapped = Py_WRAP;
615         }else if (type == Py_NEW){
616                 self->eul = PyMem_Malloc(3 * sizeof(float));
617                 if(!eul) { //new empty
618                         for(x = 0; x < 3; x++) {
619                                 self->eul[x] = 0.0f;
620                         }
621                 }else{
622                         VECCOPY(self->eul, eul);
623                 }
624                 self->wrapped = Py_NEW;
625         }else{ //bad type
626                 return NULL;
627         }
628         return (PyObject *)self;
629 }
630
631 PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
632 {
633         EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW, NULL);
634         if(self) {
635                 Py_INCREF(cb_user);
636                 self->cb_user=                  cb_user;
637                 self->cb_type=                  (unsigned char)cb_type;
638                 self->cb_subtype=               (unsigned char)cb_subtype;
639         }
640
641         return (PyObject *)self;
642 }