diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-02-05 12:57:02 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-02-05 12:57:02 +0300 |
commit | 998198a041aebad75c31db19e6cd3d64b61f2b3c (patch) | |
tree | a152fd5b8dc40daf4aabaada15696fbf3e26f4ac /source/blender/python | |
parent | 8b52087d837ac035e2645c09ad780c45fccb9d89 (diff) |
mathutils rotate functions for Euler/Quaternion/Matrix/Vector types.
each accept Euler/Quaternion/Matrix types.
eg:
Euler.rotate(Quaternion(axis, angle))
Vector.rotate(Euler((pi/2, 0, 0)))
matrix.resize_4x4() and euler.make_compatible() were still returning an instance of themselves, now return None.
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/generic/mathutils.c | 44 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils.h | 1 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_euler.c | 40 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_matrix.c | 43 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_matrix.h | 2 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_quat.c | 31 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_vector.c | 38 |
7 files changed, 160 insertions, 39 deletions
diff --git a/source/blender/python/generic/mathutils.c b/source/blender/python/generic/mathutils.c index 25b1e458ae8..b3bff5cf67f 100644 --- a/source/blender/python/generic/mathutils.c +++ b/source/blender/python/generic/mathutils.c @@ -47,6 +47,7 @@ * - toEuler --> to_euler * - toQuat --> to_quat * - Vector.toTrackQuat --> Vector.to_track_quat + * - Vector.rotate(axis, angle) --> rotate(other), where other can be Euler/Quaternion/Matrix. * - Quaternion * Quaternion --> cross product (not dot product) * - Euler.rotate(angle, axis) --> Euler.rotate_axis(axis, angle) * - Euler.unique() *removed*, not a standard function only toggled different rotations. @@ -164,6 +165,49 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject * } } +int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix) +{ + if(EulerObject_Check(value)) { + if(!BaseMath_ReadCallback((BaseMathObject *)value)) { + return -1; + } + else { + eulO_to_mat3(rmat, ((EulerObject *)value)->eul, ((EulerObject *)value)->order); + return 0; + } + } + else if (QuaternionObject_Check(value)) { + if(!BaseMath_ReadCallback((BaseMathObject *)value)) { + return -1; + } + else { + float tquat[4]; + normalize_qt_qt(tquat, ((QuaternionObject *)value)->quat); + quat_to_mat3(rmat, tquat); + return 0; + } + } + else if (MatrixObject_Check(value)) { + if(!BaseMath_ReadCallback((BaseMathObject *)value)) { + return -1; + } + else if(((MatrixObject *)value)->colSize < 3 || ((MatrixObject *)value)->rowSize < 3) { + PyErr_Format(PyExc_ValueError, "%.200s: matrix must have minimum 3x3 dimensions", error_prefix); + return -1; + } + else { + matrix_as_3x3(rmat, (MatrixObject *)value); + normalize_m3(rmat); + return 0; + } + } + else { + PyErr_Format(PyExc_TypeError, "%.200s: expected a Euler, Quaternion or Matrix type, found %.200s", error_prefix, Py_TYPE(value)->tp_name); + return -1; + } +} + + //----------------------------------MATRIX FUNCTIONS-------------------- diff --git a/source/blender/python/generic/mathutils.h b/source/blender/python/generic/mathutils.h index 29ef52c77b0..07342f8144b 100644 --- a/source/blender/python/generic/mathutils.h +++ b/source/blender/python/generic/mathutils.h @@ -100,5 +100,6 @@ int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index); /* utility func */ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix); +int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix); #endif /* MATHUTILS_H */ diff --git a/source/blender/python/generic/mathutils_euler.c b/source/blender/python/generic/mathutils_euler.c index 8f6d7e8a182..7b5fbcb4b6f 100644 --- a/source/blender/python/generic/mathutils_euler.c +++ b/source/blender/python/generic/mathutils_euler.c @@ -180,8 +180,6 @@ static char Euler_rotate_axis_doc[] = " :type axis: string\n" " :arg angle: angle in radians.\n" " :type angle: float\n" -" :return: an instance of itself\n" -" :rtype: :class:`Euler`" ; static PyObject *Euler_rotate_axis(EulerObject * self, PyObject *args) { @@ -204,8 +202,35 @@ static PyObject *Euler_rotate_axis(EulerObject * self, PyObject *args) else rotate_eulO(self->eul, self->order, *axis, angle); (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject *)self; + + Py_RETURN_NONE; +} + +static char Euler_rotate_doc[] = +".. method:: rotate(other)\n" +"\n" +" Rotates the euler a by another mathutils value.\n" +"\n" +" :arg other: rotation component of mathutils value\n" +" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n" +; +static PyObject *Euler_rotate(EulerObject * self, PyObject *value) +{ + float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; + + if(!BaseMath_ReadCallback(self)) + return NULL; + + if(mathutils_any_to_rotmat(other_rmat, value, "euler.rotate(value)") == -1) + return NULL; + + eulO_to_mat3(self_rmat, self->eul, self->order); + mul_m3_m3m3(rmat, self_rmat, other_rmat); + + mat3_to_compatible_eulO(self->eul, self->eul, self->order, rmat); + + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } static char Euler_make_compatible_doc[] = @@ -215,8 +240,6 @@ static char Euler_make_compatible_doc[] = "\n" " :arg other: make compatible with this rotation.\n" " :type other: :class:`Euler`\n" -" :return: an instance of itself.\n" -" :rtype: :class:`Euler`\n" "\n" " .. note:: the rotation order is not taken into account for this function.\n" ; @@ -233,8 +256,8 @@ static PyObject *Euler_make_compatible(EulerObject * self, PyObject *value) compatible_eul(self->eul, teul); (void)BaseMath_WriteCallback(self); - Py_INCREF(self); - return (PyObject *)self; + + Py_RETURN_NONE; } //----------------------------Euler.rotate()----------------------- @@ -564,6 +587,7 @@ static struct PyMethodDef Euler_methods[] = { {"to_matrix", (PyCFunction) Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc}, {"to_quaternion", (PyCFunction) Euler_to_quaternion, METH_NOARGS, Euler_to_quaternion_doc}, {"rotate_axis", (PyCFunction) Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc}, + {"rotate", (PyCFunction) Euler_rotate, METH_O, Euler_rotate_doc}, {"make_compatible", (PyCFunction) Euler_make_compatible, METH_O, Euler_make_compatible_doc}, {"__copy__", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc}, {"copy", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc}, diff --git a/source/blender/python/generic/mathutils_matrix.c b/source/blender/python/generic/mathutils_matrix.c index 8f8d3267cc6..fe5503afdbe 100644 --- a/source/blender/python/generic/mathutils_matrix.c +++ b/source/blender/python/generic/mathutils_matrix.c @@ -608,7 +608,7 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); } -static void matrix_as_3x3(float mat[3][3], MatrixObject *self) +void matrix_as_3x3(float mat[3][3], MatrixObject *self) { copy_v3_v3(mat[0], self->matrix[0]); copy_v3_v3(mat[1], self->matrix[1]); @@ -733,9 +733,6 @@ static char Matrix_resize_4x4_doc[] = ".. method:: resize_4x4()\n" "\n" " Resize the matrix to 4x4.\n" -"\n" -" :return: an instance of itself.\n" -" :rtype: :class:`Matrix`\n" ; static PyObject *Matrix_resize_4x4(MatrixObject *self) { @@ -785,8 +782,7 @@ static PyObject *Matrix_resize_4x4(MatrixObject *self) self->rowSize = 4; self->colSize = 4; - Py_INCREF(self); - return (PyObject *)self; + Py_RETURN_NONE; } static char Matrix_to_4x4_doc[] = @@ -976,6 +972,40 @@ static PyObject *Matrix_inverted(MatrixObject *self) MATRIX_APPLY_TO_COPY(Matrix_invert, self); } +static char Matrix_rotate_doc[] = +".. method:: rotate(other)\n" +"\n" +" Rotates the matrix a by another mathutils value.\n" +"\n" +" :arg other: rotation component of mathutils value\n" +" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n" +"\n" +" .. note:: If any of the columns are not unit length this may not have desired results.\n" +; +static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value) +{ + float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; + + if(!BaseMath_ReadCallback(self)) + return NULL; + + if(mathutils_any_to_rotmat(other_rmat, value, "matrix.rotate(value)") == -1) + return NULL; + + if(self->colSize != 3 || self->rowSize != 3) { + PyErr_SetString(PyExc_ValueError, "Matrix must have 3x3 dimensions"); + return NULL; + } + + matrix_as_3x3(self_rmat, self); + mul_m3_m3m3(rmat, self_rmat, other_rmat); + + copy_m3_m3((float (*)[3])(self->contigPtr), rmat); + + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; +} + /*---------------------------Matrix.decompose() ---------------------*/ static char Matrix_decompose_doc[] = ".. method:: decompose()\n" @@ -1733,6 +1763,7 @@ static struct PyMethodDef Matrix_methods[] = { // TODO. {"resize_3x3", (PyCFunction) Matrix_resize3x3, METH_NOARGS, Matrix_resize3x3_doc}, {"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc}, {"resize_4x4", (PyCFunction) Matrix_resize_4x4, METH_NOARGS, Matrix_resize_4x4_doc}, + {"rotate", (PyCFunction) Matrix_rotate, METH_O, Matrix_rotate_doc}, /* return converted representation */ {"to_euler", (PyCFunction) Matrix_to_euler, METH_VARARGS, Matrix_to_euler_doc}, diff --git a/source/blender/python/generic/mathutils_matrix.h b/source/blender/python/generic/mathutils_matrix.h index 4d477818171..125846e1ddd 100644 --- a/source/blender/python/generic/mathutils_matrix.h +++ b/source/blender/python/generic/mathutils_matrix.h @@ -55,4 +55,6 @@ PyObject *newMatrixObject_cb(PyObject *user, int rowSize, int colSize, int cb_ty extern int mathutils_matrix_vector_cb_index; extern struct Mathutils_Callback mathutils_matrix_vector_cb; +void matrix_as_3x3(float mat[3][3], MatrixObject *self); + #endif /* MATHUTILS_MATRIX_H */ diff --git a/source/blender/python/generic/mathutils_quat.c b/source/blender/python/generic/mathutils_quat.c index c7d4fd186a4..e5234e504be 100644 --- a/source/blender/python/generic/mathutils_quat.c +++ b/source/blender/python/generic/mathutils_quat.c @@ -256,6 +256,36 @@ static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args) return newQuaternionObject(quat, Py_NEW, Py_TYPE(self)); } +static char Quaternion_rotate_doc[] = +".. method:: rotate(other)\n" +"\n" +" Rotates the quaternion a by another mathutils value.\n" +"\n" +" :arg other: rotation component of mathutils value\n" +" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n" +; +static PyObject *Quaternion_rotate(QuaternionObject *self, PyObject *value) +{ + float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; + float tquat[4], length; + + if(!BaseMath_ReadCallback(self)) + return NULL; + + if(mathutils_any_to_rotmat(other_rmat, value, "quaternion.rotate(value)") == -1) + return NULL; + + length= normalize_qt_qt(tquat, self->quat); + quat_to_mat3(self_rmat, tquat); + mul_m3_m3m3(rmat, self_rmat, other_rmat); + + mat3_to_quat(self->quat, rmat); + mul_qt_fl(self->quat, length); /* maintain length after rotating */ + + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; +} + //----------------------------Quaternion.normalize()---------------- //normalize the axis of rotation of [theta,vector] static char Quaternion_normalize_doc[] = @@ -962,6 +992,7 @@ static struct PyMethodDef Quaternion_methods[] = { {"dot", (PyCFunction) Quaternion_dot, METH_O, Quaternion_dot_doc}, {"difference", (PyCFunction) Quaternion_difference, METH_O, Quaternion_difference_doc}, {"slerp", (PyCFunction) Quaternion_slerp, METH_VARARGS, Quaternion_slerp_doc}, + {"rotate", (PyCFunction) Quaternion_rotate, METH_VARARGS, Quaternion_rotate_doc}, {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, diff --git a/source/blender/python/generic/mathutils_vector.c b/source/blender/python/generic/mathutils_vector.c index c39d42e31df..da0da6ddba6 100644 --- a/source/blender/python/generic/mathutils_vector.c +++ b/source/blender/python/generic/mathutils_vector.c @@ -715,44 +715,32 @@ static PyObject *Vector_lerp(VectorObject *self, PyObject *args) } static char Vector_rotate_doc[] = -".. function:: rotate(axis, angle)\n" +".. function:: rotate(other)\n" "\n" -" Return vector rotated around axis by angle.\n" +" Return vector by a rotation value.\n" "\n" -" :arg axis: rotation axis.\n" -" :type axis: :class:`Vector`\n" -" :arg angle: angle in radians.\n" -" :type angle: float\n" -" :return: an instance of itself\n" -" :rtype: :class:`Vector`\n" +" :arg other: rotation component of mathutils value\n" +" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n" ; -static PyObject *Vector_rotate(VectorObject *self, PyObject *args) +static PyObject *Vector_rotate(VectorObject *self, PyObject *value) { - PyObject *value; - float angle, vec[3], tvec[3]; + float other_rmat[3][3]; if(!BaseMath_ReadCallback(self)) return NULL; - if(!PyArg_ParseTuple(args, "Of:rotate", &value, &angle)){ - PyErr_SetString(PyExc_TypeError, "vec.rotate(axis, angle): expected 3D axis (Vector) and angle (float)"); + if(mathutils_any_to_rotmat(other_rmat, value, "vector.rotate(value)") == -1) return NULL; - } - if(self->size != 3) { - PyErr_SetString(PyExc_AttributeError, "vec.rotate(axis, angle): expects both vectors to be 3D"); + if(self->size < 3) { + PyErr_SetString(PyExc_ValueError, "Vector must be 3D or 4D"); return NULL; } - if(mathutils_array_parse(tvec, 3, 3, value, "vector.rotate(axis, angle), invalid 'axis' arg") == -1) - return NULL; + mul_m3_v3(other_rmat, self->vec); - rotate_v3_v3v3fl(vec, self->vec, tvec, angle); - - copy_v3_v3(self->vec, vec); - - Py_INCREF(self); - return (PyObject *)self; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } static char Vector_copy_doc[] = @@ -2119,7 +2107,7 @@ static struct PyMethodDef Vector_methods[] = { {"difference", (PyCFunction) Vector_difference, METH_O, Vector_difference_doc}, {"project", (PyCFunction) Vector_project, METH_O, Vector_project_doc}, {"lerp", (PyCFunction) Vector_lerp, METH_VARARGS, Vector_lerp_doc}, - {"rotate", (PyCFunction) Vector_rotate, METH_VARARGS, Vector_rotate_doc}, + {"rotate", (PyCFunction) Vector_rotate, METH_O, Vector_rotate_doc}, {"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc}, {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL}, |