diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-08-11 20:40:36 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-08-11 20:40:36 +0400 |
commit | 556b615cf8eae8c656f2d2a0905564e5c0de98cc (patch) | |
tree | b95388a46c9e9692c92638747f5abc84d66fa6bf /source/blender | |
parent | ab8ccaa7098f6fee887f2a249fddada7864cd6c5 (diff) |
mathutils module methods only contained matrix constructors, move these to matrix class methods since this is acceptable in python. eg: dict.fromkeys() and groups them more logically.
mathutils.RotationMatrix -> mathutils.Matrix.Rotation
mathutils.ScaleMatrix -> mathutils.Matrix.Scale
mathutils.ShearMatrix -> mathutils.Matrix.Shear
mathutils.TranslationMatrix -> mathutils.Matrix.Translation
mathutils.OrthoProjectionMatrix -> mathutils.Matrix.OrthoProjection
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/python/generic/mathutils.c | 439 | ||||
-rw-r--r-- | source/blender/python/generic/mathutils_matrix.c | 439 |
2 files changed, 446 insertions, 432 deletions
diff --git a/source/blender/python/generic/mathutils.c b/source/blender/python/generic/mathutils.c index 2bfd9a6d0c6..ada5bac8c2a 100644 --- a/source/blender/python/generic/mathutils.c +++ b/source/blender/python/generic/mathutils.c @@ -46,6 +46,13 @@ * - Vector.toTrackQuat --> Vector.to_track_quat * - Quaternion * Quaternion --> cross product (not dot product) * + * moved into class functions. + * - Mathutils.RotationMatrix -> mathutils.Matrix.Rotation + * - Mathutils.ScaleMatrix -> mathutils.Matrix.Scale + * - Mathutils.ShearMatrix -> mathutils.Matrix.Shear + * - Mathutils.TranslationMatrix -> mathutils.Matrix.Translation + * - Mathutils.OrthoProjectionMatrix -> mathutils.Matrix.OrthoProjection + * * Moved to Geometry module: Intersect, TriangleArea, TriangleNormal, QuadNormal, LineIntersect */ @@ -94,434 +101,7 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject * } //----------------------------------MATRIX FUNCTIONS-------------------- -//----------------------------------mathutils.RotationMatrix() ---------- -//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. -static char M_Mathutils_RotationMatrix_doc[] = -".. function:: RotationMatrix(angle, size, axis)\n" -"\n" -" Create a matrix representing a rotation.\n" -"\n" -" :arg angle: The angle of rotation desired, in radians.\n" -" :type angle: float\n" -" :arg size: The size of the rotation matrix to construct [2, 4].\n" -" :type size: int\n" -" :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object (optional when size is 2).\n" -" :type axis: string or :class:`Vector`\n" -" :return: A new rotation matrix.\n" -" :rtype: :class:`Matrix`\n"; - -static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args) -{ - VectorObject *vec= NULL; - char *axis= NULL; - int matSize; - float angle = 0.0f; - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - - if(!PyArg_ParseTuple(args, "fi|O", &angle, &matSize, &vec)) { - PyErr_SetString(PyExc_TypeError, "mathutils.RotationMatrix(angle, size, axis): expected float int and a string or vector\n"); - return NULL; - } - - if(vec && !VectorObject_Check(vec)) { - axis= _PyUnicode_AsString((PyObject *)vec); - if(axis==NULL || axis[0]=='\0' || axis[1]!='\0' || axis[0] < 'X' || axis[0] > 'Z') { - PyErr_SetString(PyExc_TypeError, "mathutils.RotationMatrix(): 3rd argument axis value must be a 3D vector or a string in 'X', 'Y', 'Z'\n"); - return NULL; - } - else { - /* use the string */ - vec= NULL; - } - } - - while (angle<-(Py_PI*2)) - angle+=(Py_PI*2); - while (angle>(Py_PI*2)) - angle-=(Py_PI*2); - - if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); - return NULL; - } - if(matSize == 2 && (vec != NULL)) { - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): cannot create a 2x2 rotation matrix around arbitrary axis\n"); - return NULL; - } - if((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) { - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): please choose an axis of rotation for 3d and 4d matrices\n"); - return NULL; - } - if(vec) { - if(vec->size != 3) { - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): the vector axis must be a 3D vector\n"); - return NULL; - } - - if(!BaseMath_ReadCallback(vec)) - return NULL; - - } - /* check for valid vector/axis above */ - if(vec) { - axis_angle_to_mat3( (float (*)[3])mat,vec->vec, angle); - } - else if(matSize == 2) { - //2D rotation matrix - mat[0] = (float) cos (angle); - mat[1] = (float) sin (angle); - mat[2] = -((float) sin(angle)); - mat[3] = (float) cos(angle); - } else if(strcmp(axis, "X") == 0) { - //rotation around X - mat[0] = 1.0f; - mat[4] = (float) cos(angle); - mat[5] = (float) sin(angle); - mat[7] = -((float) sin(angle)); - mat[8] = (float) cos(angle); - } else if(strcmp(axis, "Y") == 0) { - //rotation around Y - mat[0] = (float) cos(angle); - mat[2] = -((float) sin(angle)); - mat[4] = 1.0f; - mat[6] = (float) sin(angle); - mat[8] = (float) cos(angle); - } else if(strcmp(axis, "Z") == 0) { - //rotation around Z - mat[0] = (float) cos(angle); - mat[1] = (float) sin(angle); - mat[3] = -((float) sin(angle)); - mat[4] = (float) cos(angle); - mat[8] = 1.0f; - } - else { - /* should never get here */ - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): unknown error\n"); - return NULL; - } - - if(matSize == 4) { - //resize matrix - mat[10] = mat[8]; - mat[9] = mat[7]; - mat[8] = mat[6]; - mat[7] = 0.0f; - mat[6] = mat[5]; - mat[5] = mat[4]; - mat[4] = mat[3]; - mat[3] = 0.0f; - } - //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); -} - -static char M_Mathutils_TranslationMatrix_doc[] = -".. function:: TranslationMatrix(vector)\n" -"\n" -" Create a matrix representing a translation.\n" -"\n" -" :arg vector: The translation vector.\n" -" :type vector: :class:`Vector`\n" -" :return: An identity matrix with a translation.\n" -" :rtype: :class:`Matrix`\n"; - -static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * vec) -{ - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - - if(!VectorObject_Check(vec)) { - PyErr_SetString(PyExc_TypeError, "mathutils.TranslationMatrix(): expected vector\n"); - return NULL; - } - if(vec->size != 3 && vec->size != 4) { - PyErr_SetString(PyExc_TypeError, "mathutils.TranslationMatrix(): vector must be 3D or 4D\n"); - return NULL; - } - - if(!BaseMath_ReadCallback(vec)) - return NULL; - - //create a identity matrix and add translation - unit_m4((float(*)[4]) mat); - mat[12] = vec->vec[0]; - mat[13] = vec->vec[1]; - mat[14] = vec->vec[2]; - - return newMatrixObject(mat, 4, 4, Py_NEW, NULL); -} -//----------------------------------mathutils.ScaleMatrix() ------------- -//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. -static char M_Mathutils_ScaleMatrix_doc[] = -".. function:: ScaleMatrix(factor, size, axis)\n" -"\n" -" Create a matrix representing a scaling.\n" -"\n" -" :arg factor: The factor of scaling to apply.\n" -" :type factor: float\n" -" :arg size: The size of the scale matrix to construct [2, 4].\n" -" :type size: int\n" -" :arg axis: Direction to influence scale. (optional).\n" -" :type axis: :class:`Vector`\n" -" :return: A new scale matrix.\n" -" :rtype: :class:`Matrix`\n"; - -static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args) -{ - VectorObject *vec = NULL; - float norm = 0.0f, factor; - int matSize, x; - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - - if(!PyArg_ParseTuple(args, "fi|O!", &factor, &matSize, &vector_Type, &vec)) { - PyErr_SetString(PyExc_TypeError, "mathutils.ScaleMatrix(): expected float int and optional vector\n"); - return NULL; - } - if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError, "mathutils.ScaleMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); - return NULL; - } - if(vec) { - if(vec->size > 2 && matSize == 2) { - PyErr_SetString(PyExc_AttributeError, "mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n"); - return NULL; - } - - if(!BaseMath_ReadCallback(vec)) - return NULL; - - } - if(vec == NULL) { //scaling along axis - if(matSize == 2) { - mat[0] = factor; - mat[3] = factor; - } else { - mat[0] = factor; - mat[4] = factor; - mat[8] = factor; - } - } else { //scaling in arbitrary direction - //normalize arbitrary axis - for(x = 0; x < vec->size; x++) { - norm += vec->vec[x] * vec->vec[x]; - } - norm = (float) sqrt(norm); - for(x = 0; x < vec->size; x++) { - vec->vec[x] /= norm; - } - if(matSize == 2) { - mat[0] = 1 +((factor - 1) *(vec->vec[0] * vec->vec[0])); - mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1])); - mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[1])); - mat[3] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1])); - } else { - mat[0] = 1 + ((factor - 1) *(vec->vec[0] * vec->vec[0])); - mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1])); - mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[2])); - mat[3] =((factor - 1) *(vec->vec[0] * vec->vec[1])); - mat[4] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1])); - mat[5] =((factor - 1) *(vec->vec[1] * vec->vec[2])); - mat[6] =((factor - 1) *(vec->vec[0] * vec->vec[2])); - mat[7] =((factor - 1) *(vec->vec[1] * vec->vec[2])); - mat[8] = 1 + ((factor - 1) *(vec->vec[2] * vec->vec[2])); - } - } - if(matSize == 4) { - //resize matrix - mat[10] = mat[8]; - mat[9] = mat[7]; - mat[8] = mat[6]; - mat[7] = 0.0f; - mat[6] = mat[5]; - mat[5] = mat[4]; - mat[4] = mat[3]; - mat[3] = 0.0f; - } - //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); -} -//----------------------------------mathutils.OrthoProjectionMatrix() --- -//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. -static char M_Mathutils_OrthoProjectionMatrix_doc[] = -".. function:: OrthoProjectionMatrix(plane, size, axis)\n" -"\n" -" Create a matrix to represent an orthographic projection.\n" -"\n" -" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ', 'R'], where a single axis is for a 2D matrix and 'R' requires axis is given.\n" -" :type plane: string\n" -" :arg size: The size of the projection matrix to construct [2, 4].\n" -" :type size: int\n" -" :arg axis: Arbitrary perpendicular plane vector (optional).\n" -" :type axis: :class:`Vector`\n" -" :return: A new projection matrix.\n" -" :rtype: :class:`Matrix`\n"; -static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args) -{ - VectorObject *vec = NULL; - char *plane; - int matSize, x; - float norm = 0.0f; - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - - if(!PyArg_ParseTuple(args, "si|O!", &plane, &matSize, &vector_Type, &vec)) { - PyErr_SetString(PyExc_TypeError, "mathutils.OrthoProjectionMatrix(): expected string and int and optional vector\n"); - return NULL; - } - if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError,"mathutils.OrthoProjectionMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); - return NULL; - } - if(vec) { - if(vec->size > 2 && matSize == 2) { - PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n"); - return NULL; - } - - if(!BaseMath_ReadCallback(vec)) - return NULL; - - } - if(vec == NULL) { //ortho projection onto cardinal plane - if((strcmp(plane, "X") == 0) && matSize == 2) { - mat[0] = 1.0f; - } else if((strcmp(plane, "Y") == 0) && matSize == 2) { - mat[3] = 1.0f; - } else if((strcmp(plane, "XY") == 0) && matSize > 2) { - mat[0] = 1.0f; - mat[4] = 1.0f; - } else if((strcmp(plane, "XZ") == 0) && matSize > 2) { - mat[0] = 1.0f; - mat[8] = 1.0f; - } else if((strcmp(plane, "YZ") == 0) && matSize > 2) { - mat[4] = 1.0f; - mat[8] = 1.0f; - } else { - PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): unknown plane - expected: X, Y, XY, XZ, YZ\n"); - return NULL; - } - } else { //arbitrary plane - //normalize arbitrary axis - for(x = 0; x < vec->size; x++) { - norm += vec->vec[x] * vec->vec[x]; - } - norm = (float) sqrt(norm); - for(x = 0; x < vec->size; x++) { - vec->vec[x] /= norm; - } - if((strcmp(plane, "R") == 0) && matSize == 2) { - mat[0] = 1 - (vec->vec[0] * vec->vec[0]); - mat[1] = -(vec->vec[0] * vec->vec[1]); - mat[2] = -(vec->vec[0] * vec->vec[1]); - mat[3] = 1 - (vec->vec[1] * vec->vec[1]); - } else if((strcmp(plane, "R") == 0) && matSize > 2) { - mat[0] = 1 - (vec->vec[0] * vec->vec[0]); - mat[1] = -(vec->vec[0] * vec->vec[1]); - mat[2] = -(vec->vec[0] * vec->vec[2]); - mat[3] = -(vec->vec[0] * vec->vec[1]); - mat[4] = 1 - (vec->vec[1] * vec->vec[1]); - mat[5] = -(vec->vec[1] * vec->vec[2]); - mat[6] = -(vec->vec[0] * vec->vec[2]); - mat[7] = -(vec->vec[1] * vec->vec[2]); - mat[8] = 1 - (vec->vec[2] * vec->vec[2]); - } else { - PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): unknown plane - expected: 'r' expected for axis designation\n"); - return NULL; - } - } - if(matSize == 4) { - //resize matrix - mat[10] = mat[8]; - mat[9] = mat[7]; - mat[8] = mat[6]; - mat[7] = 0.0f; - mat[6] = mat[5]; - mat[5] = mat[4]; - mat[4] = mat[3]; - mat[3] = 0.0f; - } - //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); -} - -static char M_Mathutils_ShearMatrix_doc[] = -".. function:: ShearMatrix(plane, factor, size)\n" -"\n" -" Create a matrix to represent an shear transformation.\n" -"\n" -" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'], where a single axis is for a 2D matrix.\n" -" :type plane: string\n" -" :arg factor: The factor of shear to apply.\n" -" :type factor: float\n" -" :arg size: The size of the shear matrix to construct [2, 4].\n" -" :type size: int\n" -" :return: A new shear matrix.\n" -" :rtype: :class:`Matrix`\n"; - -static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args) -{ - int matSize; - char *plane; - float factor; - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - - if(!PyArg_ParseTuple(args, "sfi", &plane, &factor, &matSize)) { - PyErr_SetString(PyExc_TypeError,"mathutils.ShearMatrix(): expected string float and int\n"); - return NULL; - } - if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError,"mathutils.ShearMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); - return NULL; - } - - if((strcmp(plane, "X") == 0) - && matSize == 2) { - mat[0] = 1.0f; - mat[2] = factor; - mat[3] = 1.0f; - } else if((strcmp(plane, "Y") == 0) && matSize == 2) { - mat[0] = 1.0f; - mat[1] = factor; - mat[3] = 1.0f; - } else if((strcmp(plane, "XY") == 0) && matSize > 2) { - mat[0] = 1.0f; - mat[4] = 1.0f; - mat[6] = factor; - mat[7] = factor; - } else if((strcmp(plane, "XZ") == 0) && matSize > 2) { - mat[0] = 1.0f; - mat[3] = factor; - mat[4] = 1.0f; - mat[5] = factor; - mat[8] = 1.0f; - } else if((strcmp(plane, "YZ") == 0) && matSize > 2) { - mat[0] = 1.0f; - mat[1] = factor; - mat[2] = factor; - mat[4] = 1.0f; - mat[8] = 1.0f; - } else { - PyErr_SetString(PyExc_AttributeError, "mathutils.ShearMatrix(): expected: x, y, xy, xz, yz or wrong matrix size for shearing plane\n"); - return NULL; - } - if(matSize == 4) { - //resize matrix - mat[10] = mat[8]; - mat[9] = mat[7]; - mat[8] = mat[6]; - mat[7] = 0.0f; - mat[6] = mat[5]; - mat[5] = mat[4]; - mat[4] = mat[3]; - mat[3] = 0.0f; - } - //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); -} /* Utility functions */ @@ -647,11 +227,6 @@ void BaseMathObject_dealloc(BaseMathObject * self) /*----------------------------MODULE INIT-------------------------*/ struct PyMethodDef M_Mathutils_methods[] = { - {"RotationMatrix", (PyCFunction) M_Mathutils_RotationMatrix, METH_VARARGS, M_Mathutils_RotationMatrix_doc}, - {"ScaleMatrix", (PyCFunction) M_Mathutils_ScaleMatrix, METH_VARARGS, M_Mathutils_ScaleMatrix_doc}, - {"ShearMatrix", (PyCFunction) M_Mathutils_ShearMatrix, METH_VARARGS, M_Mathutils_ShearMatrix_doc}, - {"TranslationMatrix", (PyCFunction) M_Mathutils_TranslationMatrix, METH_O, M_Mathutils_TranslationMatrix_doc}, - {"OrthoProjectionMatrix", (PyCFunction) M_Mathutils_OrthoProjectionMatrix, METH_VARARGS, M_Mathutils_OrthoProjectionMatrix_doc}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/python/generic/mathutils_matrix.c b/source/blender/python/generic/mathutils_matrix.c index 9be50fe6349..1ef834b7a3e 100644 --- a/source/blender/python/generic/mathutils_matrix.c +++ b/source/blender/python/generic/mathutils_matrix.c @@ -181,6 +181,438 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return newMatrixObject(matrix, argSize, seqSize, Py_NEW, NULL); } +/*-----------------------CLASS-METHODS----------------------------*/ + +//----------------------------------mathutils.RotationMatrix() ---------- +//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. +static char C_Matrix_Rotation_doc[] = +".. classmethod:: Rotation(angle, size, axis)\n" +"\n" +" Create a matrix representing a rotation.\n" +"\n" +" :arg angle: The angle of rotation desired, in radians.\n" +" :type angle: float\n" +" :arg size: The size of the rotation matrix to construct [2, 4].\n" +" :type size: int\n" +" :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object (optional when size is 2).\n" +" :type axis: string or :class:`Vector`\n" +" :return: A new rotation matrix.\n" +" :rtype: :class:`Matrix`\n"; + +static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args) +{ + VectorObject *vec= NULL; + char *axis= NULL; + int matSize; + float angle = 0.0f; + float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + if(!PyArg_ParseTuple(args, "fi|O", &angle, &matSize, &vec)) { + PyErr_SetString(PyExc_TypeError, "mathutils.RotationMatrix(angle, size, axis): expected float int and a string or vector\n"); + return NULL; + } + + if(vec && !VectorObject_Check(vec)) { + axis= _PyUnicode_AsString((PyObject *)vec); + if(axis==NULL || axis[0]=='\0' || axis[1]!='\0' || axis[0] < 'X' || axis[0] > 'Z') { + PyErr_SetString(PyExc_TypeError, "mathutils.RotationMatrix(): 3rd argument axis value must be a 3D vector or a string in 'X', 'Y', 'Z'\n"); + return NULL; + } + else { + /* use the string */ + vec= NULL; + } + } + + while (angle<-(Py_PI*2)) + angle+=(Py_PI*2); + while (angle>(Py_PI*2)) + angle-=(Py_PI*2); + + if(matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); + return NULL; + } + if(matSize == 2 && (vec != NULL)) { + PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): cannot create a 2x2 rotation matrix around arbitrary axis\n"); + return NULL; + } + if((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) { + PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): please choose an axis of rotation for 3d and 4d matrices\n"); + return NULL; + } + if(vec) { + if(vec->size != 3) { + PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): the vector axis must be a 3D vector\n"); + return NULL; + } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + + } + + /* check for valid vector/axis above */ + if(vec) { + axis_angle_to_mat3( (float (*)[3])mat,vec->vec, angle); + } + else if(matSize == 2) { + //2D rotation matrix + mat[0] = (float) cos (angle); + mat[1] = (float) sin (angle); + mat[2] = -((float) sin(angle)); + mat[3] = (float) cos(angle); + } else if(strcmp(axis, "X") == 0) { + //rotation around X + mat[0] = 1.0f; + mat[4] = (float) cos(angle); + mat[5] = (float) sin(angle); + mat[7] = -((float) sin(angle)); + mat[8] = (float) cos(angle); + } else if(strcmp(axis, "Y") == 0) { + //rotation around Y + mat[0] = (float) cos(angle); + mat[2] = -((float) sin(angle)); + mat[4] = 1.0f; + mat[6] = (float) sin(angle); + mat[8] = (float) cos(angle); + } else if(strcmp(axis, "Z") == 0) { + //rotation around Z + mat[0] = (float) cos(angle); + mat[1] = (float) sin(angle); + mat[3] = -((float) sin(angle)); + mat[4] = (float) cos(angle); + mat[8] = 1.0f; + } + else { + /* should never get here */ + PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): unknown error\n"); + return NULL; + } + + if(matSize == 4) { + //resize matrix + mat[10] = mat[8]; + mat[9] = mat[7]; + mat[8] = mat[6]; + mat[7] = 0.0f; + mat[6] = mat[5]; + mat[5] = mat[4]; + mat[4] = mat[3]; + mat[3] = 0.0f; + } + //pass to matrix creation + return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); +} + + +static char C_Matrix_Translation_doc[] = +".. classmethod:: Translation(vector)\n" +"\n" +" Create a matrix representing a translation.\n" +"\n" +" :arg vector: The translation vector.\n" +" :type vector: :class:`Vector`\n" +" :return: An identity matrix with a translation.\n" +" :rtype: :class:`Matrix`\n"; + +static PyObject *C_Matrix_Translation(PyObject *cls, VectorObject * vec) +{ + float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + if(!VectorObject_Check(vec)) { + PyErr_SetString(PyExc_TypeError, "mathutils.TranslationMatrix(): expected vector\n"); + return NULL; + } + if(vec->size != 3 && vec->size != 4) { + PyErr_SetString(PyExc_TypeError, "mathutils.TranslationMatrix(): vector must be 3D or 4D\n"); + return NULL; + } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + + //create a identity matrix and add translation + unit_m4((float(*)[4]) mat); + mat[12] = vec->vec[0]; + mat[13] = vec->vec[1]; + mat[14] = vec->vec[2]; + + return newMatrixObject(mat, 4, 4, Py_NEW, (PyTypeObject *)cls); +} +//----------------------------------mathutils.ScaleMatrix() ------------- +//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. +static char C_Matrix_Scale_doc[] = +".. classmethod:: Scale(factor, size, axis)\n" +"\n" +" Create a matrix representing a scaling.\n" +"\n" +" :arg factor: The factor of scaling to apply.\n" +" :type factor: float\n" +" :arg size: The size of the scale matrix to construct [2, 4].\n" +" :type size: int\n" +" :arg axis: Direction to influence scale. (optional).\n" +" :type axis: :class:`Vector`\n" +" :return: A new scale matrix.\n" +" :rtype: :class:`Matrix`\n"; + +static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args) +{ + VectorObject *vec = NULL; + float norm = 0.0f, factor; + int matSize, x; + float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + if(!PyArg_ParseTuple(args, "fi|O!", &factor, &matSize, &vector_Type, &vec)) { + PyErr_SetString(PyExc_TypeError, "mathutils.ScaleMatrix(): expected float int and optional vector\n"); + return NULL; + } + if(matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_AttributeError, "mathutils.ScaleMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); + return NULL; + } + if(vec) { + if(vec->size > 2 && matSize == 2) { + PyErr_SetString(PyExc_AttributeError, "mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n"); + return NULL; + } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + + } + if(vec == NULL) { //scaling along axis + if(matSize == 2) { + mat[0] = factor; + mat[3] = factor; + } else { + mat[0] = factor; + mat[4] = factor; + mat[8] = factor; + } + } else { //scaling in arbitrary direction + //normalize arbitrary axis + for(x = 0; x < vec->size; x++) { + norm += vec->vec[x] * vec->vec[x]; + } + norm = (float) sqrt(norm); + for(x = 0; x < vec->size; x++) { + vec->vec[x] /= norm; + } + if(matSize == 2) { + mat[0] = 1 +((factor - 1) *(vec->vec[0] * vec->vec[0])); + mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1])); + mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[1])); + mat[3] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1])); + } else { + mat[0] = 1 + ((factor - 1) *(vec->vec[0] * vec->vec[0])); + mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1])); + mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[2])); + mat[3] =((factor - 1) *(vec->vec[0] * vec->vec[1])); + mat[4] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1])); + mat[5] =((factor - 1) *(vec->vec[1] * vec->vec[2])); + mat[6] =((factor - 1) *(vec->vec[0] * vec->vec[2])); + mat[7] =((factor - 1) *(vec->vec[1] * vec->vec[2])); + mat[8] = 1 + ((factor - 1) *(vec->vec[2] * vec->vec[2])); + } + } + if(matSize == 4) { + //resize matrix + mat[10] = mat[8]; + mat[9] = mat[7]; + mat[8] = mat[6]; + mat[7] = 0.0f; + mat[6] = mat[5]; + mat[5] = mat[4]; + mat[4] = mat[3]; + mat[3] = 0.0f; + } + //pass to matrix creation + return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); +} +//----------------------------------mathutils.OrthoProjectionMatrix() --- +//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. +static char C_Matrix_OrthoProjection_doc[] = +".. classmethod:: OrthoProjection(plane, size, axis)\n" +"\n" +" Create a matrix to represent an orthographic projection.\n" +"\n" +" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ', 'R'], where a single axis is for a 2D matrix and 'R' requires axis is given.\n" +" :type plane: string\n" +" :arg size: The size of the projection matrix to construct [2, 4].\n" +" :type size: int\n" +" :arg axis: Arbitrary perpendicular plane vector (optional).\n" +" :type axis: :class:`Vector`\n" +" :return: A new projection matrix.\n" +" :rtype: :class:`Matrix`\n"; +static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) +{ + VectorObject *vec = NULL; + char *plane; + int matSize, x; + float norm = 0.0f; + float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + if(!PyArg_ParseTuple(args, "si|O!", &plane, &matSize, &vector_Type, &vec)) { + PyErr_SetString(PyExc_TypeError, "mathutils.OrthoProjectionMatrix(): expected string and int and optional vector\n"); + return NULL; + } + if(matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_AttributeError,"mathutils.OrthoProjectionMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); + return NULL; + } + if(vec) { + if(vec->size > 2 && matSize == 2) { + PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n"); + return NULL; + } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + + } + if(vec == NULL) { //ortho projection onto cardinal plane + if((strcmp(plane, "X") == 0) && matSize == 2) { + mat[0] = 1.0f; + } else if((strcmp(plane, "Y") == 0) && matSize == 2) { + mat[3] = 1.0f; + } else if((strcmp(plane, "XY") == 0) && matSize > 2) { + mat[0] = 1.0f; + mat[4] = 1.0f; + } else if((strcmp(plane, "XZ") == 0) && matSize > 2) { + mat[0] = 1.0f; + mat[8] = 1.0f; + } else if((strcmp(plane, "YZ") == 0) && matSize > 2) { + mat[4] = 1.0f; + mat[8] = 1.0f; + } else { + PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): unknown plane - expected: X, Y, XY, XZ, YZ\n"); + return NULL; + } + } else { //arbitrary plane + //normalize arbitrary axis + for(x = 0; x < vec->size; x++) { + norm += vec->vec[x] * vec->vec[x]; + } + norm = (float) sqrt(norm); + for(x = 0; x < vec->size; x++) { + vec->vec[x] /= norm; + } + if((strcmp(plane, "R") == 0) && matSize == 2) { + mat[0] = 1 - (vec->vec[0] * vec->vec[0]); + mat[1] = -(vec->vec[0] * vec->vec[1]); + mat[2] = -(vec->vec[0] * vec->vec[1]); + mat[3] = 1 - (vec->vec[1] * vec->vec[1]); + } else if((strcmp(plane, "R") == 0) && matSize > 2) { + mat[0] = 1 - (vec->vec[0] * vec->vec[0]); + mat[1] = -(vec->vec[0] * vec->vec[1]); + mat[2] = -(vec->vec[0] * vec->vec[2]); + mat[3] = -(vec->vec[0] * vec->vec[1]); + mat[4] = 1 - (vec->vec[1] * vec->vec[1]); + mat[5] = -(vec->vec[1] * vec->vec[2]); + mat[6] = -(vec->vec[0] * vec->vec[2]); + mat[7] = -(vec->vec[1] * vec->vec[2]); + mat[8] = 1 - (vec->vec[2] * vec->vec[2]); + } else { + PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): unknown plane - expected: 'r' expected for axis designation\n"); + return NULL; + } + } + if(matSize == 4) { + //resize matrix + mat[10] = mat[8]; + mat[9] = mat[7]; + mat[8] = mat[6]; + mat[7] = 0.0f; + mat[6] = mat[5]; + mat[5] = mat[4]; + mat[4] = mat[3]; + mat[3] = 0.0f; + } + //pass to matrix creation + return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); +} + +static char C_Matrix_Shear_doc[] = +".. classmethod:: Shear(plane, factor, size)\n" +"\n" +" Create a matrix to represent an shear transformation.\n" +"\n" +" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'], where a single axis is for a 2D matrix.\n" +" :type plane: string\n" +" :arg factor: The factor of shear to apply.\n" +" :type factor: float\n" +" :arg size: The size of the shear matrix to construct [2, 4].\n" +" :type size: int\n" +" :return: A new shear matrix.\n" +" :rtype: :class:`Matrix`\n"; + +static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) +{ + int matSize; + char *plane; + float factor; + float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + if(!PyArg_ParseTuple(args, "sfi", &plane, &factor, &matSize)) { + PyErr_SetString(PyExc_TypeError,"mathutils.ShearMatrix(): expected string float and int\n"); + return NULL; + } + if(matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_AttributeError,"mathutils.ShearMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); + return NULL; + } + + if((strcmp(plane, "X") == 0) + && matSize == 2) { + mat[0] = 1.0f; + mat[2] = factor; + mat[3] = 1.0f; + } else if((strcmp(plane, "Y") == 0) && matSize == 2) { + mat[0] = 1.0f; + mat[1] = factor; + mat[3] = 1.0f; + } else if((strcmp(plane, "XY") == 0) && matSize > 2) { + mat[0] = 1.0f; + mat[4] = 1.0f; + mat[6] = factor; + mat[7] = factor; + } else if((strcmp(plane, "XZ") == 0) && matSize > 2) { + mat[0] = 1.0f; + mat[3] = factor; + mat[4] = 1.0f; + mat[5] = factor; + mat[8] = 1.0f; + } else if((strcmp(plane, "YZ") == 0) && matSize > 2) { + mat[0] = 1.0f; + mat[1] = factor; + mat[2] = factor; + mat[4] = 1.0f; + mat[8] = 1.0f; + } else { + PyErr_SetString(PyExc_AttributeError, "mathutils.ShearMatrix(): expected: x, y, xy, xz, yz or wrong matrix size for shearing plane\n"); + return NULL; + } + if(matSize == 4) { + //resize matrix + mat[10] = mat[8]; + mat[9] = mat[7]; + mat[8] = mat[6]; + mat[7] = 0.0f; + mat[6] = mat[5]; + mat[5] = mat[4]; + mat[4] = mat[3]; + mat[3] = 0.0f; + } + //pass to matrix creation + return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); +} + /* assumes rowsize == colsize is checked and the read callback has run */ static float matrix_determinant(MatrixObject * self) { @@ -1326,6 +1758,13 @@ static struct PyMethodDef Matrix_methods[] = { {"to_quat", (PyCFunction) Matrix_toQuat, METH_NOARGS, Matrix_toQuat_doc}, {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, + + /* class methods */ + {"Rotation", (PyCFunction) C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc}, + {"Scale", (PyCFunction) C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc}, + {"Shear", (PyCFunction) C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc}, + {"Translation", (PyCFunction) C_Matrix_Translation, METH_O | METH_CLASS, C_Matrix_Translation_doc}, + {"OrthoProjection", (PyCFunction) C_Matrix_OrthoProjection, METH_VARARGS | METH_CLASS, C_Matrix_OrthoProjection_doc}, {NULL, NULL, 0, NULL} }; |