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