Changeset View
Changeset View
Standalone View
Standalone View
source/blender/python/mathutils/mathutils_Matrix.c
| Show First 20 Lines • Show All 2,315 Lines • ▼ Show 20 Lines | if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); | sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); | ||||
| return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1)); | return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1)); | ||||
| } | } | ||||
| /*------------------------obj * obj------------------------------ | /*------------------------obj * obj------------------------------ | ||||
| * multiplication */ | * element-wise multiplication */ | ||||
| static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar) | static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar) | ||||
| { | { | ||||
| float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; | float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; | ||||
| mul_vn_vn_fl(tmat, mat->matrix, mat->num_col * mat->num_row, scalar); | mul_vn_vn_fl(tmat, mat->matrix, mat->num_col * mat->num_row, scalar); | ||||
| return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_TYPE(mat)); | return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_TYPE(mat)); | ||||
| } | } | ||||
| static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) | static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) | ||||
| { | { | ||||
| float scalar; | float scalar; | ||||
| int vec_size; | |||||
| MatrixObject *mat1 = NULL, *mat2 = NULL; | MatrixObject *mat1 = NULL, *mat2 = NULL; | ||||
| if (MatrixObject_Check(m1)) { | if (MatrixObject_Check(m1)) { | ||||
| mat1 = (MatrixObject *)m1; | mat1 = (MatrixObject *)m1; | ||||
| if (BaseMath_ReadCallback(mat1) == -1) | if (BaseMath_ReadCallback(mat1) == -1) | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (MatrixObject_Check(m2)) { | if (MatrixObject_Check(m2)) { | ||||
| mat2 = (MatrixObject *)m2; | mat2 = (MatrixObject *)m2; | ||||
| if (BaseMath_ReadCallback(mat2) == -1) | if (BaseMath_ReadCallback(mat2) == -1) | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (mat1 && mat2) { | if (mat1 && mat2) { | ||||
| #ifdef USE_MATHUTILS_ELEM_MUL | |||||
| /* MATRIX * MATRIX */ | /* MATRIX * MATRIX */ | ||||
| float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; | float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; | ||||
| if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) { | |||||
| PyErr_SetString(PyExc_ValueError, | |||||
| "matrix1 * matrix2: matrix1 number of rows/columns " | |||||
| "and the matrix2 number of rows/columns must be the same"); | |||||
| return NULL; | |||||
| } | |||||
| mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); | |||||
| return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1)); | |||||
| #endif | |||||
| } | |||||
| else if (mat2) { | |||||
| /*FLOAT/INT * MATRIX */ | |||||
| if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) { | |||||
| return matrix_mul_float(mat2, scalar); | |||||
| } | |||||
| } | |||||
| else if (mat1) { | |||||
| /* MATRIX * FLOAT/INT */ | |||||
| if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) { | |||||
| return matrix_mul_float(mat1, scalar); | |||||
| } | |||||
| } | |||||
| PyErr_Format(PyExc_TypeError, | |||||
| "Element-wise multiplication: " | |||||
| "not supported between '%.200s' and '%.200s' types", | |||||
| Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); | |||||
| return NULL; | |||||
| } | |||||
| /*------------------------obj *= obj------------------------------ | |||||
| * Inplace element-wise multiplication */ | |||||
| static PyObject *Matrix_imul(PyObject *m1, PyObject *m2) | |||||
| { | |||||
| float scalar; | |||||
| MatrixObject *mat1 = NULL, *mat2 = NULL; | |||||
| if (MatrixObject_Check(m1)) { | |||||
| mat1 = (MatrixObject *)m1; | |||||
| if (BaseMath_ReadCallback(mat1) == -1) | |||||
| return NULL; | |||||
| } | |||||
| if (MatrixObject_Check(m2)) { | |||||
| mat2 = (MatrixObject *)m2; | |||||
| if (BaseMath_ReadCallback(mat2) == -1) | |||||
| return NULL; | |||||
| } | |||||
| if (mat1 && mat2) { | |||||
| #ifdef USE_MATHUTILS_ELEM_MUL | |||||
| /* MATRIX *= MATRIX */ | |||||
| if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) { | |||||
| PyErr_SetString(PyExc_ValueError, | |||||
| "matrix1 *= matrix2: matrix1 number of rows/columns " | |||||
| "and the matrix2 number of rows/columns must be the same"); | |||||
| return NULL; | |||||
| } | |||||
| mul_vn_vn(mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); | |||||
| #else | |||||
| PyErr_Format(PyExc_TypeError, | |||||
| "Inplace element-wise multiplication: " | |||||
| "not supported between '%.200s' and '%.200s' types", | |||||
| Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); | |||||
| return NULL; | |||||
| #endif | |||||
| } | |||||
| else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) { | |||||
| /* MATRIX *= FLOAT/INT */ | |||||
| mul_vn_fl(mat1->matrix, mat1->num_row * mat1->num_col, scalar); | |||||
| } | |||||
| else { | |||||
| PyErr_Format(PyExc_TypeError, | |||||
| "Inplace element-wise multiplication: " | |||||
| "not supported between '%.200s' and '%.200s' types", | |||||
| Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); | |||||
| return NULL; | |||||
| } | |||||
| (void)BaseMath_WriteCallback(mat1); | |||||
| Py_INCREF(m1); | |||||
| return m1; | |||||
| } | |||||
| /*------------------------obj @ obj------------------------------ | |||||
| * matrix multiplication */ | |||||
| static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2) | |||||
| { | |||||
| int vec_size; | |||||
| MatrixObject *mat1 = NULL, *mat2 = NULL; | |||||
| if (MatrixObject_Check(m1)) { | |||||
| mat1 = (MatrixObject *)m1; | |||||
| if (BaseMath_ReadCallback(mat1) == -1) | |||||
| return NULL; | |||||
| } | |||||
| if (MatrixObject_Check(m2)) { | |||||
| mat2 = (MatrixObject *)m2; | |||||
| if (BaseMath_ReadCallback(mat2) == -1) | |||||
| return NULL; | |||||
| } | |||||
| if (mat1 && mat2) { | |||||
| /* MATRIX @ MATRIX */ | |||||
| float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; | |||||
| int col, row, item; | int col, row, item; | ||||
| if (mat1->num_col != mat2->num_row) { | if (mat1->num_col != mat2->num_row) { | ||||
| PyErr_SetString(PyExc_ValueError, | PyErr_SetString(PyExc_ValueError, | ||||
| "matrix1 * matrix2: matrix1 number of columns " | "matrix1 * matrix2: matrix1 number of columns " | ||||
| "and the matrix2 number of rows must be the same"); | "and the matrix2 number of rows must be the same"); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| for (col = 0; col < mat2->num_col; col++) { | for (col = 0; col < mat2->num_col; col++) { | ||||
| for (row = 0; row < mat1->num_row; row++) { | for (row = 0; row < mat1->num_row; row++) { | ||||
| double dot = 0.0f; | double dot = 0.0f; | ||||
| for (item = 0; item < mat1->num_col; item++) { | for (item = 0; item < mat1->num_col; item++) { | ||||
| dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col)); | dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col)); | ||||
| } | } | ||||
| mat[(col * mat1->num_row) + row] = (float)dot; | mat[(col * mat1->num_row) + row] = (float)dot; | ||||
| } | } | ||||
| } | } | ||||
| return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1)); | return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1)); | ||||
| } | } | ||||
| else if (mat2) { | |||||
| /*FLOAT/INT * MATRIX */ | |||||
| if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) { | |||||
| return matrix_mul_float(mat2, scalar); | |||||
| } | |||||
| } | |||||
| else if (mat1) { | else if (mat1) { | ||||
| /* MATRIX * VECTOR */ | /* MATRIX @ VECTOR */ | ||||
| if (VectorObject_Check(m2)) { | if (VectorObject_Check(m2)) { | ||||
| VectorObject *vec2 = (VectorObject *)m2; | VectorObject *vec2 = (VectorObject *)m2; | ||||
| float tvec[MATRIX_MAX_DIM]; | float tvec[MATRIX_MAX_DIM]; | ||||
| if (BaseMath_ReadCallback(vec2) == -1) | if (BaseMath_ReadCallback(vec2) == -1) | ||||
| return NULL; | return NULL; | ||||
| if (column_vector_multiplication(tvec, vec2, mat1) == -1) { | if (column_vector_multiplication(tvec, vec2, mat1) == -1) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (mat1->num_col == 4 && vec2->size == 3) { | if (mat1->num_col == 4 && vec2->size == 3) { | ||||
| vec_size = 3; | vec_size = 3; | ||||
| } | } | ||||
| else { | else { | ||||
| vec_size = mat1->num_row; | vec_size = mat1->num_row; | ||||
| } | } | ||||
| return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2)); | return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2)); | ||||
| } | } | ||||
| /*FLOAT/INT * MATRIX */ | |||||
| else if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) { | |||||
| return matrix_mul_float(mat1, scalar); | |||||
| } | } | ||||
| PyErr_Format(PyExc_TypeError, | |||||
| "Matrix multiplication: " | |||||
| "not supported between '%.200s' and '%.200s' types", | |||||
| Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); | |||||
| return NULL; | |||||
| } | } | ||||
| else { | /*------------------------obj @= obj------------------------------ | ||||
| BLI_assert(!"internal error"); | * inplace matrix multiplication */ | ||||
| static PyObject *Matrix_imatmul(PyObject *m1, PyObject *m2) | |||||
| { | |||||
| MatrixObject *mat1 = NULL, *mat2 = NULL; | |||||
| if (MatrixObject_Check(m1)) { | |||||
| mat1 = (MatrixObject *)m1; | |||||
| if (BaseMath_ReadCallback(mat1) == -1) | |||||
| return NULL; | |||||
| } | |||||
| if (MatrixObject_Check(m2)) { | |||||
| mat2 = (MatrixObject *)m2; | |||||
| if (BaseMath_ReadCallback(mat2) == -1) | |||||
| return NULL; | |||||
| } | } | ||||
| if (mat1 && mat2) { | |||||
| /* MATRIX @= MATRIX */ | |||||
| float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; | |||||
| int col, row, item; | |||||
| if (mat1->num_col != mat2->num_row) { | |||||
| PyErr_SetString(PyExc_ValueError, | |||||
| "matrix1 * matrix2: matrix1 number of columns " | |||||
| "and the matrix2 number of rows must be the same"); | |||||
| return NULL; | |||||
| } | |||||
| for (col = 0; col < mat2->num_col; col++) { | |||||
| for (row = 0; row < mat1->num_row; row++) { | |||||
| double dot = 0.0f; | |||||
| for (item = 0; item < mat1->num_col; item++) { | |||||
| dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col)); | |||||
| } | |||||
| /* store in new matrix as overwriting original at this point will cause | |||||
| * subsequent iterations to use incorrect values */ | |||||
| mat[(col * mat1->num_row) + row] = (float)dot; | |||||
| } | |||||
| } | |||||
| /* copy matrix back */ | |||||
| memcpy(mat1->matrix, mat, mat1->num_row * mat1->num_col); | |||||
| } | |||||
| else { | |||||
| PyErr_Format(PyExc_TypeError, | PyErr_Format(PyExc_TypeError, | ||||
| "Matrix multiplication: " | "Inplace matrix multiplication: " | ||||
| "not supported between '%.200s' and '%.200s' types", | "not supported between '%.200s' and '%.200s' types", | ||||
| Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); | Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| (void)BaseMath_WriteCallback(mat1); | |||||
| Py_INCREF(m1); | |||||
| return m1; | |||||
| } | |||||
| /*-----------------PROTOCOL DECLARATIONS--------------------------*/ | /*-----------------PROTOCOL DECLARATIONS--------------------------*/ | ||||
| static PySequenceMethods Matrix_SeqMethods = { | static PySequenceMethods Matrix_SeqMethods = { | ||||
| (lenfunc) Matrix_len, /* sq_length */ | (lenfunc) Matrix_len, /* sq_length */ | ||||
| (binaryfunc) NULL, /* sq_concat */ | (binaryfunc) NULL, /* sq_concat */ | ||||
| (ssizeargfunc) NULL, /* sq_repeat */ | (ssizeargfunc) NULL, /* sq_repeat */ | ||||
| (ssizeargfunc) Matrix_item_row, /* sq_item */ | (ssizeargfunc) Matrix_item_row, /* sq_item */ | ||||
| (ssizessizeargfunc) NULL, /* sq_slice, deprecated */ | (ssizessizeargfunc) NULL, /* sq_slice, deprecated */ | ||||
| (ssizeobjargproc) Matrix_ass_item_row, /* sq_ass_item */ | (ssizeobjargproc) Matrix_ass_item_row, /* sq_ass_item */ | ||||
| ▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | static PyNumberMethods Matrix_NumMethods = { | ||||
| NULL, /*nb_and*/ | NULL, /*nb_and*/ | ||||
| NULL, /*nb_xor*/ | NULL, /*nb_xor*/ | ||||
| NULL, /*nb_or*/ | NULL, /*nb_or*/ | ||||
| NULL, /*nb_int*/ | NULL, /*nb_int*/ | ||||
| NULL, /*nb_reserved*/ | NULL, /*nb_reserved*/ | ||||
| NULL, /*nb_float*/ | NULL, /*nb_float*/ | ||||
| NULL, /* nb_inplace_add */ | NULL, /* nb_inplace_add */ | ||||
| NULL, /* nb_inplace_subtract */ | NULL, /* nb_inplace_subtract */ | ||||
| NULL, /* nb_inplace_multiply */ | (binaryfunc) Matrix_imul, /* nb_inplace_multiply */ | ||||
| NULL, /* nb_inplace_remainder */ | NULL, /* nb_inplace_remainder */ | ||||
| NULL, /* nb_inplace_power */ | NULL, /* nb_inplace_power */ | ||||
| NULL, /* nb_inplace_lshift */ | NULL, /* nb_inplace_lshift */ | ||||
| NULL, /* nb_inplace_rshift */ | NULL, /* nb_inplace_rshift */ | ||||
| NULL, /* nb_inplace_and */ | NULL, /* nb_inplace_and */ | ||||
| NULL, /* nb_inplace_xor */ | NULL, /* nb_inplace_xor */ | ||||
| NULL, /* nb_inplace_or */ | NULL, /* nb_inplace_or */ | ||||
| NULL, /* nb_floor_divide */ | NULL, /* nb_floor_divide */ | ||||
| NULL, /* nb_true_divide */ | NULL, /* nb_true_divide */ | ||||
| NULL, /* nb_inplace_floor_divide */ | NULL, /* nb_inplace_floor_divide */ | ||||
| NULL, /* nb_inplace_true_divide */ | NULL, /* nb_inplace_true_divide */ | ||||
| NULL, /* nb_index */ | NULL, /* nb_index */ | ||||
| (binaryfunc) Matrix_matmul, /* nb_matrix_multiply */ | |||||
| (binaryfunc) Matrix_imatmul, /* nb_inplace_matrix_multiply */ | |||||
| }; | }; | ||||
| PyDoc_STRVAR(Matrix_translation_doc, | PyDoc_STRVAR(Matrix_translation_doc, | ||||
| "The translation component of the matrix.\n\n:type: Vector" | "The translation component of the matrix.\n\n:type: Vector" | ||||
| ); | ); | ||||
| static PyObject *Matrix_translation_get(MatrixObject *self, void *UNUSED(closure)) | static PyObject *Matrix_translation_get(MatrixObject *self, void *UNUSED(closure)) | ||||
| { | { | ||||
| PyObject *ret; | PyObject *ret; | ||||
| ▲ Show 20 Lines • Show All 659 Lines • Show Last 20 Lines | |||||