22#ifndef MATH_STANDALONE
35 static const char order[][4] = {
"XYZ",
"XZY",
"YXZ",
"YZX",
"ZXY",
"ZYX"};
43#ifdef __LITTLE_ENDIAN__
44# define MAKE_ID3(a, b, c) ((a) | ((b) << 8) | ((c) << 16))
46# define MAKE_ID3(a, b, c) (((a) << 24) | ((b) << 16) | ((c) << 8))
49 switch (*((
const PY_INT32_T *)
str)) {
67 PyErr_Format(PyExc_ValueError,
"%s: invalid euler order '%s'", error_prefix,
str);
88 PyTuple_SET_ITEM(
ret, i, PyFloat_FromDouble(
self->eul[i]));
101static PyObject *
Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
103 PyObject *seq =
nullptr;
104 const char *order_str =
nullptr;
109 if (kwds && PyDict_Size(kwds)) {
110 PyErr_SetString(PyExc_TypeError,
111 "mathutils.Euler(): "
112 "takes no keyword args");
116 if (!PyArg_ParseTuple(args,
"|Os:mathutils.Euler", &seq, &order_str)) {
120 switch (PyTuple_GET_SIZE(args)) {
145 Euler_to_quaternion_doc,
146 ".. method:: to_quaternion()\n"
148 " Return a quaternion representation of the euler.\n"
150 " :return: Quaternion representation of the euler.\n"
151 " :rtype: :class:`Quaternion`\n");
168 ".. method:: to_matrix()\n"
170 " Return a matrix representation of the euler.\n"
172 " :return: A 3x3 rotation matrix representation of the euler.\n"
173 " :rtype: :class:`Matrix`\n");
190 ".. method:: zero()\n"
192 " Set all values to zero.\n");
210 Euler_rotate_axis_doc,
211 ".. method:: rotate_axis(axis, angle)\n"
213 " Rotates the euler a certain amount and returning a unique euler rotation\n"
214 " (no 720 degree pitches).\n"
216 " :arg axis: single character in ['X, 'Y', 'Z'].\n"
218 " :arg angle: angle in radians.\n"
219 " :type angle: float\n");
225 if (!PyArg_ParseTuple(args,
"Cf:rotate_axis", &axis, &angle)) {
226 PyErr_SetString(PyExc_TypeError,
227 "Euler.rotate_axis(): "
228 "expected an axis 'X', 'Y', 'Z' and an angle (float)");
232 if (!
ELEM(axis,
'X',
'Y',
'Z')) {
233 PyErr_SetString(PyExc_ValueError,
234 "Euler.rotate_axis(): "
235 "expected axis to be 'X', 'Y' or 'Z'");
253 ".. method:: rotate(other)\n"
255 " Rotates the euler by another mathutils value.\n"
257 " :arg other: rotation component of mathutils value\n"
258 " :type other: :class:`Euler` | :class:`Quaternion` | :class:`Matrix`\n");
261 float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
282 Euler_make_compatible_doc,
283 ".. method:: make_compatible(other)\n"
285 " Make this euler compatible with another,\n"
286 " so interpolating between them works as intended.\n"
288 " .. note:: the rotation order is not taken into account for this function.\n");
301 "euler.make_compatible(other), invalid 'other' arg") == -1)
316 ".. function:: copy()\n"
318 " Returns a copy of this euler.\n"
320 " :return: A copy of the euler.\n"
321 " :rtype: :class:`Euler`\n"
323 " .. note:: use this to get a copy of a wrapped euler with\n"
324 " no reference to the original data.\n");
349 PyObject *
ret, *tuple;
363#ifndef MATH_STANDALONE
375 "<Euler (x=%.4f, y=%.4f, z=%.4f), order='%s'>",
415 res = ok ? Py_False : Py_True;
422 res = Py_NotImplemented;
429 return Py_NewRef(res);
471 PyErr_SetString(PyExc_IndexError,
473 "array index out of range");
481 return PyFloat_FromDouble(
self->eul[i]);
493 f = PyFloat_AsDouble(value);
494 if (f == -1 && PyErr_Occurred()) {
495 PyErr_SetString(PyExc_TypeError,
496 "euler[attribute] = x: "
497 "assigned value not a number");
506 PyErr_SetString(PyExc_IndexError,
507 "euler[attribute] = x: "
508 "array assignment index out of range");
536 begin = std::min(begin, end);
538 tuple = PyTuple_New(end - begin);
540 PyTuple_SET_ITEM(tuple,
count - begin, PyFloat_FromDouble(
self->eul[
count]));
561 begin = std::min(begin, end);
569 if (size != (end - begin)) {
570 PyErr_SetString(PyExc_ValueError,
571 "euler[begin:end] = []: "
572 "size mismatch in slice assignment");
577 self->eul[begin + i] = eul[i];
587 if (PyIndex_Check(item)) {
589 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
590 if (i == -1 && PyErr_Occurred()) {
598 if (PySlice_Check(item)) {
599 Py_ssize_t start, stop, step, slicelength;
601 if (PySlice_GetIndicesEx(item,
EULER_SIZE, &start, &stop, &step, &slicelength) < 0) {
605 if (slicelength <= 0) {
606 return PyTuple_New(0);
612 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with eulers");
617 PyExc_TypeError,
"euler indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
624 if (PyIndex_Check(item)) {
625 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
626 if (i == -1 && PyErr_Occurred()) {
634 if (PySlice_Check(item)) {
635 Py_ssize_t start, stop, step, slicelength;
637 if (PySlice_GetIndicesEx(item,
EULER_SIZE, &start, &stop, &step, &slicelength) < 0) {
645 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with euler");
650 PyExc_TypeError,
"euler indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
690 "Euler axis angle in radians.\n"
708 "Euler rotation order.\n"
710 ":type: str in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']");
723 const char *order_str;
730 if (((order_str = PyUnicode_AsUTF8(value)) ==
nullptr) ||
773 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr}
782#if (defined(__GNUC__) && !defined(__clang__))
783# pragma GCC diagnostic push
784# pragma GCC diagnostic ignored "-Wcast-function-type"
788 {
"zero", (PyCFunction)
Euler_zero, METH_NOARGS, Euler_zero_doc},
789 {
"to_matrix", (PyCFunction)
Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc},
791 {
"rotate_axis", (PyCFunction)
Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc},
792 {
"rotate", (PyCFunction)
Euler_rotate, METH_O, Euler_rotate_doc},
794 {
"copy", (PyCFunction)
Euler_copy, METH_NOARGS, Euler_copy_doc},
795 {
"__copy__", (PyCFunction)
Euler_copy, METH_NOARGS, Euler_copy_doc},
796 {
"__deepcopy__", (PyCFunction)
Euler_deepcopy, METH_VARARGS, Euler_copy_doc},
800 {
nullptr,
nullptr, 0,
nullptr},
803#if (defined(__GNUC__) && !defined(__clang__))
804# pragma GCC diagnostic pop
813#ifdef MATH_STANDALONE
814# define Euler_str nullptr
820 ".. class:: Euler(angles, order='XYZ')\n"
822 " This object gives access to Eulers in Blender.\n"
824 " .. seealso:: `Euler angles <https://en.wikipedia.org/wiki/Euler_angles>`__ on Wikipedia.\n"
826 " :arg angles: (X, Y, Z) angles in radians.\n"
827 " :type angles: Sequence[float]\n"
828 " :arg order: Optional order of the angles, a permutation of ``XYZ``.\n"
829 " :type order: str\n");
831 PyVarObject_HEAD_INIT(
nullptr, 0)
850 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
882#ifdef MATH_STANDALONE
897 eul_alloc =
static_cast<float *
>(PyMem_Malloc(
EULER_SIZE *
sizeof(
float)));
898 if (
UNLIKELY(eul_alloc ==
nullptr)) {
899 PyErr_SetString(PyExc_MemoryError,
901 "problem allocating data");
907 self->eul = eul_alloc;
910 self->cb_user =
nullptr;
911 self->cb_type =
self->cb_subtype = 0;
924 PyMem_Free(eul_alloc);
927 return (PyObject *)
self;
937 self->cb_user =
nullptr;
938 self->cb_type =
self->cb_subtype = 0;
946 return (PyObject *)
self;
957 self->cb_user = cb_user;
958 self->cb_type = cb_type;
959 self->cb_subtype = cb_subtype;
961 PyObject_GC_Track(
self);
964 return (PyObject *)
self;
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
double double_round(double x, int ndigits)
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void rotate_eulO(float beul[3], short order, char axis, float angle)
void eulO_to_quat(float q[4], const float e[3], short order)
void mat3_to_compatible_eulO(float eul[3], const float oldrot[3], short order, const float mat[3][3])
void compatible_eul(float eul[3], const float oldrot[3])
void eulO_to_mat3(float M[3][3], const float e[3], short order)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
local_group_size(16, 16) .push_constant(Type b
int BaseMathObject_is_gc(BaseMathObject *self)
Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
void BaseMathObject_dealloc(BaseMathObject *self)
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
char BaseMathObject_is_valid_doc[]
char BaseMathObject_is_wrapped_doc[]
PyObject * BaseMathObject_owner_get(BaseMathObject *self, void *)
char BaseMathObject_is_frozen_doc[]
PyObject * mathutils_dynstr_to_py(DynStr *ds)
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
PyObject * BaseMathObject_is_frozen_get(BaseMathObject *self, void *)
PyObject * BaseMathObject_freeze(BaseMathObject *self)
PyObject * BaseMathObject_is_wrapped_get(BaseMathObject *self, void *)
char BaseMathObject_owner_doc[]
char BaseMathObject_freeze_doc[]
PyObject * BaseMathObject_is_valid_get(BaseMathObject *self, void *)
int BaseMathObject_clear(BaseMathObject *self)
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
#define BaseMath_ReadCallback_ForWrite(_self)
#define BaseMath_ReadIndexCallback(_self, _index)
#define BaseMath_WriteCallback(_self)
#define BASE_MATH_NEW(struct_name, root_type, base_type)
#define BaseMathObject_Prepare_ForHash(_self)
#define BASE_MATH_FLAG_DEFAULT
#define BaseMath_Prepare_ForWrite(_self)
#define BaseMath_ReadCallback(_self)
#define BaseMath_WriteIndexCallback(_self, _index)
static PyObject * Euler_copy(EulerObject *self)
static PyObject * Euler_to_tuple_ex(EulerObject *self, int ndigits)
static PySequenceMethods Euler_SeqMethods
static PyObject * Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq)
PyObject * Euler_CreatePyObject_wrap(float eul[3], const short order, PyTypeObject *base_type)
static PyObject * Euler_item(EulerObject *self, Py_ssize_t i)
static PyObject * Euler_zero(EulerObject *self)
short euler_order_from_string(const char *str, const char *error_prefix)
static PyObject * Euler_subscript(EulerObject *self, PyObject *item)
static PyObject * Euler_rotate(EulerObject *self, PyObject *value)
static const char * euler_order_str(EulerObject *self)
static Py_hash_t Euler_hash(EulerObject *self)
static PyObject * Euler_order_get(EulerObject *self, void *)
#define MAKE_ID3(a, b, c)
PyObject * Euler_CreatePyObject(const float eul[3], const short order, PyTypeObject *base_type)
static int Euler_axis_set(EulerObject *self, PyObject *value, void *type)
static PyObject * Euler_repr(EulerObject *self)
static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *value)
static int Euler_order_set(EulerObject *self, PyObject *value, void *)
static PyObject * Euler_str(EulerObject *self)
PyDoc_STRVAR(Euler_to_quaternion_doc, ".. method:: to_quaternion()\n" "\n" " Return a quaternion representation of the euler.\n" "\n" " :return: Quaternion representation of the euler.\n" " :rtype: :class:`Quaternion`\n")
static PyObject * Euler_richcmpr(PyObject *a, PyObject *b, int op)
static PyObject * Euler_deepcopy(EulerObject *self, PyObject *args)
static PyObject * Euler_make_compatible(EulerObject *self, PyObject *value)
static PyGetSetDef Euler_getseters[]
static Py_ssize_t Euler_len(EulerObject *)
static int Euler_ass_item(EulerObject *self, Py_ssize_t i, PyObject *value)
static PyObject * Euler_rotate_axis(EulerObject *self, PyObject *args)
static PyMappingMethods Euler_AsMapping
static PyObject * Euler_axis_get(EulerObject *self, void *type)
PyObject * Euler_CreatePyObject_cb(PyObject *cb_user, const short order, uchar cb_type, uchar cb_subtype)
static PyObject * Euler_slice(EulerObject *self, int begin, int end)
static PyMethodDef Euler_methods[]
static PyObject * Euler_to_matrix(EulerObject *self)
static PyObject * Euler_to_quaternion(EulerObject *self)
#define EulerObject_Check(v)
PyObject * Matrix_CreatePyObject(const float *mat, const ushort col_num, const ushort row_num, PyTypeObject *base_type)
PyObject * Quaternion_CreatePyObject(const float quat[4], PyTypeObject *base_type)
int PyC_CheckArgs_DeepCopy(PyObject *args)