Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2010-08-11 20:40:36 +0400
committerCampbell Barton <ideasman42@gmail.com>2010-08-11 20:40:36 +0400
commit556b615cf8eae8c656f2d2a0905564e5c0de98cc (patch)
treeb95388a46c9e9692c92638747f5abc84d66fa6bf /source/blender
parentab8ccaa7098f6fee887f2a249fddada7864cd6c5 (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.c439
-rw-r--r--source/blender/python/generic/mathutils_matrix.c439
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}
};