diff options
Diffstat (limited to 'source/blender/python/mathutils/mathutils_Quaternion.c')
-rw-r--r-- | source/blender/python/mathutils/mathutils_Quaternion.c | 569 |
1 files changed, 367 insertions, 202 deletions
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 7b51154f0d0..6994a313237 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -26,9 +26,49 @@ static void quat__axis_angle_sanitize(float axis[3], float *angle); static PyObject *Quaternion_copy(QuaternionObject *self); static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args); -/* -----------------------------METHODS------------------------------ */ +/* -------------------------------------------------------------------- */ +/** \name Utilities + * \{ */ -/* NOTE: BaseMath_ReadCallback must be called beforehand. */ +static PyObject *quat__apply_to_copy(PyObject *(*quat_func)(QuaternionObject *), + QuaternionObject *self) +{ + PyObject *ret = Quaternion_copy(self); + PyObject *ret_dummy = quat_func((QuaternionObject *)ret); + if (ret_dummy) { + Py_DECREF(ret_dummy); + return ret; + } + /* error */ + Py_DECREF(ret); + return NULL; +} + +/** Axis vector suffers from precision errors, use this function to ensure. */ +static void quat__axis_angle_sanitize(float axis[3], float *angle) +{ + if (axis) { + if (is_zero_v3(axis) || !isfinite(axis[0]) || !isfinite(axis[1]) || !isfinite(axis[2])) { + axis[0] = 1.0f; + axis[1] = 0.0f; + axis[2] = 0.0f; + } + else if (EXPP_FloatsAreEqual(axis[0], 0.0f, 10) && EXPP_FloatsAreEqual(axis[1], 0.0f, 10) && + EXPP_FloatsAreEqual(axis[2], 0.0f, 10)) { + axis[0] = 1.0f; + } + } + + if (angle) { + if (!isfinite(*angle)) { + *angle = 0.0f; + } + } +} + +/** + * \note #BaseMath_ReadCallback must be called beforehand. + */ static PyObject *Quaternion_to_tuple_ext(QuaternionObject *self, int ndigits) { PyObject *ret; @@ -50,6 +90,72 @@ static PyObject *Quaternion_to_tuple_ext(QuaternionObject *self, int ndigits) return ret; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: `__new__` / `mathutils.Quaternion()` + * \{ */ + +static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *seq = NULL; + double angle = 0.0f; + float quat[QUAT_SIZE]; + unit_qt(quat); + + if (kwds && PyDict_Size(kwds)) { + PyErr_SetString(PyExc_TypeError, + "mathutils.Quaternion(): " + "takes no keyword args"); + return NULL; + } + + if (!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle)) { + return NULL; + } + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 1: { + int size; + + if ((size = mathutils_array_parse(quat, 3, QUAT_SIZE, seq, "mathutils.Quaternion()")) == + -1) { + return NULL; + } + + if (size == 4) { + /* 4d: Quaternion (common case) */ + } + else { + /* 3d: Interpret as exponential map */ + BLI_assert(size == 3); + expmap_to_quat(quat, quat); + } + + break; + } + case 2: { + float axis[3]; + if (mathutils_array_parse(axis, 3, 3, seq, "mathutils.Quaternion()") == -1) { + return NULL; + } + angle = angle_wrap_rad(angle); /* clamp because of precision issues */ + axis_angle_to_quat(quat, axis, angle); + break; + /* PyArg_ParseTuple assures no more than 2 */ + } + } + return Quaternion_CreatePyObject(quat, type); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: To Euler + * \{ */ + PyDoc_STRVAR(Quaternion_to_euler_doc, ".. method:: to_euler(order, euler_compat)\n" "\n" @@ -114,6 +220,12 @@ static PyObject *Quaternion_to_euler(QuaternionObject *self, PyObject *args) return Euler_CreatePyObject(eul, order, NULL); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: To Matrix + * \{ */ + PyDoc_STRVAR(Quaternion_to_matrix_doc, ".. method:: to_matrix()\n" "\n" @@ -133,6 +245,12 @@ static PyObject *Quaternion_to_matrix(QuaternionObject *self) return Matrix_CreatePyObject(mat, 3, 3, NULL); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: To Axis/Angle + * \{ */ + PyDoc_STRVAR(Quaternion_to_axis_angle_doc, ".. method:: to_axis_angle()\n" "\n" @@ -163,6 +281,12 @@ static PyObject *Quaternion_to_axis_angle(QuaternionObject *self) return ret; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: To Swing/Twist + * \{ */ + PyDoc_STRVAR(Quaternion_to_swing_twist_doc, ".. method:: to_swing_twist(axis)\n" "\n" @@ -207,6 +331,12 @@ static PyObject *Quaternion_to_swing_twist(QuaternionObject *self, PyObject *axi return ret; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: To Exponential Map + * \{ */ + PyDoc_STRVAR( Quaternion_to_exponential_map_doc, ".. method:: to_exponential_map()\n" @@ -232,6 +362,12 @@ static PyObject *Quaternion_to_exponential_map(QuaternionObject *self) return Vector_CreatePyObject(expmap, 3, NULL); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: Cross Product + * \{ */ + PyDoc_STRVAR(Quaternion_cross_doc, ".. method:: cross(other)\n" "\n" @@ -259,6 +395,12 @@ static PyObject *Quaternion_cross(QuaternionObject *self, PyObject *value) return Quaternion_CreatePyObject(quat, Py_TYPE(self)); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: Dot Product + * \{ */ + PyDoc_STRVAR(Quaternion_dot_doc, ".. method:: dot(other)\n" "\n" @@ -285,6 +427,12 @@ static PyObject *Quaternion_dot(QuaternionObject *self, PyObject *value) return PyFloat_FromDouble(dot_qtqt(self->quat, tquat)); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: Rotation Difference + * \{ */ + PyDoc_STRVAR(Quaternion_rotation_difference_doc, ".. function:: rotation_difference(other)\n" "\n" @@ -315,6 +463,12 @@ static PyObject *Quaternion_rotation_difference(QuaternionObject *self, PyObject return Quaternion_CreatePyObject(quat, Py_TYPE(self)); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: Spherical Interpolation (slerp) + * \{ */ + PyDoc_STRVAR(Quaternion_slerp_doc, ".. function:: slerp(other, factor)\n" "\n" @@ -360,6 +514,12 @@ static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args) return Quaternion_CreatePyObject(quat, Py_TYPE(self)); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: Rotate + * \{ */ + PyDoc_STRVAR(Quaternion_rotate_doc, ".. method:: rotate(other)\n" "\n" @@ -423,9 +583,15 @@ static PyObject *Quaternion_make_compatible(QuaternionObject *self, PyObject *va Py_RETURN_NONE; } -/* ----------------------------Quaternion.normalize()---------------- */ -/* Normalize the quaternion. This may change the angle as well as the - * rotation axis, as all of (w, x, y, z) are scaled. */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: Normalize + * + * Normalize the quaternion. This may change the angle as well as the + * rotation axis, as all of (w, x, y, z) are scaled. + * \{ */ + PyDoc_STRVAR(Quaternion_normalize_doc, ".. function:: normalize()\n" "\n" @@ -453,6 +619,15 @@ static PyObject *Quaternion_normalized(QuaternionObject *self) return quat__apply_to_copy(Quaternion_normalize, self); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: Invert + * + * Normalize the quaternion. This may change the angle as well as the + * rotation axis, as all of (w, x, y, z) are scaled. + * \{ */ + PyDoc_STRVAR(Quaternion_invert_doc, ".. function:: invert()\n" "\n" @@ -480,6 +655,12 @@ static PyObject *Quaternion_inverted(QuaternionObject *self) return quat__apply_to_copy(Quaternion_invert, self); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: Set Identity + * \{ */ + PyDoc_STRVAR(Quaternion_identity_doc, ".. function:: identity()\n" "\n" @@ -498,6 +679,12 @@ static PyObject *Quaternion_identity(QuaternionObject *self) Py_RETURN_NONE; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: Negate + * \{ */ + PyDoc_STRVAR(Quaternion_negate_doc, ".. function:: negate()\n" "\n" @@ -516,6 +703,12 @@ static PyObject *Quaternion_negate(QuaternionObject *self) Py_RETURN_NONE; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: Conjugate + * \{ */ + PyDoc_STRVAR(Quaternion_conjugate_doc, ".. function:: conjugate()\n" "\n" @@ -543,6 +736,12 @@ static PyObject *Quaternion_conjugated(QuaternionObject *self) return quat__apply_to_copy(Quaternion_conjugate, self); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Methods: Copy/Deep-Copy + * \{ */ + PyDoc_STRVAR(Quaternion_copy_doc, ".. function:: copy()\n" "\n" @@ -569,7 +768,12 @@ static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args) return Quaternion_copy(self); } -/* print the object to screen */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: `__repr__` & `__str__` + * \{ */ + static PyObject *Quaternion_repr(QuaternionObject *self) { PyObject *ret, *tuple; @@ -608,6 +812,12 @@ static PyObject *Quaternion_str(QuaternionObject *self) } #endif +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: Rich Compare + * \{ */ + static PyObject *Quaternion_richcmpr(PyObject *a, PyObject *b, int op) { PyObject *res; @@ -646,6 +856,12 @@ static PyObject *Quaternion_richcmpr(PyObject *a, PyObject *b, int op) return Py_INCREF_RET(res); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: Hash (`__hash__`) + * \{ */ + static Py_hash_t Quaternion_hash(QuaternionObject *self) { if (BaseMath_ReadCallback(self) == -1) { @@ -659,15 +875,19 @@ static Py_hash_t Quaternion_hash(QuaternionObject *self) return mathutils_array_hash(self->quat, QUAT_SIZE); } -/* ---------------------SEQUENCE PROTOCOLS------------------------ */ -/* ----------------------------len(object)------------------------ */ -/* sequence length */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: Sequence & Mapping Protocols Implementation + * \{ */ + +/** Sequence length: `len(object)`. */ static int Quaternion_len(QuaternionObject *UNUSED(self)) { return QUAT_SIZE; } -/* ----------------------------object[]--------------------------- */ -/* sequence accessor (get) */ + +/** Sequence accessor (get): `x = object[i]`. */ static PyObject *Quaternion_item(QuaternionObject *self, int i) { if (i < 0) { @@ -687,8 +907,8 @@ static PyObject *Quaternion_item(QuaternionObject *self, int i) return PyFloat_FromDouble(self->quat[i]); } -/* ----------------------------object[]------------------------- */ -/* sequence accessor (set) */ + +/** Sequence accessor (set): `object[i] = x`. */ static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob) { float f; @@ -724,8 +944,8 @@ static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob) return 0; } -/* ----------------------------object[z:y]------------------------ */ -/* sequence slice (get) */ + +/** Sequence slice accessor (get): `x = object[i:j]`. */ static PyObject *Quaternion_slice(QuaternionObject *self, int begin, int end) { PyObject *tuple; @@ -749,8 +969,8 @@ static PyObject *Quaternion_slice(QuaternionObject *self, int begin, int end) return tuple; } -/* ----------------------------object[z:y]------------------------ */ -/* sequence slice (set) */ + +/** Sequence slice accessor (set): `object[i:j] = x`. */ static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyObject *seq) { int i, size; @@ -779,7 +999,7 @@ static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyOb return -1; } - /* parsed well - now set in vector */ + /* Parsed well, now set in vector. */ for (i = 0; i < size; i++) { self->quat[begin + i] = quat[i]; } @@ -788,6 +1008,7 @@ static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyOb return 0; } +/** Sequence generic subscript (get): `x = object[...]`. */ static PyObject *Quaternion_subscript(QuaternionObject *self, PyObject *item) { if (PyIndex_Check(item)) { @@ -824,6 +1045,7 @@ static PyObject *Quaternion_subscript(QuaternionObject *self, PyObject *item) return NULL; } +/** Sequence generic subscript (set): `object[...] = x`. */ static int Quaternion_ass_subscript(QuaternionObject *self, PyObject *item, PyObject *value) { if (PyIndex_Check(item)) { @@ -856,9 +1078,13 @@ static int Quaternion_ass_subscript(QuaternionObject *self, PyObject *item, PyOb return -1; } -/* ------------------------NUMERIC PROTOCOLS---------------------- */ -/* ------------------------obj + obj------------------------------ */ -/* addition */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: Numeric Protocol Implementation + * \{ */ + +/** Addition: `object + object`. */ static PyObject *Quaternion_add(PyObject *q1, PyObject *q2) { float quat[QUAT_SIZE]; @@ -882,8 +1108,8 @@ static PyObject *Quaternion_add(PyObject *q1, PyObject *q2) add_qt_qtqt(quat, quat1->quat, quat2->quat, 1.0f); return Quaternion_CreatePyObject(quat, Py_TYPE(q1)); } -/* ------------------------obj - obj------------------------------ */ -/* subtraction */ + +/** Subtraction: `object - object`. */ static PyObject *Quaternion_sub(PyObject *q1, PyObject *q2) { int x; @@ -921,8 +1147,7 @@ static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar) return Quaternion_CreatePyObject(tquat, Py_TYPE(quat)); } -/*------------------------obj * obj------------------------------ - * multiplication */ +/** Multiplication (element-wise or scalar): `object * object`. */ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2) { float scalar; @@ -965,8 +1190,8 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2) Py_TYPE(q2)->tp_name); return NULL; } -/*------------------------obj *= obj------------------------------ - * in-place multiplication */ + +/** Multiplication in-place (element-wise or scalar): `object *= object`. */ static PyObject *Quaternion_imul(PyObject *q1, PyObject *q2) { float scalar; @@ -1005,8 +1230,8 @@ static PyObject *Quaternion_imul(PyObject *q1, PyObject *q2) Py_INCREF(q1); return q1; } -/*------------------------obj @ obj------------------------------ - * quaternion multiplication */ + +/** Multiplication (quaternion multiply): `object @ object`. */ static PyObject *Quaternion_matmul(PyObject *q1, PyObject *q2) { float quat[QUAT_SIZE]; @@ -1060,8 +1285,8 @@ static PyObject *Quaternion_matmul(PyObject *q1, PyObject *q2) Py_TYPE(q2)->tp_name); return NULL; } -/*------------------------obj @= obj------------------------------ - * in-place quaternion multiplication */ + +/** Multiplication in-place (quaternion multiply): `object @= object`. */ static PyObject *Quaternion_imatmul(PyObject *q1, PyObject *q2) { float quat[QUAT_SIZE]; @@ -1098,8 +1323,7 @@ static PyObject *Quaternion_imatmul(PyObject *q1, PyObject *q2) return q1; } -/* -obj - * Returns the negative of this object. */ +/** Negative (returns the negative of this object): `-object`. */ static PyObject *Quaternion_neg(QuaternionObject *self) { float tquat[QUAT_SIZE]; @@ -1112,18 +1336,23 @@ static PyObject *Quaternion_neg(QuaternionObject *self) return Quaternion_CreatePyObject(tquat, Py_TYPE(self)); } -/* -----------------PROTOCOL DECLARATIONS-------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: Protocol Declarations + * \{ */ + static PySequenceMethods Quaternion_SeqMethods = { - (lenfunc)Quaternion_len, /* sq_length */ - (binaryfunc)NULL, /* sq_concat */ - (ssizeargfunc)NULL, /* sq_repeat */ - (ssizeargfunc)Quaternion_item, /* sq_item */ - (ssizessizeargfunc)NULL, /* sq_slice, deprecated */ - (ssizeobjargproc)Quaternion_ass_item, /* sq_ass_item */ - (ssizessizeobjargproc)NULL, /* sq_ass_slice, deprecated */ - (objobjproc)NULL, /* sq_contains */ - (binaryfunc)NULL, /* sq_inplace_concat */ - (ssizeargfunc)NULL, /* sq_inplace_repeat */ + (lenfunc)Quaternion_len, /*sq_length*/ + (binaryfunc)NULL, /*sq_concat*/ + (ssizeargfunc)NULL, /*sq_repeat*/ + (ssizeargfunc)Quaternion_item, /*sq_item*/ + (ssizessizeargfunc)NULL, /*sq_slice(deprecated)*/ + (ssizeobjargproc)Quaternion_ass_item, /*sq_ass_item*/ + (ssizessizeobjargproc)NULL, /*sq_ass_slice(deprecated)*/ + (objobjproc)NULL, /*sq_contains*/ + (binaryfunc)NULL, /*sq_inplace_concat*/ + (ssizeargfunc)NULL, /*sq_inplace_repeat*/ }; static PyMappingMethods Quaternion_AsMapping = { @@ -1152,25 +1381,31 @@ static PyNumberMethods Quaternion_NumMethods = { NULL, /*nb_int*/ NULL, /*nb_reserved*/ NULL, /*nb_float*/ - NULL, /* nb_inplace_add */ - NULL, /* nb_inplace_subtract */ - (binaryfunc)Quaternion_imul, /* nb_inplace_multiply */ - NULL, /* nb_inplace_remainder */ - NULL, /* nb_inplace_power */ - NULL, /* nb_inplace_lshift */ - NULL, /* nb_inplace_rshift */ - NULL, /* nb_inplace_and */ - NULL, /* nb_inplace_xor */ - NULL, /* nb_inplace_or */ - NULL, /* nb_floor_divide */ - NULL, /* nb_true_divide */ - NULL, /* nb_inplace_floor_divide */ - NULL, /* nb_inplace_true_divide */ - NULL, /* nb_index */ - (binaryfunc)Quaternion_matmul, /* nb_matrix_multiply */ - (binaryfunc)Quaternion_imatmul, /* nb_inplace_matrix_multiply */ + NULL, /*nb_inplace_add*/ + NULL, /*nb_inplace_subtract*/ + (binaryfunc)Quaternion_imul, /*nb_inplace_multiply*/ + NULL, /*nb_inplace_remainder*/ + NULL, /*nb_inplace_power*/ + NULL, /*nb_inplace_lshift*/ + NULL, /*nb_inplace_rshift*/ + NULL, /*nb_inplace_and*/ + NULL, /*nb_inplace_xor*/ + NULL, /*nb_inplace_or*/ + NULL, /*nb_floor_divide*/ + NULL, /*nb_true_divide*/ + NULL, /*nb_inplace_floor_divide*/ + NULL, /*nb_inplace_true_divide*/ + NULL, /*nb_index*/ + (binaryfunc)Quaternion_matmul, /*nb_matrix_multiply*/ + (binaryfunc)Quaternion_imatmul, /*nb_inplace_matrix_multiply*/ }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: Get/Set Item Implementation + * \{ */ + PyDoc_STRVAR(Quaternion_axis_doc, "Quaternion axis value.\n\n:type: float"); static PyObject *Quaternion_axis_get(QuaternionObject *self, void *type) { @@ -1300,98 +1535,69 @@ static int Quaternion_axis_vector_set(QuaternionObject *self, return 0; } -/* ----------------------------------mathutils.Quaternion() -------------- */ -static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *seq = NULL; - double angle = 0.0f; - float quat[QUAT_SIZE]; - unit_qt(quat); - - if (kwds && PyDict_Size(kwds)) { - PyErr_SetString(PyExc_TypeError, - "mathutils.Quaternion(): " - "takes no keyword args"); - return NULL; - } - - if (!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle)) { - return NULL; - } - - switch (PyTuple_GET_SIZE(args)) { - case 0: - break; - case 1: { - int size; - - if ((size = mathutils_array_parse(quat, 3, QUAT_SIZE, seq, "mathutils.Quaternion()")) == - -1) { - return NULL; - } +/** \} */ - if (size == 4) { - /* 4d: Quaternion (common case) */ - } - else { - /* 3d: Interpret as exponential map */ - BLI_assert(size == 3); - expmap_to_quat(quat, quat); - } - - break; - } - case 2: { - float axis[3]; - if (mathutils_array_parse(axis, 3, 3, seq, "mathutils.Quaternion()") == -1) { - return NULL; - } - angle = angle_wrap_rad(angle); /* clamp because of precision issues */ - axis_angle_to_quat(quat, axis, angle); - break; - /* PyArg_ParseTuple assures no more than 2 */ - } - } - return Quaternion_CreatePyObject(quat, type); -} +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: Get/Set Item Definitions + * \{ */ -static PyObject *quat__apply_to_copy(PyObject *(*quat_func)(QuaternionObject *), - QuaternionObject *self) -{ - PyObject *ret = Quaternion_copy(self); - PyObject *ret_dummy = quat_func((QuaternionObject *)ret); - if (ret_dummy) { - Py_DECREF(ret_dummy); - return ret; - } - /* error */ - Py_DECREF(ret); - return NULL; -} +static PyGetSetDef Quaternion_getseters[] = { + {"w", + (getter)Quaternion_axis_get, + (setter)Quaternion_axis_set, + Quaternion_axis_doc, + (void *)0}, + {"x", + (getter)Quaternion_axis_get, + (setter)Quaternion_axis_set, + Quaternion_axis_doc, + (void *)1}, + {"y", + (getter)Quaternion_axis_get, + (setter)Quaternion_axis_set, + Quaternion_axis_doc, + (void *)2}, + {"z", + (getter)Quaternion_axis_get, + (setter)Quaternion_axis_set, + Quaternion_axis_doc, + (void *)3}, + {"magnitude", (getter)Quaternion_magnitude_get, (setter)NULL, Quaternion_magnitude_doc, NULL}, + {"angle", + (getter)Quaternion_angle_get, + (setter)Quaternion_angle_set, + Quaternion_angle_doc, + NULL}, + {"axis", + (getter)Quaternion_axis_vector_get, + (setter)Quaternion_axis_vector_set, + Quaternion_axis_vector_doc, + NULL}, + {"is_wrapped", + (getter)BaseMathObject_is_wrapped_get, + (setter)NULL, + BaseMathObject_is_wrapped_doc, + NULL}, + {"is_frozen", + (getter)BaseMathObject_is_frozen_get, + (setter)NULL, + BaseMathObject_is_frozen_doc, + NULL}, + {"is_valid", + (getter)BaseMathObject_is_valid_get, + (setter)NULL, + BaseMathObject_is_valid_doc, + NULL}, + {"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ +}; -/* axis vector suffers from precision errors, use this function to ensure */ -static void quat__axis_angle_sanitize(float axis[3], float *angle) -{ - if (axis) { - if (is_zero_v3(axis) || !isfinite(axis[0]) || !isfinite(axis[1]) || !isfinite(axis[2])) { - axis[0] = 1.0f; - axis[1] = 0.0f; - axis[2] = 0.0f; - } - else if (EXPP_FloatsAreEqual(axis[0], 0.0f, 10) && EXPP_FloatsAreEqual(axis[1], 0.0f, 10) && - EXPP_FloatsAreEqual(axis[2], 0.0f, 10)) { - axis[0] = 1.0f; - } - } +/** \} */ - if (angle) { - if (!isfinite(*angle)) { - *angle = 0.0f; - } - } -} +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: Method Definitions + * \{ */ -/* -----------------------METHOD DEFINITIONS ---------------------- */ static struct PyMethodDef Quaternion_methods[] = { /* In place only. */ {"identity", (PyCFunction)Quaternion_identity, METH_NOARGS, Quaternion_identity_doc}, @@ -1446,61 +1652,12 @@ static struct PyMethodDef Quaternion_methods[] = { {NULL, NULL, 0, NULL}, }; -/*****************************************************************************/ -/* Python attributes get/set structure: */ -/*****************************************************************************/ -static PyGetSetDef Quaternion_getseters[] = { - {"w", - (getter)Quaternion_axis_get, - (setter)Quaternion_axis_set, - Quaternion_axis_doc, - (void *)0}, - {"x", - (getter)Quaternion_axis_get, - (setter)Quaternion_axis_set, - Quaternion_axis_doc, - (void *)1}, - {"y", - (getter)Quaternion_axis_get, - (setter)Quaternion_axis_set, - Quaternion_axis_doc, - (void *)2}, - {"z", - (getter)Quaternion_axis_get, - (setter)Quaternion_axis_set, - Quaternion_axis_doc, - (void *)3}, - {"magnitude", (getter)Quaternion_magnitude_get, (setter)NULL, Quaternion_magnitude_doc, NULL}, - {"angle", - (getter)Quaternion_angle_get, - (setter)Quaternion_angle_set, - Quaternion_angle_doc, - NULL}, - {"axis", - (getter)Quaternion_axis_vector_get, - (setter)Quaternion_axis_vector_set, - Quaternion_axis_vector_doc, - NULL}, - {"is_wrapped", - (getter)BaseMathObject_is_wrapped_get, - (setter)NULL, - BaseMathObject_is_wrapped_doc, - NULL}, - {"is_frozen", - (getter)BaseMathObject_is_frozen_get, - (setter)NULL, - BaseMathObject_is_frozen_doc, - NULL}, - {"is_valid", - (getter)BaseMathObject_is_valid_get, - (setter)NULL, - BaseMathObject_is_valid_doc, - NULL}, - {"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ -}; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: Python Object Definition + * \{ */ -/* ------------------PY_OBECT DEFINITION-------------------------- */ PyDoc_STRVAR(quaternion_doc, ".. class:: Quaternion([seq, [angle]])\n" "\n" @@ -1577,6 +1734,12 @@ PyTypeObject quaternion_Type = { NULL, /* tp_del */ }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Quaternion Type: C/API Constructors + * \{ */ + PyObject *Quaternion_CreatePyObject(const float quat[4], PyTypeObject *base_type) { QuaternionObject *self; @@ -1643,3 +1806,5 @@ PyObject *Quaternion_CreatePyObject_cb(PyObject *cb_user, uchar cb_type, uchar c return (PyObject *)self; } + +/** \} */ |