mathutils: support Vector.rotate for 2D vectors

This commit is contained in:
Tiago Chaves
2020-02-20 13:57:32 +11:00
committed by Campbell Barton
parent 0115568ca6
commit bc86eb1780
3 changed files with 45 additions and 16 deletions

View File

@@ -3306,6 +3306,23 @@ int Matrix_ParseAny(PyObject *o, void *p)
return 1; return 1;
} }
int Matrix_Parse2x2(PyObject *o, void *p)
{
MatrixObject **pymat_p = p;
MatrixObject *pymat = (MatrixObject *)o;
if (!Matrix_ParseCheck(pymat)) {
return 0;
}
if ((pymat->num_col != 2) || (pymat->num_row != 2)) {
PyErr_SetString(PyExc_ValueError, "matrix must be 2x2");
return 0;
}
*pymat_p = pymat;
return 1;
}
int Matrix_Parse3x3(PyObject *o, void *p) int Matrix_Parse3x3(PyObject *o, void *p)
{ {
MatrixObject **pymat_p = p; MatrixObject **pymat_p = p;

View File

@@ -76,6 +76,7 @@ PyObject *Matrix_CreatePyObject_cb(PyObject *user,
/* PyArg_ParseTuple's "O&" formatting helpers. */ /* PyArg_ParseTuple's "O&" formatting helpers. */
int Matrix_ParseAny(PyObject *o, void *p); int Matrix_ParseAny(PyObject *o, void *p);
int Matrix_Parse2x2(PyObject *o, void *p);
int Matrix_Parse3x3(PyObject *o, void *p); int Matrix_Parse3x3(PyObject *o, void *p);
int Matrix_Parse4x4(PyObject *o, void *p); int Matrix_Parse4x4(PyObject *o, void *p);

View File

@@ -1273,32 +1273,43 @@ static PyObject *Vector_slerp(VectorObject *self, PyObject *args)
return Vector_CreatePyObject(ret_vec, size, Py_TYPE(self)); return Vector_CreatePyObject(ret_vec, size, Py_TYPE(self));
} }
PyDoc_STRVAR(Vector_rotate_doc, PyDoc_STRVAR(
".. function:: rotate(other)\n" Vector_rotate_doc,
"\n" ".. function:: rotate(other)\n"
" Rotate the vector by a rotation value.\n" "\n"
"\n" " Rotate the vector by a rotation value.\n"
" :arg other: rotation component of mathutils value\n" "\n"
" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"); " .. note:: 2D vectors are a special case that can only be rotated by a 2x2 matrix.\n"
"\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 *value) static PyObject *Vector_rotate(VectorObject *self, PyObject *value)
{ {
float other_rmat[3][3];
if (BaseMath_ReadCallback_ForWrite(self) == -1) { if (BaseMath_ReadCallback_ForWrite(self) == -1) {
return NULL; return NULL;
} }
if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1) { if (self->size == 2) {
return NULL; /* Special case for 2D Vector with 2x2 matrix, so we avoid resizing it to a 3x3. */
float other_rmat[2][2];
MatrixObject *pymat;
if (!Matrix_Parse2x2(value, &pymat)) {
return NULL;
}
normalize_m2_m2(other_rmat, (const float(*)[2])pymat->matrix);
/* Equivalent to a rotation along the Z axis. */
mul_m2_v2(other_rmat, self->vec);
} }
else {
float other_rmat[3][3];
if (self->size < 3 || self->size > 4) { if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1) {
PyErr_SetString(PyExc_ValueError, "Vector must be 3D or 4D"); return NULL;
return NULL; }
mul_m3_v3(other_rmat, self->vec);
} }
mul_m3_v3(other_rmat, self->vec);
(void)BaseMath_WriteCallback(self); (void)BaseMath_WriteCallback(self);
Py_RETURN_NONE; Py_RETURN_NONE;
} }