9ec5e90a49374b8a46648d5a4f673a1253d6acf1
[blender-staging.git] / source / blender / python / mathutils / mathutils.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  * Contributor(s): Joseph Gilbert, Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/python/mathutils/mathutils.c
24  *  \ingroup pymathutils
25  */
26
27 #include <Python.h>
28
29 #include "mathutils.h"
30
31 #include "BLI_math.h"
32 #include "BLI_utildefines.h"
33
34 #include "../generic/python_utildefines.h"
35
36 #ifndef MATH_STANDALONE
37 #  include "BLI_dynstr.h"
38 #endif
39
40 PyDoc_STRVAR(M_Mathutils_doc,
41 "This module provides access to the math classes:\n"
42 "\n"
43 "- :class:`Color`,\n"
44 "- :class:`Euler`,\n"
45 "- :class:`Matrix`,\n"
46 "- :class:`Quaternion`,\n"
47 "- :class:`Vector`,\n"
48 "\n"
49 ".. note::\n"
50 "\n"
51 "   Classes, methods and attributes that accept vectors also accept other numeric sequences,\n"
52 "   such as tuples, lists."
53 );
54 static int mathutils_array_parse_fast(float *array,
55                                       int size,
56                                       PyObject *value_fast,
57                                       const char *error_prefix)
58 {
59         PyObject *item;
60
61         int i;
62
63         i = size;
64         do {
65                 i--;
66                 if (((array[i] = PyFloat_AsDouble((item = PySequence_Fast_GET_ITEM(value_fast, i)))) == -1.0f) &&
67                     PyErr_Occurred())
68                 {
69                         PyErr_Format(PyExc_TypeError,
70                                      "%.200s: sequence index %d expected a number, "
71                                      "found '%.200s' type, ",
72                                      error_prefix, i, Py_TYPE(item)->tp_name);
73                         Py_DECREF(value_fast);
74                         return -1;
75                 }
76         } while (i);
77
78         Py_XDECREF(value_fast);
79         return size;
80 }
81
82 /**
83  * helper function that returns a Python ``__hash__``.
84  *
85  * \note consistent with the equivalent tuple of floats (CPython's 'tuplehash')
86  */
87 Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
88 {
89         int i;
90         Py_uhash_t x;  /* Unsigned for defined overflow behavior. */
91         Py_hash_t y;
92         Py_uhash_t mult;
93         Py_ssize_t len;
94
95         mult = _PyHASH_MULTIPLIER;
96         len = array_len;
97         x = 0x345678UL;
98         i = 0;
99         while (--len >= 0) {
100                 y = _Py_HashDouble((double)(array[i++]));
101                 if (y == -1)
102                         return -1;
103                 x = (x ^ y) * mult;
104                 /* the cast might truncate len; that doesn't change hash stability */
105                 mult += (Py_hash_t)(82520UL + len + len);
106         }
107         x += 97531UL;
108         if (x == (Py_uhash_t)-1)
109                 x = -2;
110         return x;
111 }
112
113 /* helper functionm returns length of the 'value', -1 on error */
114 int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
115 {
116         const int flag = array_max;
117         int size;
118
119         array_max &= ~MU_ARRAY_FLAGS;
120
121 #if 1 /* approx 6x speedup for mathutils types */
122
123         if ((size = VectorObject_Check(value)     ? ((VectorObject *)value)->size : 0) ||
124             (size = EulerObject_Check(value)      ? 3 : 0) ||
125             (size = QuaternionObject_Check(value) ? 4 : 0) ||
126             (size = ColorObject_Check(value)      ? 3 : 0))
127         {
128                 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
129                         return -1;
130                 }
131
132                 if (flag & MU_ARRAY_SPILL) {
133                         CLAMP_MAX(size, array_max);
134                 }
135
136                 if (size > array_max || size < array_min) {
137                         if (array_max == array_min) {
138                                 PyErr_Format(PyExc_ValueError,
139                                              "%.200s: sequence size is %d, expected %d",
140                                              error_prefix, size, array_max);
141                         }
142                         else {
143                                 PyErr_Format(PyExc_ValueError,
144                                              "%.200s: sequence size is %d, expected [%d - %d]",
145                                              error_prefix, size, array_min, array_max);
146                         }
147                         return -1;
148                 }
149
150                 memcpy(array, ((BaseMathObject *)value)->data, size * sizeof(float));
151         }
152         else
153 #endif
154         {
155                 PyObject *value_fast = NULL;
156
157                 /* non list/tuple cases */
158                 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
159                         /* PySequence_Fast sets the error */
160                         return -1;
161                 }
162
163                 size = PySequence_Fast_GET_SIZE(value_fast);
164
165                 if (flag & MU_ARRAY_SPILL) {
166                         CLAMP_MAX(size, array_max);
167                 }
168
169                 if (size > array_max || size < array_min) {
170                         if (array_max == array_min) {
171                                 PyErr_Format(PyExc_ValueError,
172                                              "%.200s: sequence size is %d, expected %d",
173                                              error_prefix, size, array_max);
174                         }
175                         else {
176                                 PyErr_Format(PyExc_ValueError,
177                                              "%.200s: sequence size is %d, expected [%d - %d]",
178                                              error_prefix, size, array_min, array_max);
179                         }
180                         Py_DECREF(value_fast);
181                         return -1;
182                 }
183
184                 size = mathutils_array_parse_fast(array, size, value_fast, error_prefix);
185         }
186
187         if (size != -1) {
188                 if (flag & MU_ARRAY_ZERO) {
189                         int size_left = array_max - size;
190                         if (size_left) {
191                                 memset(&array[size], 0, sizeof(float) * size_left);
192                         }
193                 }
194         }
195
196         return size;
197 }
198
199 /* on error, -1 is returned and no allocation is made */
200 int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, const char *error_prefix)
201 {
202         int size;
203
204 #if 1 /* approx 6x speedup for mathutils types */
205
206         if ((size = VectorObject_Check(value)     ? ((VectorObject *)value)->size : 0) ||
207             (size = EulerObject_Check(value)      ? 3 : 0) ||
208             (size = QuaternionObject_Check(value) ? 4 : 0) ||
209             (size = ColorObject_Check(value)      ? 3 : 0))
210         {
211                 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
212                         return -1;
213                 }
214
215                 if (size < array_min) {
216                         PyErr_Format(PyExc_ValueError,
217                                      "%.200s: sequence size is %d, expected > %d",
218                                      error_prefix, size, array_min);
219                         return -1;
220                 }
221                 
222                 *array = PyMem_Malloc(size * sizeof(float));
223                 memcpy(*array, ((BaseMathObject *)value)->data, size * sizeof(float));
224                 return size;
225         }
226         else
227 #endif
228         {
229                 PyObject *value_fast = NULL;
230                 // *array = NULL;
231                 int ret;
232
233                 /* non list/tuple cases */
234                 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
235                         /* PySequence_Fast sets the error */
236                         return -1;
237                 }
238
239                 size = PySequence_Fast_GET_SIZE(value_fast);
240
241                 if (size < array_min) {
242                         PyErr_Format(PyExc_ValueError,
243                                      "%.200s: sequence size is %d, expected > %d",
244                                      error_prefix, size, array_min);
245                         return -1;
246                 }
247
248                 *array = PyMem_Malloc(size * sizeof(float));
249
250                 ret = mathutils_array_parse_fast(*array, size, value_fast, error_prefix);
251
252                 if (ret == -1) {
253                         PyMem_Free(*array);
254                 }
255
256                 return ret;
257         }
258 }
259
260 /* parse an array of vectors */
261 int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix)
262 {
263         PyObject *value_fast = NULL;
264         const int array_dim_flag = array_dim;
265         int i, size;
266
267         /* non list/tuple cases */
268         if (!(value_fast = PySequence_Fast(value, error_prefix))) {
269                 /* PySequence_Fast sets the error */
270                 return -1;
271         }
272
273         size = PySequence_Fast_GET_SIZE(value_fast);
274
275         if (size != 0) {
276                 float *fp;
277
278                 array_dim &= ~MU_ARRAY_FLAGS;
279
280                 fp = *array = PyMem_Malloc(size * array_dim * sizeof(float));
281
282                 for (i = 0; i < size; i++, fp += array_dim) {
283                         PyObject *item = PySequence_Fast_GET_ITEM(value, i);
284
285                         if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) {
286                                 PyMem_Free(*array);
287                                 *array = NULL;
288                                 size = -1;
289                                 break;
290                         }
291                 }
292         }
293
294         Py_DECREF(value_fast);
295         return size;
296 }
297
298 int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
299 {
300         if (EulerObject_Check(value)) {
301                 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
302                         return -1;
303                 }
304                 else {
305                         eulO_to_mat3(rmat, ((EulerObject *)value)->eul, ((EulerObject *)value)->order);
306                         return 0;
307                 }
308         }
309         else if (QuaternionObject_Check(value)) {
310                 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
311                         return -1;
312                 }
313                 else {
314                         float tquat[4];
315                         normalize_qt_qt(tquat, ((QuaternionObject *)value)->quat);
316                         quat_to_mat3(rmat, tquat);
317                         return 0;
318                 }
319         }
320         else if (MatrixObject_Check(value)) {
321                 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
322                         return -1;
323                 }
324                 else if (((MatrixObject *)value)->num_row < 3 || ((MatrixObject *)value)->num_col < 3) {
325                         PyErr_Format(PyExc_ValueError,
326                                      "%.200s: matrix must have minimum 3x3 dimensions",
327                                      error_prefix);
328                         return -1;
329                 }
330                 else {
331                         matrix_as_3x3(rmat, (MatrixObject *)value);
332                         normalize_m3(rmat);
333                         return 0;
334                 }
335         }
336         else {
337                 PyErr_Format(PyExc_TypeError,
338                              "%.200s: expected a Euler, Quaternion or Matrix type, "
339                              "found %.200s", error_prefix, Py_TYPE(value)->tp_name);
340                 return -1;
341         }
342 }
343
344
345 /* ----------------------------------MATRIX FUNCTIONS-------------------- */
346
347
348 /* Utility functions */
349
350 /* LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon */
351 #define SIGNMASK(i) (-(int)(((unsigned int)(i)) >> 31))
352
353 int EXPP_FloatsAreEqual(float af, float bf, int maxDiff)
354 {
355         /* solid, fast routine across all platforms
356          * with constant time behavior */
357         int ai = *(int *)(&af);
358         int bi = *(int *)(&bf);
359         int test = SIGNMASK(ai ^ bi);
360         int diff, v1, v2;
361
362         assert((0 == test) || (0xFFFFFFFF == test));
363         diff = (ai ^ (test & 0x7fffffff)) - bi;
364         v1 = maxDiff + diff;
365         v2 = maxDiff - diff;
366         return (v1 | v2) >= 0;
367 }
368
369 /*---------------------- EXPP_VectorsAreEqual -------------------------
370  * Builds on EXPP_FloatsAreEqual to test vectors */
371 int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
372 {
373         int x;
374         for (x = 0; x < size; x++) {
375                 if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
376                         return 0;
377         }
378         return 1;
379 }
380
381 #ifndef MATH_STANDALONE
382 /* dynstr as python string utility funcions, frees 'ds'! */
383 PyObject *mathutils_dynstr_to_py(struct DynStr *ds)
384 {
385         const int ds_len = BLI_dynstr_get_len(ds); /* space for \0 */
386         char *ds_buf     = PyMem_Malloc(ds_len + 1);
387         PyObject *ret;
388         BLI_dynstr_get_cstring_ex(ds, ds_buf);
389         BLI_dynstr_free(ds);
390         ret = PyUnicode_FromStringAndSize(ds_buf, ds_len);
391         PyMem_Free(ds_buf);
392         return ret;
393 }
394 #endif
395
396 /* silly function, we dont use arg. just check its compatible with __deepcopy__ */
397 int mathutils_deepcopy_args_check(PyObject *args)
398 {
399         PyObject *dummy_pydict;
400         return PyArg_ParseTuple(args, "|O!:__deepcopy__", &PyDict_Type, &dummy_pydict) != 0;
401 }
402
403 /* Mathutils Callbacks */
404
405 /* for mathutils internal use only, eventually should re-alloc but to start with we only have a few users */
406 #define MATHUTILS_TOT_CB 16
407 static Mathutils_Callback *mathutils_callbacks[MATHUTILS_TOT_CB] = {NULL};
408
409 unsigned char Mathutils_RegisterCallback(Mathutils_Callback *cb)
410 {
411         unsigned char i;
412         
413         /* find the first free slot */
414         for (i = 0; mathutils_callbacks[i]; i++) {
415                 if (mathutils_callbacks[i] == cb) /* already registered? */
416                         return i;
417         }
418
419         BLI_assert(i + 1 < MATHUTILS_TOT_CB);
420
421         mathutils_callbacks[i] = cb;
422         return i;
423 }
424
425 /* use macros to check for NULL */
426 int _BaseMathObject_ReadCallback(BaseMathObject *self)
427 {
428         Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
429         if (LIKELY(cb->get(self, self->cb_subtype) != -1)) {
430                 return 0;
431         }
432
433         if (!PyErr_Occurred()) {
434                 PyErr_Format(PyExc_RuntimeError,
435                              "%s read, user has become invalid",
436                              Py_TYPE(self)->tp_name);
437         }
438         return -1;
439 }
440
441 int _BaseMathObject_WriteCallback(BaseMathObject *self)
442 {
443         Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
444         if (LIKELY(cb->set(self, self->cb_subtype) != -1)) {
445                 return 0;
446         }
447
448         if (!PyErr_Occurred()) {
449                 PyErr_Format(PyExc_RuntimeError,
450                              "%s write, user has become invalid",
451                              Py_TYPE(self)->tp_name);
452         }
453         return -1;
454 }
455
456 int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index)
457 {
458         Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
459         if (LIKELY(cb->get_index(self, self->cb_subtype, index) != -1)) {
460                 return 0;
461         }
462
463         if (!PyErr_Occurred()) {
464                 PyErr_Format(PyExc_RuntimeError,
465                              "%s read index, user has become invalid",
466                              Py_TYPE(self)->tp_name);
467         }
468         return -1;
469 }
470
471 int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
472 {
473         Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
474         if (LIKELY(cb->set_index(self, self->cb_subtype, index) != -1)) {
475                 return 0;
476         }
477
478         if (!PyErr_Occurred()) {
479                 PyErr_Format(PyExc_RuntimeError,
480                              "%s write index, user has become invalid",
481                              Py_TYPE(self)->tp_name);
482         }
483         return -1;
484 }
485
486 void _BaseMathObject_RaiseFrozenExc(const BaseMathObject *self)
487 {
488         PyErr_Format(PyExc_TypeError,
489                      "%s is frozen (immutable)",
490                      Py_TYPE(self)->tp_name);
491 }
492
493 void _BaseMathObject_RaiseNotFrozenExc(const BaseMathObject *self)
494 {
495         PyErr_Format(PyExc_TypeError,
496                      "%s is not frozen (mutable), call freeze first",
497                      Py_TYPE(self)->tp_name);
498 }
499
500 /* BaseMathObject generic functions for all mathutils types */
501 char BaseMathObject_owner_doc[] = "The item this is wrapping or None  (read-only).";
502 PyObject *BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure))
503 {
504         PyObject *ret = self->cb_user ? self->cb_user : Py_None;
505         return Py_INCREF_RET(ret);
506 }
507
508 char BaseMathObject_is_wrapped_doc[] = "True when this object wraps external data (read-only).\n\n:type: boolean";
509 PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closure))
510 {
511         return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_WRAP) != 0);
512 }
513
514 char BaseMathObject_is_frozen_doc[] = "True when this object has been frozen (read-only).\n\n:type: boolean";
515 PyObject *BaseMathObject_is_frozen_get(BaseMathObject *self, void *UNUSED(closure))
516 {
517         return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_FROZEN) != 0);
518 }
519
520 char BaseMathObject_freeze_doc[] =
521 ".. function:: freeze()\n"
522 "\n"
523 "   Make this object immutable.\n"
524 "\n"
525 "   After this the object can be hashed, used in dictionaries & sets.\n"
526 "\n"
527 "   :return: An instance of this object.\n"
528 ;
529 PyObject *BaseMathObject_freeze(BaseMathObject *self)
530 {
531         if (self->flag & BASE_MATH_FLAG_IS_WRAP) {
532                 PyErr_SetString(PyExc_TypeError, "Cannot freeze wrapped data");
533                 return NULL;
534         }
535
536         self->flag |= BASE_MATH_FLAG_IS_FROZEN;
537
538         return Py_INCREF_RET((PyObject *)self);
539 }
540
541 int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
542 {
543         Py_VISIT(self->cb_user);
544         return 0;
545 }
546
547 int BaseMathObject_clear(BaseMathObject *self)
548 {
549         Py_CLEAR(self->cb_user);
550         return 0;
551 }
552
553 void BaseMathObject_dealloc(BaseMathObject *self)
554 {
555         /* only free non wrapped */
556         if ((self->flag & BASE_MATH_FLAG_IS_WRAP) == 0) {
557                 PyMem_Free(self->data);
558         }
559
560         if (self->cb_user) {
561                 PyObject_GC_UnTrack(self);
562                 BaseMathObject_clear(self);
563         }
564
565         Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes
566 }
567
568 /*----------------------------MODULE INIT-------------------------*/
569 static struct PyMethodDef M_Mathutils_methods[] = {
570         {NULL, NULL, 0, NULL}
571 };
572
573 static struct PyModuleDef M_Mathutils_module_def = {
574         PyModuleDef_HEAD_INIT,
575         "mathutils",  /* m_name */
576         M_Mathutils_doc,  /* m_doc */
577         0,  /* m_size */
578         M_Mathutils_methods,  /* m_methods */
579         NULL,  /* m_reload */
580         NULL,  /* m_traverse */
581         NULL,  /* m_clear */
582         NULL,  /* m_free */
583 };
584
585
586 /* submodules only */
587 #include "mathutils_geometry.h"
588 #include "mathutils_interpolate.h"
589 #ifndef MATH_STANDALONE
590 #  include "mathutils_kdtree.h"
591 #  include "mathutils_noise.h"
592 #endif
593
594 PyMODINIT_FUNC PyInit_mathutils(void)
595 {
596         PyObject *mod;
597         PyObject *submodule;
598         PyObject *sys_modules = PyThreadState_GET()->interp->modules;
599
600         if (PyType_Ready(&vector_Type) < 0)
601                 return NULL;
602         if (PyType_Ready(&matrix_Type) < 0)
603                 return NULL;
604         if (PyType_Ready(&matrix_access_Type) < 0)
605                 return NULL;
606         if (PyType_Ready(&euler_Type) < 0)
607                 return NULL;
608         if (PyType_Ready(&quaternion_Type) < 0)
609                 return NULL;
610         if (PyType_Ready(&color_Type) < 0)
611                 return NULL;
612
613         mod = PyModule_Create(&M_Mathutils_module_def);
614         
615         /* each type has its own new() function */
616         PyModule_AddObject(mod, vector_Type.tp_name,     (PyObject *)&vector_Type);
617         PyModule_AddObject(mod, matrix_Type.tp_name,     (PyObject *)&matrix_Type);
618         PyModule_AddObject(mod, euler_Type.tp_name,      (PyObject *)&euler_Type);
619         PyModule_AddObject(mod, quaternion_Type.tp_name, (PyObject *)&quaternion_Type);
620         PyModule_AddObject(mod, color_Type.tp_name,      (PyObject *)&color_Type);
621         
622         /* submodule */
623         PyModule_AddObject(mod, "geometry",       (submodule = PyInit_mathutils_geometry()));
624         /* XXX, python doesnt do imports with this usefully yet
625          * 'from mathutils.geometry import PolyFill'
626          * ...fails without this. */
627         PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
628         Py_INCREF(submodule);
629
630         PyModule_AddObject(mod, "interpolate",    (submodule = PyInit_mathutils_interpolate()));
631         /* XXX, python doesnt do imports with this usefully yet
632          * 'from mathutils.geometry import PolyFill'
633          * ...fails without this. */
634         PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
635         Py_INCREF(submodule);
636
637 #ifndef MATH_STANDALONE
638         /* Noise submodule */
639         PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise()));
640         PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
641         Py_INCREF(submodule);
642
643         /* KDTree submodule */
644         PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree()));
645         PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
646         Py_INCREF(submodule);
647 #endif
648
649         mathutils_matrix_row_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_row_cb);
650         mathutils_matrix_col_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_col_cb);
651         mathutils_matrix_translation_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_translation_cb);
652
653         return mod;
654 }