Blender V4.3
mathutils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <Python.h>
10
11#include "mathutils.hh"
12
13#include "BLI_math_matrix.h"
14#include "BLI_math_rotation.h"
15#include "BLI_utildefines.h"
16
19
20#ifndef MATH_STANDALONE
21# include "BLI_dynstr.h"
22#endif
23
25 /* Wrap. */
26 M_Mathutils_doc,
27 "This module provides access to math operations.\n"
28 "\n"
29 ".. note::\n"
30 "\n"
31 " Classes, methods and attributes that accept vectors also accept other numeric sequences,\n"
32 " such as tuples, lists.\n"
33 "\n"
34 "The :mod:`mathutils` module provides the following classes:\n"
35 "\n"
36 "- :class:`Color`,\n"
37 "- :class:`Euler`,\n"
38 "- :class:`Matrix`,\n"
39 "- :class:`Quaternion`,\n"
40 "- :class:`Vector`,\n");
42 int size,
43 PyObject *value_fast,
44 const char *error_prefix)
45{
46 PyObject *item;
47 PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
48
49 int i;
50
51 i = size;
52 do {
53 i--;
54 if (((array[i] = PyFloat_AsDouble(item = value_fast_items[i])) == -1.0f) && PyErr_Occurred()) {
55 PyErr_Format(PyExc_TypeError,
56 "%.200s: sequence index %d expected a number, "
57 "found '%.200s' type, ",
58 error_prefix,
59 i,
60 Py_TYPE(item)->tp_name);
61 size = -1;
62 break;
63 }
64 } while (i);
65
66 return size;
67}
68
69Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
70{
71 int i;
72 Py_uhash_t x; /* Unsigned for defined overflow behavior. */
73 Py_hash_t y;
74 Py_uhash_t mult;
75 Py_ssize_t len;
76
77 mult = _PyHASH_MULTIPLIER;
78 len = array_len;
79 x = 0x345678UL;
80 i = 0;
81 while (--len >= 0) {
82 y = _Py_HashDouble(nullptr, double(array[i++]));
83 if (y == -1) {
84 return -1;
85 }
86 x = (x ^ y) * mult;
87 /* the cast might truncate len; that doesn't change hash stability */
88 mult += (Py_hash_t)(82520UL + len + len);
89 }
90 x += 97531UL;
91 if (x == (Py_uhash_t)-1) {
92 x = -2;
93 }
94 return x;
95}
96
98 float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
99{
100 const uint flag = array_num_max;
101 int num;
102
103 array_num_max &= ~MU_ARRAY_FLAGS;
104
105#if 1 /* approx 6x speedup for mathutils types */
106
107 if ((num = VectorObject_Check(value) ? ((VectorObject *)value)->vec_num : 0) ||
108 (num = EulerObject_Check(value) ? 3 : 0) || (num = QuaternionObject_Check(value) ? 4 : 0) ||
109 (num = ColorObject_Check(value) ? 3 : 0))
110 {
111 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
112 return -1;
113 }
114
115 if (flag & MU_ARRAY_SPILL) {
116 CLAMP_MAX(num, array_num_max);
117 }
118
119 if (num > array_num_max || num < array_num_min) {
120 if (array_num_max == array_num_min) {
121 PyErr_Format(PyExc_ValueError,
122 "%.200s: sequence length is %d, expected %d",
123 error_prefix,
124 num,
125 array_num_max);
126 }
127 else {
128 PyErr_Format(PyExc_ValueError,
129 "%.200s: sequence length is %d, expected [%d - %d]",
130 error_prefix,
131 num,
132 array_num_min,
133 array_num_max);
134 }
135 return -1;
136 }
137
138 memcpy(array, ((const BaseMathObject *)value)->data, num * sizeof(float));
139 }
140 else
141#endif
142 {
143 PyObject *value_fast = nullptr;
144
145 /* non list/tuple cases */
146 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
147 /* PySequence_Fast sets the error */
148 return -1;
149 }
150
151 num = PySequence_Fast_GET_SIZE(value_fast);
152
153 if (flag & MU_ARRAY_SPILL) {
154 CLAMP_MAX(num, array_num_max);
155 }
156
157 if (num > array_num_max || num < array_num_min) {
158 if (array_num_max == array_num_min) {
159 PyErr_Format(PyExc_ValueError,
160 "%.200s: sequence length is %d, expected %d",
161 error_prefix,
162 num,
163 array_num_max);
164 }
165 else {
166 PyErr_Format(PyExc_ValueError,
167 "%.200s: sequence length is %d, expected [%d - %d]",
168 error_prefix,
169 num,
170 array_num_min,
171 array_num_max);
172 }
173 Py_DECREF(value_fast);
174 return -1;
175 }
176
177 num = mathutils_array_parse_fast(array, num, value_fast, error_prefix);
178 Py_DECREF(value_fast);
179 }
180
181 if (num != -1) {
182 if (flag & MU_ARRAY_ZERO) {
183 const int array_num_left = array_num_max - num;
184 if (array_num_left) {
185 memset(&array[num], 0, sizeof(float) * array_num_left);
186 }
187 }
188 }
189
190 return num;
191}
192
194 int array_num_min,
195 PyObject *value,
196 const char *error_prefix)
197{
198 int num;
199
200#if 1 /* approx 6x speedup for mathutils types */
201
202 if ((num = VectorObject_Check(value) ? ((VectorObject *)value)->vec_num : 0) ||
203 (num = EulerObject_Check(value) ? 3 : 0) || (num = QuaternionObject_Check(value) ? 4 : 0) ||
204 (num = ColorObject_Check(value) ? 3 : 0))
205 {
206 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
207 return -1;
208 }
209
210 if (num < array_num_min) {
211 PyErr_Format(PyExc_ValueError,
212 "%.200s: sequence size is %d, expected >= %d",
213 error_prefix,
214 num,
215 array_num_min);
216 return -1;
217 }
218
219 *array = static_cast<float *>(PyMem_Malloc(num * sizeof(float)));
220 memcpy(*array, ((const BaseMathObject *)value)->data, num * sizeof(float));
221 return num;
222 }
223
224#endif
225
226 PyObject *value_fast = nullptr;
227 // *array = nullptr;
228 int ret;
229
230 /* non list/tuple cases */
231 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
232 /* PySequence_Fast sets the error */
233 return -1;
234 }
235
236 num = PySequence_Fast_GET_SIZE(value_fast);
237
238 if (num < array_num_min) {
239 Py_DECREF(value_fast);
240 PyErr_Format(PyExc_ValueError,
241 "%.200s: sequence size is %d, expected >= %d",
242 error_prefix,
243 num,
244 array_num_min);
245 return -1;
246 }
247
248 *array = static_cast<float *>(PyMem_Malloc(num * sizeof(float)));
249
250 ret = mathutils_array_parse_fast(*array, num, value_fast, error_prefix);
251 Py_DECREF(value_fast);
252
253 if (ret == -1) {
254 PyMem_Free(*array);
255 }
256
257 return ret;
258}
259
261 int array_dim,
262 PyObject *value,
263 const char *error_prefix)
264{
265 PyObject *value_fast;
266 const int array_dim_flag = array_dim;
267 int i, num;
268
269 /* non list/tuple cases */
270 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
271 /* PySequence_Fast sets the error */
272 return -1;
273 }
274
275 num = PySequence_Fast_GET_SIZE(value_fast);
276
277 if (num != 0) {
278 PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
279 float *fp;
280
281 array_dim &= ~MU_ARRAY_FLAGS;
282
283 fp = *array = static_cast<float *>(PyMem_Malloc(num * array_dim * sizeof(float)));
284
285 for (i = 0; i < num; i++, fp += array_dim) {
286 PyObject *item = value_fast_items[i];
287
288 if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) {
289 PyMem_Free(*array);
290 *array = nullptr;
291 num = -1;
292 break;
293 }
294 }
295 }
296
297 Py_DECREF(value_fast);
298 return num;
299}
300
301int mathutils_int_array_parse(int *array, int array_dim, PyObject *value, const char *error_prefix)
302{
303 int size, i;
304 PyObject *value_fast, **value_fast_items, *item;
305
306 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
307 /* PySequence_Fast sets the error */
308 return -1;
309 }
310
311 if ((size = PySequence_Fast_GET_SIZE(value_fast)) != array_dim) {
312 PyErr_Format(PyExc_ValueError,
313 "%.200s: sequence size is %d, expected %d",
314 error_prefix,
315 size,
316 array_dim);
317 Py_DECREF(value_fast);
318 return -1;
319 }
320
321 value_fast_items = PySequence_Fast_ITEMS(value_fast);
322 i = size;
323 while (i > 0) {
324 i--;
325 if (((array[i] = PyC_Long_AsI32(item = value_fast_items[i])) == -1) && PyErr_Occurred()) {
326 PyErr_Format(PyExc_TypeError, "%.200s: sequence index %d expected an int", error_prefix, i);
327 size = -1;
328 break;
329 }
330 }
331 Py_DECREF(value_fast);
332
333 return size;
334}
335
337 int array_dim,
338 PyObject *value,
339 const char *error_prefix)
340{
341 PyObject *value_fast;
342 int i, size;
343
344 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
345 /* PySequence_Fast sets the error */
346 return -1;
347 }
348
349 size = PySequence_Fast_GET_SIZE(value_fast);
350
351 if (size != 0) {
352 PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
353 int *ip;
354
355 ip = *array = static_cast<int *>(PyMem_Malloc(size * array_dim * sizeof(int)));
356
357 for (i = 0; i < size; i++, ip += array_dim) {
358 PyObject *item = value_fast_items[i];
359
360 if (mathutils_int_array_parse(ip, array_dim, item, error_prefix) == -1) {
361 PyMem_Free(*array);
362 *array = nullptr;
363 size = -1;
364 break;
365 }
366 }
367 }
368
369 Py_DECREF(value_fast);
370 return size;
371}
372
374 const char *error_prefix,
376{
377 PyObject *value_fast;
378 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
379 /* PySequence_Fast sets the error */
380 return false;
381 }
382
383 const int size = PySequence_Fast_GET_SIZE(value_fast);
384 if (size != 0) {
385 PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
386 r_data.reinitialize(size);
387 for (const int64_t i : r_data.index_range()) {
388 PyObject *subseq = value_fast_items[i];
389 const int subseq_len = int(PySequence_Size(subseq));
390 if (subseq_len == -1) {
391 PyErr_Format(
392 PyExc_ValueError, "%.200s: sequence expected to have subsequences", error_prefix);
393 Py_DECREF(value_fast);
394 return false;
395 }
396 r_data[i].resize(subseq_len);
397 blender::MutableSpan<int> group = r_data[i];
398 if (mathutils_int_array_parse(group.data(), group.size(), subseq, error_prefix) == -1) {
399 Py_DECREF(value_fast);
400 return false;
401 }
402 }
403 }
404
405 Py_DECREF(value_fast);
406 return true;
407}
408
409int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
410{
411 if (EulerObject_Check(value)) {
412 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
413 return -1;
414 }
415
416 eulO_to_mat3(rmat, ((const EulerObject *)value)->eul, ((const EulerObject *)value)->order);
417 return 0;
418 }
419 if (QuaternionObject_Check(value)) {
420 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
421 return -1;
422 }
423
424 float tquat[4];
425 normalize_qt_qt(tquat, ((const QuaternionObject *)value)->quat);
426 quat_to_mat3(rmat, tquat);
427 return 0;
428 }
429 if (MatrixObject_Check(value)) {
430 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
431 return -1;
432 }
433 if (((MatrixObject *)value)->row_num < 3 || ((MatrixObject *)value)->col_num < 3) {
434 PyErr_Format(
435 PyExc_ValueError, "%.200s: matrix must have minimum 3x3 dimensions", error_prefix);
436 return -1;
437 }
438
439 matrix_as_3x3(rmat, (MatrixObject *)value);
440 normalize_m3(rmat);
441 return 0;
442 }
443
444 PyErr_Format(PyExc_TypeError,
445 "%.200s: expected a Euler, Quaternion or Matrix type, "
446 "found %.200s",
447 error_prefix,
448 Py_TYPE(value)->tp_name);
449 return -1;
450}
451
452/* ----------------------------------MATRIX FUNCTIONS-------------------- */
453
454/* Utility functions */
455
456/* LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon */
457/* XXX We may want to use 'safer' BLI's compare_ff_relative ultimately?
458 * LomontRRDCompare4() is an optimized version of Dawson's AlmostEqual2sComplement()
459 * (see [1] and [2]).
460 * Dawson himself now claims this is not a 'safe' thing to do
461 * (pushing ULP method beyond its limits),
462 * an recommends using work from [3] instead, which is done in BLI func...
463 *
464 * [1] http://www.randydillon.org/Papers/2007/everfast.htm
465 * [2] http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
466 * [3] https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
467 * instead.
468 */
469#define SIGNMASK(i) (-int((uint(i)) >> 31))
470
471int EXPP_FloatsAreEqual(float af, float bf, int maxDiff)
472{
473 /* solid, fast routine across all platforms
474 * with constant time behavior */
475 const int ai = *(const int *)(&af);
476 const int bi = *(const int *)(&bf);
477 const int test = SIGNMASK(ai ^ bi);
478 int diff, v1, v2;
479
480 BLI_assert((0 == test) || (0xFFFFFFFF == test));
481 diff = (ai ^ (test & 0x7fffffff)) - bi;
482 v1 = maxDiff + diff;
483 v2 = maxDiff - diff;
484 return (v1 | v2) >= 0;
485}
486
487/*---------------------- EXPP_VectorsAreEqual -------------------------
488 * Builds on EXPP_FloatsAreEqual to test vectors */
489
490int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
491{
492 int x;
493 for (x = 0; x < size; x++) {
494 if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0) {
495 return 0;
496 }
497 }
498 return 1;
499}
500
501#ifndef MATH_STANDALONE
503{
504 const int ds_len = BLI_dynstr_get_len(ds); /* space for \0 */
505 char *ds_buf = static_cast<char *>(PyMem_Malloc(ds_len + 1));
506 PyObject *ret;
507 BLI_dynstr_get_cstring_ex(ds, ds_buf);
508 BLI_dynstr_free(ds);
509 ret = PyUnicode_FromStringAndSize(ds_buf, ds_len);
510 PyMem_Free(ds_buf);
511 return ret;
512}
513#endif
514
515/* Mathutils Callbacks */
516
517/* For mathutils internal use only,
518 * eventually should re-alloc but to start with we only have a few users. */
519#define MATHUTILS_TOT_CB 17
521
523{
524 uchar i;
525
526 /* find the first free slot */
527 for (i = 0; mathutils_callbacks[i]; i++) {
528 if (mathutils_callbacks[i] == cb) {
529 /* already registered? */
530 return i;
531 }
532 }
533
535
536 mathutils_callbacks[i] = cb;
537 return i;
538}
539
541{
543 if (LIKELY(cb->check(self) != -1)) {
544 return 0;
545 }
546 return -1;
547}
548
550{
551 /* NOTE: use macros to check for nullptr. */
552
554 if (LIKELY(cb->get(self, self->cb_subtype) != -1)) {
555 return 0;
556 }
557
558 if (!PyErr_Occurred()) {
559 PyErr_Format(PyExc_RuntimeError, "%s read, user has become invalid", Py_TYPE(self)->tp_name);
560 }
561 return -1;
562}
563
565{
567 if (LIKELY(cb->set(self, self->cb_subtype) != -1)) {
568 return 0;
569 }
570
571 if (!PyErr_Occurred()) {
572 PyErr_Format(PyExc_RuntimeError, "%s write, user has become invalid", Py_TYPE(self)->tp_name);
573 }
574 return -1;
575}
576
578{
580 if (LIKELY(cb->get_index(self, self->cb_subtype, index) != -1)) {
581 return 0;
582 }
583
584 if (!PyErr_Occurred()) {
585 PyErr_Format(
586 PyExc_RuntimeError, "%s read index, user has become invalid", Py_TYPE(self)->tp_name);
587 }
588 return -1;
589}
590
592{
594 if (LIKELY(cb->set_index(self, self->cb_subtype, index) != -1)) {
595 return 0;
596 }
597
598 if (!PyErr_Occurred()) {
599 PyErr_Format(
600 PyExc_RuntimeError, "%s write index, user has become invalid", Py_TYPE(self)->tp_name);
601 }
602 return -1;
603}
604
606{
607 PyErr_Format(PyExc_TypeError, "%s is frozen (immutable)", Py_TYPE(self)->tp_name);
608}
609
611{
612 PyErr_Format(
613 PyExc_TypeError, "%s is not frozen (mutable), call freeze first", Py_TYPE(self)->tp_name);
614}
615
616/* #BaseMathObject generic functions for all mathutils types. */
617
618char BaseMathObject_owner_doc[] = "The item this is wrapping or None (read-only).";
619PyObject *BaseMathObject_owner_get(BaseMathObject *self, void * /*closure*/)
620{
621 PyObject *ret = self->cb_user ? self->cb_user : Py_None;
622 return Py_NewRef(ret);
623}
624
626 "True when this object wraps external data (read-only).\n\n:type: bool";
627PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void * /*closure*/)
628{
629 return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_WRAP) != 0);
630}
631
633 "True when this object has been frozen (read-only).\n\n:type: bool";
634PyObject *BaseMathObject_is_frozen_get(BaseMathObject *self, void * /*closure*/)
635{
636 return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_FROZEN) != 0);
637}
638
639char BaseMathObject_is_valid_doc[] = "True when the owner of this data is valid.\n\n:type: bool";
640PyObject *BaseMathObject_is_valid_get(BaseMathObject *self, void * /*closure*/)
641{
642 return PyBool_FromLong(BaseMath_CheckCallback(self) == 0);
643}
644
646 ".. function:: freeze()\n"
647 "\n"
648 " Make this object immutable.\n"
649 "\n"
650 " After this the object can be hashed, used in dictionaries & sets.\n"
651 "\n"
652 " :return: An instance of this object.\n";
654{
655 if ((self->flag & BASE_MATH_FLAG_IS_WRAP) || (self->cb_user != nullptr)) {
656 PyErr_SetString(PyExc_TypeError, "Cannot freeze wrapped/owned data");
657 return nullptr;
658 }
659
661
662 return Py_NewRef(self);
663}
664
665int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
666{
667 Py_VISIT(self->cb_user);
668 return 0;
669}
670
672{
673 Py_CLEAR(self->cb_user);
674 return 0;
675}
676
678#ifndef NDEBUG
680{
681 PyObject *cb_user = self->cb_user;
682 self->cb_user = (PyObject *)uintptr_t(-1);
683 bool is_tracked = PyObject_GC_IsTracked((PyObject *)self);
684 self->cb_user = cb_user;
685 return is_tracked;
686}
687#endif /* !NDEBUG */
688
690{
691 /* only free non wrapped */
692 if ((self->flag & BASE_MATH_FLAG_IS_WRAP) == 0) {
693 PyMem_Free(self->data);
694 }
695
696 if (self->cb_user) {
698 PyObject_GC_UnTrack(self);
700 }
701 else if (!BaseMathObject_CheckExact(self)) {
702 /* Sub-classed types get an extra track (in Pythons internal `subtype_dealloc` function). */
704 PyObject_GC_UnTrack(self);
706 }
707
708 Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); /* breaks sub-types. */
709}
710
712{
713 return self->cb_user != nullptr;
714}
715
716PyObject *_BaseMathObject_new_impl(PyTypeObject *root_type, PyTypeObject *base_type)
717{
718 PyObject *obj;
719 if (ELEM(base_type, nullptr, root_type)) {
720 obj = _PyObject_GC_New(root_type);
721 if (obj) {
723 }
724 }
725 else {
726 /* Calls Generic allocation function which always tracks
727 * (because `root_type` is flagged for GC). */
728 obj = base_type->tp_alloc(base_type, 0);
729 if (obj) {
731 PyObject_GC_UnTrack(obj);
733 }
734 }
735
736 return obj;
737}
738
739/*----------------------------MODULE INIT-------------------------*/
740static PyMethodDef M_Mathutils_methods[] = {
741 {nullptr, nullptr, 0, nullptr},
742};
743
744static PyModuleDef M_Mathutils_module_def = {
745 /*m_base*/ PyModuleDef_HEAD_INIT,
746 /*m_name*/ "mathutils",
747 /*m_doc*/ M_Mathutils_doc,
748 /*m_size*/ 0,
749 /*m_methods*/ M_Mathutils_methods,
750 /*m_slots*/ nullptr,
751 /*m_traverse*/ nullptr,
752 /*m_clear*/ nullptr,
753 /*m_free*/ nullptr,
754};
755
756/* submodules only */
757#include "mathutils_geometry.hh"
759#ifndef MATH_STANDALONE
760# include "mathutils_bvhtree.hh"
761# include "mathutils_kdtree.hh"
762# include "mathutils_noise.hh"
763#endif
764
765PyMODINIT_FUNC PyInit_mathutils()
766{
767 PyObject *mod;
768 PyObject *submodule;
769 PyObject *sys_modules = PyImport_GetModuleDict();
770
771 if (PyType_Ready(&vector_Type) < 0) {
772 return nullptr;
773 }
774 if (PyType_Ready(&matrix_Type) < 0) {
775 return nullptr;
776 }
777 if (PyType_Ready(&matrix_access_Type) < 0) {
778 return nullptr;
779 }
780 if (PyType_Ready(&euler_Type) < 0) {
781 return nullptr;
782 }
783 if (PyType_Ready(&quaternion_Type) < 0) {
784 return nullptr;
785 }
786 if (PyType_Ready(&color_Type) < 0) {
787 return nullptr;
788 }
789
790 mod = PyModule_Create(&M_Mathutils_module_def);
791
792 /* each type has its own new() function */
793 PyModule_AddType(mod, &vector_Type);
794 PyModule_AddType(mod, &matrix_Type);
795 PyModule_AddType(mod, &euler_Type);
796 PyModule_AddType(mod, &quaternion_Type);
797 PyModule_AddType(mod, &color_Type);
798
799 /* submodule */
800 PyModule_AddObject(mod, "geometry", (submodule = PyInit_mathutils_geometry()));
801 /* XXX, python doesn't do imports with this usefully yet
802 * 'from mathutils.geometry import PolyFill'
803 * ...fails without this. */
804 PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
805
806 PyModule_AddObject(mod, "interpolate", (submodule = PyInit_mathutils_interpolate()));
807 /* XXX, python doesn't do imports with this usefully yet
808 * 'from mathutils.geometry import PolyFill'
809 * ...fails without this. */
810 PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
811
812#ifndef MATH_STANDALONE
813 /* Noise submodule */
814 PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise()));
815 PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
816
817 /* BVHTree submodule */
818 PyModule_AddObject(mod, "bvhtree", (submodule = PyInit_mathutils_bvhtree()));
819 PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
820
821 /* KDTree_3d submodule */
822 PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree()));
823 PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
824#endif
825
830
831 return mod;
832}
#define BLI_assert(a)
Definition BLI_assert.h:50
A dynamically sized string ADT.
int BLI_dynstr_get_len(const DynStr *ds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition BLI_dynstr.c:128
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition BLI_dynstr.c:174
void BLI_dynstr_get_cstring_ex(const DynStr *__restrict ds, char *__restrict rets) ATTR_NONNULL()
Definition BLI_dynstr.c:133
void normalize_m3(float R[3][3]) ATTR_NONNULL()
void quat_to_mat3(float m[3][3], const float q[4])
float normalize_qt_qt(float r[4], const float q[4])
void eulO_to_mat3(float M[3][3], const float e[3], short order)
unsigned char uchar
unsigned int uint
#define CLAMP_MAX(a, c)
#define ELEM(...)
#define LIKELY(x)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
PyObject * self
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE void mult(const btTransform &t1, const btTransform &t2)
Set the current transform as the value of the product of two transforms.
Definition btTransform.h:76
int len
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
Definition frames.inl:1166
static Mathutils_Callback * mathutils_callbacks[MATHUTILS_TOT_CB]
Definition mathutils.cc:520
int _BaseMathObject_CheckCallback(BaseMathObject *self)
Definition mathutils.cc:540
static int mathutils_array_parse_fast(float *array, int size, PyObject *value_fast, const char *error_prefix)
Definition mathutils.cc:41
int EXPP_FloatsAreEqual(float af, float bf, int maxDiff)
Definition mathutils.cc:471
#define SIGNMASK(i)
Definition mathutils.cc:469
bool mathutils_array_parse_alloc_viseq(PyObject *value, const char *error_prefix, blender::Array< blender::Vector< int > > &r_data)
Definition mathutils.cc:373
PyMODINIT_FUNC PyInit_mathutils()
Definition mathutils.cc:765
int mathutils_array_parse_alloc(float **array, int array_num_min, PyObject *value, const char *error_prefix)
Definition mathutils.cc:193
#define MATHUTILS_TOT_CB
Definition mathutils.cc:519
int BaseMathObject_is_gc(BaseMathObject *self)
Definition mathutils.cc:711
void _BaseMathObject_RaiseFrozenExc(const BaseMathObject *self)
Definition mathutils.cc:605
Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
Definition mathutils.cc:69
void BaseMathObject_dealloc(BaseMathObject *self)
Definition mathutils.cc:689
int _BaseMathObject_WriteCallback(BaseMathObject *self)
Definition mathutils.cc:564
int mathutils_int_array_parse(int *array, int array_dim, PyObject *value, const char *error_prefix)
Definition mathutils.cc:301
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
Definition mathutils.cc:490
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
Definition mathutils.cc:97
static bool BaseMathObject_is_tracked(BaseMathObject *self)
Definition mathutils.cc:679
int mathutils_array_parse_alloc_vi(int **array, int array_dim, PyObject *value, const char *error_prefix)
Definition mathutils.cc:336
uchar Mathutils_RegisterCallback(Mathutils_Callback *cb)
Definition mathutils.cc:522
int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix)
Definition mathutils.cc:260
char BaseMathObject_is_valid_doc[]
Definition mathutils.cc:639
static PyModuleDef M_Mathutils_module_def
Definition mathutils.cc:744
char BaseMathObject_is_wrapped_doc[]
Definition mathutils.cc:625
PyDoc_STRVAR(M_Mathutils_doc, "This module provides access to math operations.\n" "\n" ".. note::\n" "\n" " Classes, methods and attributes that accept vectors also accept other numeric sequences,\n" " such as tuples, lists.\n" "\n" "The :mod:`mathutils` module provides the following classes:\n" "\n" "- :class:`Color`,\n" "- :class:`Euler`,\n" "- :class:`Matrix`,\n" "- :class:`Quaternion`,\n" "- :class:`Vector`,\n")
PyObject * BaseMathObject_owner_get(BaseMathObject *self, void *)
Definition mathutils.cc:619
char BaseMathObject_is_frozen_doc[]
Definition mathutils.cc:632
static PyMethodDef M_Mathutils_methods[]
Definition mathutils.cc:740
PyObject * mathutils_dynstr_to_py(DynStr *ds)
Definition mathutils.cc:502
PyObject * _BaseMathObject_new_impl(PyTypeObject *root_type, PyTypeObject *base_type)
Definition mathutils.cc:716
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
Definition mathutils.cc:409
PyObject * BaseMathObject_is_frozen_get(BaseMathObject *self, void *)
Definition mathutils.cc:634
PyObject * BaseMathObject_freeze(BaseMathObject *self)
Definition mathutils.cc:653
PyObject * BaseMathObject_is_wrapped_get(BaseMathObject *self, void *)
Definition mathutils.cc:627
char BaseMathObject_owner_doc[]
Definition mathutils.cc:618
int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
Definition mathutils.cc:591
char BaseMathObject_freeze_doc[]
Definition mathutils.cc:645
PyObject * BaseMathObject_is_valid_get(BaseMathObject *self, void *)
Definition mathutils.cc:640
int BaseMathObject_clear(BaseMathObject *self)
Definition mathutils.cc:671
int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index)
Definition mathutils.cc:577
int _BaseMathObject_ReadCallback(BaseMathObject *self)
Definition mathutils.cc:549
void _BaseMathObject_RaiseNotFrozenExc(const BaseMathObject *self)
Definition mathutils.cc:610
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
Definition mathutils.cc:665
#define BaseMath_CheckCallback(_self)
Definition mathutils.hh:123
@ BASE_MATH_FLAG_IS_WRAP
Definition mathutils.hh:36
@ BASE_MATH_FLAG_IS_FROZEN
Definition mathutils.hh:41
#define MU_ARRAY_ZERO
Definition mathutils.hh:206
#define MU_ARRAY_SPILL
Definition mathutils.hh:209
#define BaseMath_ReadCallback(_self)
Definition mathutils.hh:125
#define BaseMathObject_CheckExact(v)
Definition mathutils.hh:70
PyTypeObject color_Type
#define ColorObject_Check(v)
PyTypeObject euler_Type
#define EulerObject_Check(v)
Mathutils_Callback mathutils_matrix_col_cb
PyTypeObject matrix_access_Type
void matrix_as_3x3(float mat[3][3], MatrixObject *self)
Mathutils_Callback mathutils_matrix_row_cb
Mathutils_Callback mathutils_matrix_translation_cb
uchar mathutils_matrix_col_cb_index
uchar mathutils_matrix_row_cb_index
uchar mathutils_matrix_translation_cb_index
PyTypeObject matrix_Type
#define MatrixObject_Check(v)
PyTypeObject quaternion_Type
#define QuaternionObject_Check(v)
PyTypeObject vector_Type
#define VectorObject_Check(v)
PyMODINIT_FUNC PyInit_mathutils_bvhtree()
PyMODINIT_FUNC PyInit_mathutils_geometry()
PyMODINIT_FUNC PyInit_mathutils_interpolate()
PyMODINIT_FUNC PyInit_mathutils_kdtree()
PyMODINIT_FUNC PyInit_mathutils_noise()
header-only utilities
return ret
_W64 unsigned int uintptr_t
Definition stdint.h:119
__int64 int64_t
Definition stdint.h:89
BaseMathSetIndexFunc set_index
Definition mathutils.hh:108
BaseMathCheckFunc check
Definition mathutils.hh:104
BaseMathGetIndexFunc get_index
Definition mathutils.hh:107
BaseMathSetFunc set
Definition mathutils.hh:106
BaseMathGetFunc get
Definition mathutils.hh:105
ccl_device_inline int mod(int x, int m)
Definition util/math.h:520
uint8_t flag
Definition wm_window.cc:138