diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index ac0f5f44c74..918b3b93e0e 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -48,6 +48,8 @@ void copy_m3_m3(float R[3][3], const float A[3][3]); void copy_m4_m4(float R[4][4], const float A[4][4]); void copy_m3_m4(float R[3][3], const float A[4][4]); void copy_m4_m3(float R[4][4], const float A[3][3]); +void copy_m3_m2(float R[3][3], const float A[2][2]); +void copy_m4_m2(float R[4][4], const float A[2][2]); void copy_m4_m4_db(double m1[4][4], const double m2[4][4]); @@ -242,6 +244,7 @@ void transpose_m4_m4(float R[4][4], const float A[4][4]); int compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit); +void normalize_m2(float R[2][2]) ATTR_NONNULL(); void normalize_m3_ex(float R[3][3], float r_scale[3]) ATTR_NONNULL(); void normalize_m3(float R[3][3]) ATTR_NONNULL(); void normalize_m3_m3_ex(float R[3][3], const float A[3][3], float r_scale[3]) ATTR_NONNULL(); diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 4d8a2f72eca..0a76c350f81 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -143,6 +143,44 @@ void copy_m4_m3(float m1[4][4], const float m2[3][3]) /* no clear */ m1[3][3] = 1.0f; } +void copy_m3_m2(float m1[3][3], const float m2[2][2]) +{ + m1[0][0] = m2[0][0]; + m1[0][1] = m2[0][1]; + m1[0][2] = 0.0f; + + m1[1][0] = m2[1][0]; + m1[1][1] = m2[1][1]; + m1[1][2] = 0.0f; + + m1[2][0] = 0.0f; + m1[2][1] = 0.0f; + m1[2][2] = 1.0f; +} + +void copy_m4_m2(float m1[4][4], const float m2[2][2]) +{ + m1[0][0] = m2[0][0]; + m1[0][1] = m2[0][1]; + m1[0][2] = 0.0f; + m1[0][3] = 0.0f; + + m1[1][0] = m2[1][0]; + m1[1][1] = m2[1][1]; + m1[1][2] = 0.0f; + m1[1][3] = 0.0f; + + m1[2][0] = 0.0f; + m1[2][1] = 0.0f; + m1[2][2] = 1.0f; + m1[2][3] = 0.0f; + + m1[3][0] = 0.0f; + m1[3][1] = 0.0f; + m1[3][2] = 0.0f; + m1[3][3] = 1.0f; +} + void copy_m4d_m4(double m1[4][4], const float m2[4][4]) { m1[0][0] = m2[0][0]; @@ -1745,6 +1783,14 @@ bool is_uniform_scaled_m4(const float m[4][4]) return is_uniform_scaled_m3(t); } +void normalize_m2(float mat[2][2]) +{ + int i; + for (i = 0; i < 2; i++) { + normalize_v2(mat[i]); + } +} + void normalize_m3_ex(float mat[3][3], float r_scale[3]) { int i; diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 32921ae0ca9..47f8151b37a 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -973,6 +973,12 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls); } +void matrix_as_2x2(float mat[2][2], MatrixObject *self) +{ + copy_v2_v2(mat[0], MATRIX_COL_PTR(self, 0)); + copy_v2_v2(mat[1], MATRIX_COL_PTR(self, 1)); +} + void matrix_as_3x3(float mat[3][3], MatrixObject *self) { copy_v3_v3(mat[0], MATRIX_COL_PTR(self, 0)); @@ -1344,7 +1350,11 @@ static PyObject *Matrix_to_4x4(MatrixObject *self) copy_m4_m3(mat, (float(*)[3])self->matrix); return Matrix_CreatePyObject((float *)mat, 4, 4, Py_TYPE(self)); } - /* TODO, 2x2 matrix */ + else if (self->num_row == 2 && self->num_col == 2) { + float mat[4][4]; + copy_m4_m2(mat, (float(*)[2])self->matrix); + return Matrix_CreatePyObject((float *)mat, 4, 4, Py_TYPE(self)); + } PyErr_SetString(PyExc_ValueError, "Matrix.to_4x4(): " @@ -1367,7 +1377,12 @@ static PyObject *Matrix_to_3x3(MatrixObject *self) return NULL; } - if ((self->num_row < 3) || (self->num_col < 3)) { + if (self->num_row == 2 && self->num_col == 2) { + float mat[3][3]; + copy_m3_m2(mat, (float(*)[2])self->matrix); + return Matrix_CreatePyObject((float *)mat, 3, 3, Py_TYPE(self)); + } + else if ((self->num_row < 3) || (self->num_col < 3)) { PyErr_SetString(PyExc_ValueError, "Matrix.to_3x3(): inappropriate matrix size"); return NULL; } diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h index 3b42e22a787..e07e4bc3f35 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.h +++ b/source/blender/python/mathutils/mathutils_Matrix.h @@ -87,6 +87,7 @@ extern struct Mathutils_Callback mathutils_matrix_row_cb; /* default */ extern struct Mathutils_Callback mathutils_matrix_col_cb; extern struct Mathutils_Callback mathutils_matrix_translation_cb; +void matrix_as_2x2(float mat[2][2], MatrixObject *self); void matrix_as_3x3(float mat[3][3], MatrixObject *self); #endif /* __MATHUTILS_MATRIX_H__ */ diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 387e560d946..bca0103f5ce 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -1282,22 +1282,38 @@ PyDoc_STRVAR(Vector_rotate_doc, " :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"); static PyObject *Vector_rotate(VectorObject *self, PyObject *value) { - float other_rmat[3][3]; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { return NULL; } - if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1) { - return NULL; - } + /* special case for 2D Vector with 2x2 matrix, so we avoid resizing it to a 3x3 */ + if (self->size == 2 && + MatrixObject_Check(value) && + BaseMath_ReadCallback((BaseMathObject *)value) != -1 && + ((MatrixObject *)value)->num_row == 2 && + ((MatrixObject *)value)->num_col == 2) + { + float other_rmat[2][2]; - if (self->size < 3 || self->size > 4) { - PyErr_SetString(PyExc_ValueError, "Vector must be 3D or 4D"); - return NULL; + matrix_as_2x2(other_rmat, (MatrixObject *)value); + normalize_m2(other_rmat); + + mul_m2v2(other_rmat, self->vec); /* equivalent to a rotation along the Z axis */ } + else { + float other_rmat[3][3]; - mul_m3_v3(other_rmat, self->vec); + if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1) { + return NULL; + } + + if (self->size < 3 || self->size > 4) { + PyErr_SetString(PyExc_ValueError, "Vector must be 3D or 4D"); + return NULL; + } + + mul_m3_v3(other_rmat, self->vec); + } (void)BaseMath_WriteCallback(self); Py_RETURN_NONE;