28 #include "../generic/py_capi_utils.h"
29 #include "../generic/python_utildefines.h"
31 #ifndef MATH_STANDALONE
52 PyErr_SetString(PyExc_AttributeError,
54 "owner matrix has been resized since this row vector was created");
64 PyErr_SetString(PyExc_AttributeError,
66 "owner matrix has been resized since this column vector was created");
97 for (
col = 0;
col <
self->num_col;
col++) {
116 for (
col = 0;
col <
self->num_col;
col++) {
192 for (row = 0; row < num_row; row++) {
215 for (row = 0; row < num_row; row++) {
285 for (row = 0; row < 3; row++) {
301 for (row = 0; row < 3; row++) {
350 if (kwds && PyDict_Size(kwds)) {
351 PyErr_SetString(PyExc_TypeError,
353 "takes no keyword args");
357 switch (PyTuple_GET_SIZE(args)) {
361 PyObject *arg = PyTuple_GET_ITEM(args, 0);
366 const ushort num_row = PySequence_Size(arg);
368 if (num_row >= 2 && num_row <= 4) {
369 PyObject *item = PySequence_GetItem(arg, 0);
372 const ushort num_col = PySequence_Size(item);
375 if (num_col >= 2 && num_col <= 4) {
390 PyErr_SetString(PyExc_TypeError,
392 "expects no args or a single arg containing 2-4 numeric sequences");
403 Py_DECREF(ret_dummy);
432 ".. classmethod:: Identity(size)\n"
434 " Create an identity matrix.\n"
436 " :arg size: The size of the identity matrix to construct [2, 4].\n"
438 " :return: A new identity matrix.\n"
439 " :rtype: :class:`Matrix`\n");
444 if (!PyArg_ParseTuple(args,
"i:Matrix.Identity", &matSize)) {
448 if (matSize < 2 || matSize > 4) {
449 PyErr_SetString(PyExc_RuntimeError,
450 "Matrix.Identity(): "
451 "size must be between 2 and 4");
459 ".. classmethod:: Rotation(angle, size, axis)\n"
461 " Create a matrix representing a rotation.\n"
463 " :arg angle: The angle of rotation desired, in radians.\n"
464 " :type angle: float\n"
465 " :arg size: The size of the rotation matrix to construct [2, 4].\n"
467 " :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object\n"
468 " (optional when size is 2).\n"
469 " :type axis: string or :class:`Vector`\n"
470 " :return: A new rotation matrix.\n"
471 " :rtype: :class:`Matrix`\n");
474 PyObject *vec =
NULL;
475 const char *axis =
NULL;
497 if (!PyArg_ParseTuple(args,
"di|O:Matrix.Rotation", &
angle, &matSize, &vec)) {
501 if (vec && PyUnicode_Check(vec)) {
502 axis = PyUnicode_AsUTF8((PyObject *)vec);
503 if (axis ==
NULL || axis[0] ==
'\0' || axis[1] !=
'\0' || axis[0] <
'X' || axis[0] >
'Z') {
504 PyErr_SetString(PyExc_ValueError,
505 "Matrix.Rotation(): "
506 "3rd argument axis value must be a 3D vector "
507 "or a string in 'X', 'Y', 'Z'");
517 if (!
ELEM(matSize, 2, 3, 4)) {
518 PyErr_SetString(PyExc_ValueError,
519 "Matrix.Rotation(): "
520 "can only return a 2x2 3x3 or 4x4 matrix");
523 if (matSize == 2 && (vec !=
NULL)) {
524 PyErr_SetString(PyExc_ValueError,
525 "Matrix.Rotation(): "
526 "cannot create a 2x2 rotation matrix around arbitrary axis");
529 if ((matSize == 3 || matSize == 4) && (axis ==
NULL) && (vec ==
NULL)) {
530 PyErr_SetString(PyExc_ValueError,
531 "Matrix.Rotation(): "
532 "axis of rotation for 3d and 4d matrices is required");
541 tvec, 3, 3, vec,
"Matrix.Rotation(angle, size, axis), invalid 'axis' arg") == -1) {
547 else if (matSize == 2) {
563 ".. classmethod:: Translation(vector)\n"
565 " Create a matrix representing a translation.\n"
567 " :arg vector: The translation vector.\n"
568 " :type vector: :class:`Vector`\n"
569 " :return: An identity matrix with a translation.\n"
570 " :rtype: :class:`Matrix`\n");
578 mat[3], 3, 4, value,
"mathutils.Matrix.Translation(vector), invalid vector arg") == -1) {
586 ".. classmethod:: Diagonal(vector)\n"
588 " Create a diagonal (scaling) matrix using the values from the vector.\n"
590 " :arg vector: The vector of values for the diagonal.\n"
591 " :type vector: :class:`Vector`\n"
592 " :return: A diagonal matrix.\n"
593 " :rtype: :class:`Matrix`\n");
596 float mat[16] = {0.0f};
600 vec, 2, 4, value,
"mathutils.Matrix.Diagonal(vector), invalid vector arg");
606 for (
int i = 0; i <
size; i++) {
607 mat[
size * i + i] = vec[i];
615 ".. classmethod:: Scale(factor, size, axis)\n"
617 " Create a matrix representing a scaling.\n"
619 " :arg factor: The factor of scaling to apply.\n"
620 " :type factor: float\n"
621 " :arg size: The size of the scale matrix to construct [2, 4].\n"
623 " :arg axis: Direction to influence scale. (optional).\n"
624 " :type axis: :class:`Vector`\n"
625 " :return: A new scale matrix.\n"
626 " :rtype: :class:`Matrix`\n");
629 PyObject *vec =
NULL;
653 if (!PyArg_ParseTuple(args,
"fi|O:Matrix.Scale", &factor, &matSize, &vec)) {
656 if (!
ELEM(matSize, 2, 3, 4)) {
657 PyErr_SetString(PyExc_ValueError,
659 "can only return a 2x2 3x3 or 4x4 matrix");
663 vec_size = (matSize == 2 ? 2 : 3);
668 "Matrix.Scale(factor, size, axis), invalid 'axis' arg") == -1) {
688 for (
x = 0;
x < vec_size;
x++) {
689 norm += tvec[
x] * tvec[
x];
692 for (
x = 0;
x < vec_size;
x++) {
696 mat[0] = 1 + ((factor - 1) * (tvec[0] * tvec[0]));
697 mat[1] = ((factor - 1) * (tvec[0] * tvec[1]));
698 mat[2] = ((factor - 1) * (tvec[0] * tvec[1]));
699 mat[3] = 1 + ((factor - 1) * (tvec[1] * tvec[1]));
702 mat[0] = 1 + ((factor - 1) * (tvec[0] * tvec[0]));
703 mat[1] = ((factor - 1) * (tvec[0] * tvec[1]));
704 mat[2] = ((factor - 1) * (tvec[0] * tvec[2]));
705 mat[3] = ((factor - 1) * (tvec[0] * tvec[1]));
706 mat[4] = 1 + ((factor - 1) * (tvec[1] * tvec[1]));
707 mat[5] = ((factor - 1) * (tvec[1] * tvec[2]));
708 mat[6] = ((factor - 1) * (tvec[0] * tvec[2]));
709 mat[7] = ((factor - 1) * (tvec[1] * tvec[2]));
710 mat[8] = 1 + ((factor - 1) * (tvec[2] * tvec[2]));
722 ".. classmethod:: OrthoProjection(axis, size)\n"
724 " Create a matrix to represent an orthographic projection.\n"
726 " :arg axis: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
727 " where a single axis is for a 2D matrix.\n"
728 " Or a vector for an arbitrary axis\n"
729 " :type axis: string or :class:`Vector`\n"
730 " :arg size: The size of the projection matrix to construct [2, 4].\n"
732 " :return: A new projection matrix.\n"
733 " :rtype: :class:`Matrix`\n");
759 if (!PyArg_ParseTuple(args,
"Oi:Matrix.OrthoProjection", &axis, &matSize)) {
762 if (!
ELEM(matSize, 2, 3, 4)) {
763 PyErr_SetString(PyExc_ValueError,
764 "Matrix.OrthoProjection(): "
765 "can only return a 2x2 3x3 or 4x4 matrix");
769 if (PyUnicode_Check(axis)) {
770 Py_ssize_t plane_len;
771 const char *plane = PyUnicode_AsUTF8AndSize(axis, &plane_len);
773 if (plane_len == 1 && plane[0] ==
'X') {
776 else if (plane_len == 1 && plane[0] ==
'Y') {
780 PyErr_Format(PyExc_ValueError,
781 "Matrix.OrthoProjection(): "
782 "unknown plane, expected: X, Y, not '%.200s'",
788 if (plane_len == 2 && plane[0] ==
'X' && plane[1] ==
'Y') {
792 else if (plane_len == 2 && plane[0] ==
'X' && plane[1] ==
'Z') {
796 else if (plane_len == 2 && plane[0] ==
'Y' && plane[1] ==
'Z') {
801 PyErr_Format(PyExc_ValueError,
802 "Matrix.OrthoProjection(): "
803 "unknown plane, expected: XY, XZ, YZ, not '%.200s'",
812 const int vec_size = (matSize == 2 ? 2 : 3);
819 "Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1) {
824 for (
x = 0;
x < vec_size;
x++) {
825 norm += tvec[
x] * tvec[
x];
828 for (
x = 0;
x < vec_size;
x++) {
832 mat[0] = 1 - (tvec[0] * tvec[0]);
833 mat[1] = -(tvec[0] * tvec[1]);
834 mat[2] = -(tvec[0] * tvec[1]);
835 mat[3] = 1 - (tvec[1] * tvec[1]);
837 else if (matSize > 2) {
838 mat[0] = 1 - (tvec[0] * tvec[0]);
839 mat[1] = -(tvec[0] * tvec[1]);
840 mat[2] = -(tvec[0] * tvec[2]);
841 mat[3] = -(tvec[0] * tvec[1]);
842 mat[4] = 1 - (tvec[1] * tvec[1]);
843 mat[5] = -(tvec[1] * tvec[2]);
844 mat[6] = -(tvec[0] * tvec[2]);
845 mat[7] = -(tvec[1] * tvec[2]);
846 mat[8] = 1 - (tvec[2] * tvec[2]);
857 ".. classmethod:: Shear(plane, size, factor)\n"
859 " Create a matrix to represent an shear transformation.\n"
861 " :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
862 " where a single axis is for a 2D matrix only.\n"
863 " :type plane: string\n"
864 " :arg size: The size of the shear matrix to construct [2, 4].\n"
866 " :arg factor: The factor of shear to apply. For a 3 or 4 *size* matrix\n"
867 " pass a pair of floats corresponding with the *plane* axis.\n"
868 " :type factor: float or float pair\n"
869 " :return: A new shear matrix.\n"
870 " :rtype: :class:`Matrix`\n");
895 if (!PyArg_ParseTuple(args,
"siO:Matrix.Shear", &plane, &matSize, &fac)) {
898 if (!
ELEM(matSize, 2, 3, 4)) {
899 PyErr_SetString(PyExc_ValueError,
901 "can only return a 2x2 3x3 or 4x4 matrix");
906 float const factor = PyFloat_AsDouble(fac);
908 if (factor == -1.0f && PyErr_Occurred()) {
909 PyErr_SetString(PyExc_TypeError,
911 "the factor to be a float");
919 if (
STREQ(plane,
"X")) {
922 else if (
STREQ(plane,
"Y")) {
926 PyErr_SetString(PyExc_ValueError,
928 "expected: X, Y or wrong matrix size for shearing plane");
945 if (
STREQ(plane,
"XY")) {
949 else if (
STREQ(plane,
"XZ")) {
953 else if (
STREQ(plane,
"YZ")) {
958 PyErr_SetString(PyExc_ValueError,
960 "expected: X, Y, XY, XZ, YZ");
984 memcpy(mat_dst->matrix, mat_src->matrix,
sizeof(
float) * (mat_dst->
num_col * mat_dst->
num_row));
989 const int mat_size =
sizeof(
float) * (
self->num_col *
self->num_row);
990 memset(
self->matrix, 0x0, mat_size);
992 const int num_row =
self->num_row;
993 for (
int col = 0;
col < col_row_max;
col++) {
994 self->matrix[(
col * num_row) +
col] = 1.0f;
1004 for (row = 0; row < mat_src->
num_row; row++) {
1014 if (
self->num_col == 2) {
1020 if (
self->num_col == 3) {
1058 const float *mat_src,
1071 for (i = 0; i < dim; i++) {
1072 for (j = 0; j < dim; j++) {
1102 float *in_mat =
self->matrix;
1113 switch (
self->num_col) {
1117 if (in_mat !=
self->matrix) {
1132 if (in_mat !=
self->matrix) {
1148 if (in_mat !=
self->matrix) {
1172 ".. method:: to_quaternion()\n"
1174 " Return a quaternion representation of the rotation matrix.\n"
1176 " :return: Quaternion representation of the rotation matrix.\n"
1177 " :rtype: :class:`Quaternion`\n");
1187 if ((
self->num_row < 3) || (
self->num_col < 3) || (
self->num_row !=
self->num_col)) {
1188 PyErr_SetString(PyExc_ValueError,
1189 "Matrix.to_quat(): "
1190 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
1193 if (
self->num_row == 3) {
1205 ".. method:: to_euler(order, euler_compat)\n"
1207 " Return an Euler representation of the rotation matrix\n"
1208 " (3x3 or 4x4 matrix only).\n"
1210 " :arg order: Optional rotation order argument in\n"
1211 " ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
1212 " :type order: string\n"
1213 " :arg euler_compat: Optional euler argument the new euler will be made\n"
1214 " compatible with (no axis flipping between them).\n"
1215 " Useful for converting a series of matrices to animation curves.\n"
1216 " :type euler_compat: :class:`Euler`\n"
1217 " :return: Euler representation of the matrix.\n"
1218 " :rtype: :class:`Euler`\n");
1221 const char *order_str =
NULL;
1223 float eul[3], eul_compatf[3];
1232 if (!PyArg_ParseTuple(args,
"|sO!:to_euler", &order_str, &
euler_Type, &eul_compat)) {
1245 if (
self->num_row == 3 &&
self->num_col == 3) {
1248 else if (
self->num_row == 4 &&
self->num_col == 4) {
1252 PyErr_SetString(PyExc_ValueError,
1253 "Matrix.to_euler(): "
1254 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
1289 ".. method:: resize_4x4()\n"
1291 " Resize the matrix to 4x4.\n");
1298 PyErr_SetString(PyExc_ValueError,
1299 "Matrix.resize_4x4(): "
1300 "cannot resize wrapped data - make a copy and resize that");
1303 if (
self->cb_user) {
1304 PyErr_SetString(PyExc_ValueError,
1305 "Matrix.resize_4x4(): "
1306 "cannot resize owned data - make a copy and resize that");
1312 PyErr_SetString(PyExc_MemoryError,
1313 "Matrix.resize_4x4(): "
1314 "problem allocating pointer space");
1320 for (
col = 0;
col <
self->num_col;
col++) {
1334 const int mat_size =
sizeof(
float) * (num_col * num_row);
1336 PyMem_Malloc(mat_size), num_col, num_row, Py_TYPE(
self));
1338 if ((
self->num_row == num_row) && (
self->num_col == num_col)) {
1339 memcpy(pymat->matrix,
self->matrix, mat_size);
1342 if ((
self->num_col < num_col) || (
self->num_row < num_row)) {
1345 const int col_len_src =
min_ii(num_col,
self->num_col);
1346 const int row_len_src =
min_ii(num_row,
self->num_row);
1347 for (
int col = 0;
col < col_len_src;
col++) {
1352 return (PyObject *)pymat;
1356 ".. method:: to_2x2()\n"
1358 " Return a 2x2 copy of this matrix.\n"
1360 " :return: a new matrix.\n"
1361 " :rtype: :class:`Matrix`\n");
1371 ".. method:: to_3x3()\n"
1373 " Return a 3x3 copy of this matrix.\n"
1375 " :return: a new matrix.\n"
1376 " :rtype: :class:`Matrix`\n");
1386 ".. method:: to_4x4()\n"
1388 " Return a 4x4 copy of this matrix.\n"
1390 " :return: a new matrix.\n"
1391 " :rtype: :class:`Matrix`\n");
1402 ".. method:: to_translation()\n"
1404 " Return the translation part of a 4 row matrix.\n"
1406 " :return: Return the translation of a matrix.\n"
1407 " :rtype: :class:`Vector`\n");
1414 if ((
self->num_row < 3) ||
self->num_col < 4) {
1415 PyErr_SetString(PyExc_ValueError,
1416 "Matrix.to_translation(): "
1417 "inappropriate matrix size");
1425 ".. method:: to_scale()\n"
1427 " Return the scale part of a 3x3 or 4x4 matrix.\n"
1429 " :return: Return the scale of a matrix.\n"
1430 " :rtype: :class:`Vector`\n"
1432 " .. note:: This method does not return a negative scale on any axis because it is "
1433 "not possible to obtain this data from the matrix alone.\n");
1445 if ((
self->num_row < 3) || (
self->num_col < 3)) {
1446 PyErr_SetString(PyExc_ValueError,
1447 "Matrix.to_scale(): "
1448 "inappropriate matrix size, 3x3 minimum size");
1465 if (
self->num_col !=
self->num_row) {
1466 PyErr_SetString(PyExc_ValueError,
1467 "Matrix.invert(ed): "
1468 "only square matrices are supported");
1477 switch (PyTuple_GET_SIZE(args)) {
1484 PyErr_SetString(PyExc_TypeError,
1486 "expects a matrix argument or nothing");
1491 PyErr_SetString(PyExc_TypeError,
1493 "matrix argument has different dimensions");
1500 PyErr_SetString(PyExc_ValueError,
1501 "Matrix.invert(ed): "
1502 "takes at most one argument");
1509 PyErr_SetString(PyExc_ValueError,
1510 "Matrix.invert(ed): "
1511 "matrix does not have an inverse");
1516 ".. method:: invert(fallback=None)\n"
1518 " Set the matrix to its inverse.\n"
1520 " :arg fallback: Set the matrix to this value when the inverse cannot be calculated\n"
1521 " (instead of raising a :exc:`ValueError` exception).\n"
1522 " :type fallback: :class:`Matrix`\n"
1524 " .. seealso:: `Inverse matrix <https://en.wikipedia.org/wiki/Inverse_matrix>`__ on "
1544 if (PyTuple_GET_SIZE(args) == 1) {
1551 if (
self != fallback) {
1566 ".. method:: inverted(fallback=None)\n"
1568 " Return an inverted copy of the matrix.\n"
1570 " :arg fallback: return this when the inverse can't be calculated\n"
1571 " (instead of raising a :exc:`ValueError`).\n"
1572 " :type fallback: any\n"
1573 " :return: the inverted matrix or fallback when given.\n"
1574 " :rtype: :class:`Matrix`\n");
1595 if (PyTuple_GET_SIZE(args) == 1) {
1596 PyObject *fallback = PyTuple_GET_ITEM(args, 0);
1597 Py_INCREF(fallback);
1631 Matrix_invert_safe_doc,
1632 ".. method:: invert_safe()\n"
1634 " Set the matrix to its inverse, will never error.\n"
1635 " If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, "
1636 "to get an invertible one.\n"
1637 " If tweaked matrix is still degenerated, set to the identity matrix instead.\n"
1639 " .. seealso:: `Inverse Matrix <https://en.wikipedia.org/wiki/Inverse_matrix>`__ on "
1658 ".. method:: inverted_safe()\n"
1660 " Return an inverted copy of the matrix, will never error.\n"
1661 " If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, "
1662 "to get an invertible one.\n"
1663 " If tweaked matrix is still degenerated, return the identity matrix instead.\n"
1665 " :return: the inverted matrix.\n"
1666 " :rtype: :class:`Matrix`\n");
1686 Matrix_adjugate_doc,
1687 ".. method:: adjugate()\n"
1689 " Set the matrix to its adjugate.\n"
1691 " :raises ValueError: if the matrix cannot be adjugate.\n"
1693 " .. seealso:: `Adjugate matrix <https://en.wikipedia.org/wiki/Adjugate_matrix>`__ on "
1701 if (
self->num_col !=
self->num_row) {
1702 PyErr_SetString(PyExc_ValueError,
1703 "Matrix.adjugate(d): "
1704 "only square matrices are supported");
1709 if (
self->num_col <= 4) {
1714 PyExc_ValueError,
"Matrix adjugate(d): size (%d) unsupported", (
int)
self->num_col);
1723 ".. method:: adjugated()\n"
1725 " Return an adjugated copy of the matrix.\n"
1727 " :return: the adjugated matrix.\n"
1728 " :rtype: :class:`Matrix`\n"
1729 " :raises ValueError: if the matrix cannot be adjugated\n");
1737 ".. method:: rotate(other)\n"
1739 " Rotates the matrix by another mathutils value.\n"
1741 " :arg other: rotation component of mathutils value\n"
1742 " :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
1744 " .. note:: If any of the columns are not unit length this may not have desired results.\n");
1747 float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
1757 if (
self->num_row != 3 ||
self->num_col != 3) {
1758 PyErr_SetString(PyExc_ValueError,
1760 "must have 3x3 dimensions");
1775 ".. method:: decompose()\n"
1777 " Return the translation, rotation, and scale components of this matrix.\n"
1779 " :return: tuple of translation, rotation, and scale\n"
1780 " :rtype: (:class:`Vector`, :class:`Quaternion`, :class:`Vector`)");
1789 if (
self->num_row != 4 ||
self->num_col != 4) {
1790 PyErr_SetString(PyExc_ValueError,
1791 "Matrix.decompose(): "
1792 "inappropriate matrix size - expects 4x4 matrix");
1803 ret = PyTuple_New(3);
1812 ".. function:: lerp(other, factor)\n"
1814 " Returns the interpolation of two matrices. Uses polar decomposition, see"
1815 " \"Matrix Animation and Polar Decomposition\", Shoemake and Duff, 1992.\n"
1817 " :arg other: value to interpolate with.\n"
1818 " :type other: :class:`Matrix`\n"
1819 " :arg factor: The interpolation value in [0.0, 1.0].\n"
1820 " :type factor: float\n"
1821 " :return: The interpolated matrix.\n"
1822 " :rtype: :class:`Matrix`\n");
1828 if (!PyArg_ParseTuple(args,
"O!f:lerp", &
matrix_Type, &mat2, &fac)) {
1833 PyErr_SetString(PyExc_ValueError,
1835 "expects both matrix objects of the same dimensions");
1844 if (
self->num_col == 4 &&
self->num_row == 4) {
1845 #ifdef MATH_STANDALONE
1846 blend_m4_m4m4((
float(*)[4])mat, (
float(*)[4])
self->matrix, (
float(*)[4])mat2->matrix, fac);
1848 interp_m4_m4m4((
float(*)[4])mat, (
float(*)[4])
self->matrix, (
float(*)[4])mat2->matrix, fac);
1851 else if (
self->num_col == 3 &&
self->num_row == 3) {
1852 #ifdef MATH_STANDALONE
1853 blend_m3_m3m3((
float(*)[3])mat, (
float(*)[3])
self->matrix, (
float(*)[3])mat2->matrix, fac);
1855 interp_m3_m3m3((
float(*)[3])mat, (
float(*)[3])
self->matrix, (
float(*)[3])mat2->matrix, fac);
1859 PyErr_SetString(PyExc_ValueError,
1861 "only 3x3 and 4x4 matrices supported");
1870 Matrix_determinant_doc,
1871 ".. method:: determinant()\n"
1873 " Return the determinant of a matrix.\n"
1875 " :return: Return the determinant of a matrix.\n"
1878 " .. seealso:: `Determinant <https://en.wikipedia.org/wiki/Determinant>`__ on Wikipedia.\n");
1885 if (
self->num_col !=
self->num_row) {
1886 PyErr_SetString(PyExc_ValueError,
1887 "Matrix.determinant(): "
1888 "only square matrices are supported");
1896 Matrix_transpose_doc,
1897 ".. method:: transpose()\n"
1899 " Set the matrix to its transpose.\n"
1901 " .. seealso:: `Transpose <https://en.wikipedia.org/wiki/Transpose>`__ on Wikipedia.\n");
1908 if (
self->num_col !=
self->num_row) {
1909 PyErr_SetString(PyExc_ValueError,
1910 "Matrix.transpose(d): "
1911 "only square matrices are supported");
1915 if (
self->num_col == 2) {
1920 else if (
self->num_col == 3) {
1932 ".. method:: transposed()\n"
1934 " Return a new, transposed matrix.\n"
1936 " :return: a transposed matrix\n"
1937 " :rtype: :class:`Matrix`\n");
1945 ".. method:: normalize()\n"
1947 " Normalize each of the matrix columns.\n");
1954 if (
self->num_col !=
self->num_row) {
1955 PyErr_SetString(PyExc_ValueError,
1956 "Matrix.normalize(): "
1957 "only square matrices are supported");
1961 if (
self->num_col == 3) {
1964 else if (
self->num_col == 4) {
1968 PyErr_SetString(PyExc_ValueError,
1969 "Matrix.normalize(): "
1970 "can only use a 3x3 or 4x4 matrix");
1978 ".. method:: normalized()\n"
1980 " Return a column normalized matrix\n"
1982 " :return: a column normalized matrix\n"
1983 " :rtype: :class:`Matrix`\n");
1991 ".. method:: zero()\n"
1993 " Set all the matrix values to zero.\n"
1995 " :rtype: :class:`Matrix`\n");
2015 if (
self->num_col == 2) {
2018 else if (
self->num_col == 3) {
2027 ".. method:: identity()\n"
2029 " Set the matrix to the identity matrix.\n"
2031 " .. note:: An object with a location and rotation of zero, and a scale of one\n"
2032 " will have an identity matrix.\n"
2034 " .. seealso:: `Identity matrix <https://en.wikipedia.org/wiki/Identity_matrix>`__ "
2042 if (
self->num_col !=
self->num_row) {
2043 PyErr_SetString(PyExc_ValueError,
2044 "Matrix.identity(): "
2045 "only square matrices are supported");
2066 ".. method:: copy()\n"
2068 " Returns a copy of this matrix.\n"
2070 " :return: an instance of itself\n"
2071 " :rtype: :class:`Matrix`\n");
2099 for (row = 0; row <
self->num_row; row++) {
2100 rows[row] = PyTuple_New(
self->num_col);
2101 for (
col = 0;
col <
self->num_col;
col++) {
2102 PyTuple_SET_ITEM(rows[row],
col, PyFloat_FromDouble(
MATRIX_ITEM(
self, row,
col)));
2105 switch (
self->num_row) {
2107 return PyUnicode_FromFormat(
2114 return PyUnicode_FromFormat(
2123 return PyUnicode_FromFormat(
2134 Py_FatalError(
"Matrix(): invalid row size!");
2138 #ifndef MATH_STANDALONE
2155 for (
col = 0;
col <
self->num_col;
col++) {
2157 for (row = 0; row <
self->num_row; row++) {
2159 dummy_buf,
sizeof(dummy_buf),
"%.4f",
MATRIX_ITEM(
self, row,
col));
2166 for (row = 0; row <
self->num_row; row++) {
2167 for (
col = 0;
col <
self->num_col;
col++) {
2202 res = ok ? Py_False : Py_True;
2209 res = Py_NotImplemented;
2212 PyErr_BadArgument();
2216 return Py_INCREF_RET(res);
2241 return self->num_row;
2252 if (row < 0 || row >=
self->num_row) {
2253 PyErr_SetString(PyExc_IndexError,
2254 "matrix[attribute]: "
2255 "array index out of range");
2268 if (col < 0 || col >=
self->num_col) {
2269 PyErr_SetString(PyExc_IndexError,
2270 "matrix[attribute]: "
2271 "array index out of range");
2289 if (row >=
self->num_row || row < 0) {
2290 PyErr_SetString(PyExc_IndexError,
"matrix[attribute] = x: bad row");
2295 vec,
self->num_col,
self->num_col, value,
"matrix[i] = value assignment") == -1) {
2300 for (
col = 0;
col <
self->num_col;
col++) {
2316 PyErr_SetString(PyExc_IndexError,
"matrix[attribute] = x: bad col");
2321 vec,
self->num_row,
self->num_row, value,
"matrix[i] = value assignment") == -1) {
2326 for (row = 0; row <
self->num_row; row++) {
2348 begin =
MIN2(begin, end);
2350 tuple = PyTuple_New(end - begin);
2352 PyTuple_SET_ITEM(tuple,
2364 PyObject *value_fast;
2372 begin =
MIN2(begin, end);
2375 if (!(value_fast = PySequence_Fast(value,
"matrix[begin:end] = value"))) {
2380 PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
2381 const int size = end - begin;
2386 if (PySequence_Fast_GET_SIZE(value_fast) !=
size) {
2387 Py_DECREF(value_fast);
2388 PyErr_SetString(PyExc_ValueError,
2389 "matrix[begin:end] = []: "
2390 "size mismatch in slice assignment");
2394 memcpy(mat,
self->matrix,
self->num_col *
self->num_row *
sizeof(
float));
2397 for (row = begin; row < end; row++) {
2399 PyObject *item = value_fast_items[row - begin];
2402 vec,
self->num_col,
self->num_col, item,
"matrix[begin:end] = value assignment") ==
2404 Py_DECREF(value_fast);
2408 for (
col = 0;
col <
self->num_col;
col++) {
2409 mat[
col *
self->num_row + row] = vec[
col];
2413 Py_DECREF(value_fast);
2416 memcpy(
self->matrix, mat,
self->num_col *
self->num_row *
sizeof(
float));
2432 PyErr_Format(PyExc_TypeError,
2433 "Matrix addition: (%s + %s) "
2434 "invalid type for this operation",
2435 Py_TYPE(m1)->tp_name,
2436 Py_TYPE(m2)->tp_name);
2444 if (mat1->
num_col != mat2->num_col || mat1->
num_row != mat2->num_row) {
2445 PyErr_SetString(PyExc_ValueError,
2447 "matrices must have the same dimensions for this operation");
2466 PyErr_Format(PyExc_TypeError,
2467 "Matrix subtraction: (%s - %s) "
2468 "invalid type for this operation",
2469 Py_TYPE(m1)->tp_name,
2470 Py_TYPE(m2)->tp_name);
2478 if (mat1->
num_col != mat2->num_col || mat1->
num_row != mat2->num_row) {
2479 PyErr_SetString(PyExc_ValueError,
2481 "matrices must have the same dimensions for this operation");
2521 if ((mat1->
num_row != mat2->num_row) || (mat1->
num_col != mat2->num_col)) {
2522 PyErr_SetString(PyExc_ValueError,
2523 "matrix1 * matrix2: matrix1 number of rows/columns "
2524 "and the matrix2 number of rows/columns must be the same");
2534 if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) {
2540 if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) {
2545 PyErr_Format(PyExc_TypeError,
2546 "Element-wise multiplication: "
2547 "not supported between '%.200s' and '%.200s' types",
2548 Py_TYPE(m1)->tp_name,
2549 Py_TYPE(m2)->tp_name);
2575 if ((mat1->
num_row != mat2->num_row) || (mat1->
num_col != mat2->num_col)) {
2576 PyErr_SetString(PyExc_ValueError,
2577 "matrix1 *= matrix2: matrix1 number of rows/columns "
2578 "and the matrix2 number of rows/columns must be the same");
2584 else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) {
2589 PyErr_Format(PyExc_TypeError,
2590 "In place element-wise multiplication: "
2591 "not supported between '%.200s' and '%.200s' types",
2592 Py_TYPE(m1)->tp_name,
2593 Py_TYPE(m2)->tp_name);
2628 if (mat1->
num_col != mat2->num_row) {
2629 PyErr_SetString(PyExc_ValueError,
2630 "matrix1 * matrix2: matrix1 number of columns "
2631 "and the matrix2 number of rows must be the same");
2635 for (
col = 0;
col < mat2->num_col;
col++) {
2636 for (row = 0; row < mat1->
num_row; row++) {
2638 for (item = 0; item < mat1->
num_col; item++) {
2670 PyErr_Format(PyExc_TypeError,
2671 "Matrix multiplication: "
2672 "not supported between '%.200s' and '%.200s' types",
2673 Py_TYPE(m1)->tp_name,
2674 Py_TYPE(m2)->tp_name);
2701 if (mat1->
num_col != mat2->num_row) {
2702 PyErr_SetString(PyExc_ValueError,
2703 "matrix1 * matrix2: matrix1 number of columns "
2704 "and the matrix2 number of rows must be the same");
2708 for (
col = 0;
col < mat2->num_col;
col++) {
2709 for (row = 0; row < mat1->
num_row; row++) {
2711 for (item = 0; item < mat1->
num_col; item++) {
2721 memcpy(mat1->matrix, mat, (mat1->
num_row * mat1->
num_col) *
sizeof(
float));
2724 PyErr_Format(PyExc_TypeError,
2725 "In place matrix multiplication: "
2726 "not supported between '%.200s' and '%.200s' types",
2727 Py_TYPE(m1)->tp_name,
2728 Py_TYPE(m2)->tp_name);
2743 (ssizessizeargfunc)
NULL,
2745 (ssizessizeobjargproc)
NULL,
2753 if (PyIndex_Check(item)) {
2755 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
2756 if (i == -1 && PyErr_Occurred()) {
2764 if (PySlice_Check(item)) {
2765 Py_ssize_t start, stop, step, slicelength;
2767 if (PySlice_GetIndicesEx(item,
self->num_row, &start, &stop, &step, &slicelength) < 0) {
2771 if (slicelength <= 0) {
2772 return PyTuple_New(0);
2778 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with matrices");
2783 PyExc_TypeError,
"matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
2789 if (PyIndex_Check(item)) {
2790 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
2791 if (i == -1 && PyErr_Occurred()) {
2799 if (PySlice_Check(item)) {
2800 Py_ssize_t start, stop, step, slicelength;
2802 if (PySlice_GetIndicesEx(item,
self->num_row, &start, &stop, &step, &slicelength) < 0) {
2810 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with matrices");
2815 PyExc_TypeError,
"matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
2864 PyDoc_STRVAR(Matrix_translation_doc,
"The translation component of the matrix.\n\n:type: Vector");
2874 if (
self->num_row != 4 ||
self->num_col != 4) {
2875 PyErr_SetString(PyExc_AttributeError,
2876 "Matrix.translation: "
2877 "inappropriate matrix size, must be 4x4");
2896 if (
self->num_row != 4 ||
self->num_col != 4) {
2897 PyErr_SetString(PyExc_AttributeError,
2898 "Matrix.translation: "
2899 "inappropriate matrix size, must be 4x4");
2915 "Access the matrix by rows (default), (read-only).\n\n:type: Matrix Access");
2923 "Access the matrix by columns, 3x3 and 4x4 only, (read-only).\n\n:type: Matrix Access");
2930 "The average scale applied to each axis (read-only).\n\n:type: float");
2940 if ((
self->num_row < 3) || (
self->num_col < 3)) {
2941 PyErr_SetString(PyExc_AttributeError,
2942 "Matrix.median_scale: "
2943 "inappropriate matrix size, 3x3 minimum");
2953 "True if this matrix results in a negative scale, 3x3 and 4x4 only, "
2954 "(read-only).\n\n:type: bool");
2962 if (
self->num_row == 4 &&
self->num_col == 4) {
2965 if (
self->num_row == 3 &&
self->num_col == 3) {
2969 PyErr_SetString(PyExc_AttributeError,
2970 "Matrix.is_negative: "
2971 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
2976 "True if this matrix is orthogonal, 3x3 and 4x4 only, (read-only).\n\n:type: bool");
2984 if (
self->num_row == 4 &&
self->num_col == 4) {
2987 if (
self->num_row == 3 &&
self->num_col == 3) {
2991 PyErr_SetString(PyExc_AttributeError,
2992 "Matrix.is_orthogonal: "
2993 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
2998 "True if this matrix has got orthogonal axis vectors, 3x3 and 4x4 only, "
2999 "(read-only).\n\n:type: bool");
3007 if (
self->num_row == 4 &&
self->num_col == 4) {
3010 if (
self->num_row == 3 &&
self->num_col == 3) {
3014 PyErr_SetString(PyExc_AttributeError,
3015 "Matrix.is_orthogonal_axis_vectors: "
3016 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
3028 Matrix_translation_doc,
3036 Matrix_is_orthogonal_doc,
3038 {
"is_orthogonal_axis_vectors",
3041 Matrix_is_orthogonal_axis_vectors_doc,
3060 {
"determinant", (PyCFunction)
Matrix_determinant, METH_NOARGS, Matrix_determinant_doc},
3061 {
"decompose", (PyCFunction)
Matrix_decompose, METH_NOARGS, Matrix_decompose_doc},
3064 {
"zero", (PyCFunction)
Matrix_zero, METH_NOARGS, Matrix_zero_doc},
3065 {
"identity", (PyCFunction)
Matrix_identity, METH_NOARGS, Matrix_identity_doc},
3068 {
"transpose", (PyCFunction)
Matrix_transpose, METH_NOARGS, Matrix_transpose_doc},
3069 {
"transposed", (PyCFunction)
Matrix_transposed, METH_NOARGS, Matrix_transposed_doc},
3070 {
"normalize", (PyCFunction)
Matrix_normalize, METH_NOARGS, Matrix_normalize_doc},
3071 {
"normalized", (PyCFunction)
Matrix_normalized, METH_NOARGS, Matrix_normalized_doc},
3072 {
"invert", (PyCFunction)
Matrix_invert, METH_VARARGS, Matrix_invert_doc},
3073 {
"inverted", (PyCFunction)
Matrix_inverted, METH_VARARGS, Matrix_inverted_doc},
3074 {
"invert_safe", (PyCFunction)
Matrix_invert_safe, METH_NOARGS, Matrix_invert_safe_doc},
3076 {
"adjugate", (PyCFunction)
Matrix_adjugate, METH_NOARGS, Matrix_adjugate_doc},
3077 {
"adjugated", (PyCFunction)
Matrix_adjugated, METH_NOARGS, Matrix_adjugated_doc},
3078 {
"to_2x2", (PyCFunction)
Matrix_to_2x2, METH_NOARGS, Matrix_to_2x2_doc},
3079 {
"to_3x3", (PyCFunction)
Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc},
3080 {
"to_4x4", (PyCFunction)
Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc},
3082 {
"resize_4x4", (PyCFunction)
Matrix_resize_4x4, METH_NOARGS, Matrix_resize_4x4_doc},
3083 {
"rotate", (PyCFunction)
Matrix_rotate, METH_O, Matrix_rotate_doc},
3086 {
"to_euler", (PyCFunction)
Matrix_to_euler, METH_VARARGS, Matrix_to_euler_doc},
3088 {
"to_scale", (PyCFunction)
Matrix_to_scale, METH_NOARGS, Matrix_to_scale_doc},
3092 {
"lerp", (PyCFunction)
Matrix_lerp, METH_VARARGS, Matrix_lerp_doc},
3093 {
"copy", (PyCFunction)
Matrix_copy, METH_NOARGS, Matrix_copy_doc},
3094 {
"__copy__", (PyCFunction)
Matrix_copy, METH_NOARGS, Matrix_copy_doc},
3095 {
"__deepcopy__", (PyCFunction)
Matrix_deepcopy, METH_VARARGS, Matrix_copy_doc},
3101 {
"Identity", (PyCFunction)
C_Matrix_Identity, METH_VARARGS | METH_CLASS, C_Matrix_Identity_doc},
3102 {
"Rotation", (PyCFunction)
C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc},
3103 {
"Scale", (PyCFunction)
C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc},
3104 {
"Shear", (PyCFunction)
C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc},
3105 {
"Diagonal", (PyCFunction)
C_Matrix_Diagonal, METH_O | METH_CLASS, C_Matrix_Diagonal_doc},
3108 METH_O | METH_CLASS,
3109 C_Matrix_Translation_doc},
3112 METH_VARARGS | METH_CLASS,
3113 C_Matrix_OrthoProjection_doc},
3120 ".. class:: Matrix([rows])\n"
3122 " This object gives access to Matrices in Blender, supporting square and rectangular\n"
3123 " matrices from 2x2 up to 4x4.\n"
3125 " :param rows: Sequence of rows.\n"
3126 " When omitted, a 4x4 identity matrix is constructed.\n"
3127 " :type rows: 2d number sequence\n");
3129 PyVarObject_HEAD_INIT(
NULL, 0)
"Matrix",
3143 #ifndef MATH_STANDALONE
3151 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
3183 PyTypeObject *base_type)
3189 if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) {
3190 PyErr_SetString(PyExc_RuntimeError,
3192 "row and column sizes must be between 2 and 4");
3196 mat_alloc = PyMem_Malloc(num_col * num_row *
sizeof(
float));
3198 PyErr_SetString(PyExc_MemoryError,
3200 "problem allocating data");
3206 self->matrix = mat_alloc;
3207 self->num_col = num_col;
3208 self->num_row = num_row;
3211 self->cb_user =
NULL;
3212 self->cb_type =
self->cb_subtype = 0;
3215 memcpy(
self->matrix, mat, num_col * num_row *
sizeof(
float));
3217 else if (num_col == num_row) {
3223 memset(
self->matrix, 0, num_col * num_row *
sizeof(
float));
3228 PyMem_Free(mat_alloc);
3231 return (PyObject *)
self;
3237 PyTypeObject *base_type)
3242 if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) {
3243 PyErr_SetString(PyExc_RuntimeError,
3245 "row and column sizes must be between 2 and 4");
3251 self->num_col = num_col;
3252 self->num_row = num_row;
3255 self->cb_user =
NULL;
3256 self->cb_type =
self->cb_subtype = 0;
3261 return (PyObject *)
self;
3270 self->cb_user = cb_user;
3271 self->cb_type = cb_type;
3272 self->cb_subtype = cb_subtype;
3273 PyObject_GC_Track(
self);
3275 return (PyObject *)
self;
3284 PyTypeObject *base_type)
3292 return (PyObject *)
self;
3302 PyExc_TypeError,
"expected a mathutils.Matrix, not a %.200s", Py_TYPE(pymat)->tp_name);
3333 PyErr_SetString(PyExc_ValueError,
"matrix must be 2x2");
3350 PyErr_SetString(PyExc_ValueError,
"matrix must be 3x3");
3367 PyErr_SetString(PyExc_ValueError,
"matrix must be 4x4");
3386 Py_VISIT(
self->matrix_user);
3392 Py_CLEAR(
self->matrix_user);
3398 if (
self->matrix_user) {
3399 PyObject_GC_UnTrack(
self);
3403 Py_TYPE(
self)->tp_free(
self);
3410 return (
self->type ==
MAT_ACCESS_ROW) ?
self->matrix_user->num_row :
self->matrix_user->num_col;
3420 int matrix_access_len;
3424 matrix_access_len = matrix_user->
num_row;
3428 matrix_access_len = matrix_user->
num_col;
3432 CLAMP(begin, 0, matrix_access_len);
3434 end = (matrix_access_len + 1) + end;
3436 CLAMP(end, 0, matrix_access_len);
3437 begin =
MIN2(begin, end);
3439 tuple = PyTuple_New(end - begin);
3441 PyTuple_SET_ITEM(tuple,
count - begin, Matrix_item_new(matrix_user,
count));
3451 if (PyIndex_Check(item)) {
3453 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
3454 if (i == -1 && PyErr_Occurred()) {
3469 if (PySlice_Check(item)) {
3470 Py_ssize_t start, stop, step, slicelength;
3472 if (PySlice_GetIndicesEx(item,
MatrixAccess_len(
self), &start, &stop, &step, &slicelength) <
3477 if (slicelength <= 0) {
3478 return PyTuple_New(0);
3484 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with matrix accessors");
3489 PyExc_TypeError,
"matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
3497 if (PyIndex_Check(item)) {
3498 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
3499 if (i == -1 && PyErr_Occurred()) {
3518 PyExc_TypeError,
"matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
3526 PyObject *iter =
NULL;
3532 iter = PyObject_GetIter(
ret);
3546 PyVarObject_HEAD_INIT(
NULL, 0)
"MatrixAccess",
3564 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
3583 return (PyObject *)matrix_access;
typedef float(TangentPoint)[2]
#define BLI_assert_unreachable()
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
bool is_negative_m3(const float mat[3][3])
void unit_m2(float m[2][2])
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void adjoint_m3_m3(float R[3][3], const float M[3][3])
void unit_m3(float m[3][3])
void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
#define PSEUDOINVERSE_EPSILON
void unit_m4(float m[4][4])
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4])
void normalize_m3(float R[3][3]) ATTR_NONNULL()
float determinant_m2(float a, float b, float c, float d)
bool is_orthogonal_m3(const float mat[3][3])
bool is_orthonormal_m3(const float mat[3][3])
float mat3_to_scale(const float M[3][3])
void adjoint_m4_m4(float R[4][4], const float M[4][4])
float determinant_m4(const float m[4][4])
void copy_m2_m2(float m1[2][2], const float m2[2][2])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], const float t)
float determinant_m3_array(const float m[3][3])
bool is_negative_m4(const float mat[4][4])
void blend_m3_m3m3(float out[3][3], const float dst[3][3], const float src[3][3], const float srcweight)
void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], const float t)
void transpose_m3(float R[3][3])
bool is_orthogonal_m4(const float mat[4][4])
float determinant_m3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3)
void blend_m4_m4m4(float out[4][4], const float dst[4][4], const float src[4][4], const float srcweight)
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void transpose_m4(float R[4][4])
bool is_orthonormal_m4(const float mat[4][4])
void normalize_m4(float R[4][4]) ATTR_NONNULL()
void adjoint_m2_m2(float R[2][2], const float M[2][2])
void angle_to_mat2(float R[2][2], const float angle)
void axis_angle_to_mat3_single(float R[3][3], const char axis, const float angle)
void mat3_to_quat(float q[4], const float mat[3][3])
void mat3_normalized_to_compatible_eul(float eul[3], const float old[3], float mat[3][3])
void mat3_normalized_to_eul(float eul[3], const float mat[3][3])
void mat3_normalized_to_compatible_eulO(float eul[3], const float old[3], const short order, const float mat[3][3])
void mat4_to_quat(float q[4], const float mat[4][4])
void axis_angle_to_mat3(float R[3][3], const float axis[3], const float angle)
float angle_wrap_rad(float angle)
void mat3_normalized_to_eulO(float eul[3], const short order, const float mat[3][3])
void copy_vn_fl(float *array_tar, const int size, const float val)
void mul_vn_vn_fl(float *array_tar, const float *array_src, const int size, const float f)
void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size)
void add_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void mul_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size)
void mul_vn_vn(float *array_tar, const float *array_src, const int size)
void mul_vn_fl(float *array_tar, const int size, const float f)
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
typedef double(DMatrix)[4][4]
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint order
Group RGB to Bright Vector Camera CLAMP
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
PyObject * BaseMathObject_freeze(BaseMathObject *self)
PyObject * BaseMathObject_is_frozen_get(BaseMathObject *self, void *UNUSED(closure))
PyObject * BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closure))
PyObject * mathutils_dynstr_to_py(struct DynStr *ds)
Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
void BaseMathObject_dealloc(BaseMathObject *self)
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
PyObject * BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure))
char BaseMathObject_is_wrapped_doc[]
char BaseMathObject_is_frozen_doc[]
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
char BaseMathObject_owner_doc[]
char BaseMathObject_freeze_doc[]
int BaseMathObject_clear(BaseMathObject *self)
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
#define BaseMath_ReadCallback_ForWrite(_self)
#define BaseMath_WriteCallback(_self)
#define BASE_MATH_NEW(struct_name, root_type, base_type)
#define BaseMathObject_Prepare_ForHash(_self)
int column_vector_multiplication(float r_vec[4], VectorObject *vec, MatrixObject *mat)
#define BASE_MATH_FLAG_DEFAULT
#define BaseMath_Prepare_ForWrite(_self)
#define BaseMath_ReadCallback(_self)
short euler_order_from_string(const char *str, const char *error_prefix)
PyObject * Euler_CreatePyObject(const float eul[3], const short order, PyTypeObject *base_type)
int Matrix_Parse3x3(PyObject *o, void *p)
static bool matrix_invert_internal(const MatrixObject *self, float *r_mat)
static int Matrix_len(MatrixObject *self)
static PyObject * C_Matrix_Identity(PyObject *cls, PyObject *args)
static PyMappingMethods MatrixAccess_AsMapping
static PyGetSetDef Matrix_getseters[]
static PyObject * Matrix_to_4x4(MatrixObject *self)
static PyObject * Matrix_lerp(MatrixObject *self, PyObject *args)
static PyObject * Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static int mathutils_matrix_col_set(BaseMathObject *bmo, int col)
PyObject * Matrix_CreatePyObject_cb(PyObject *cb_user, const ushort num_col, const ushort num_row, uchar cb_type, uchar cb_subtype)
static PyObject * Matrix_richcmpr(PyObject *a, PyObject *b, int op)
static PyObject * C_Matrix_OrthoProjection(PyObject *cls, PyObject *args)
int Matrix_ParseAny(PyObject *o, void *p)
static PyObject * matrix_mul_float(MatrixObject *mat, const float scalar)
static int mathutils_matrix_row_set(BaseMathObject *bmo, int row)
static int matrix_row_vector_check(MatrixObject *mat, VectorObject *vec, int row)
static int mathutils_matrix_row_get_index(BaseMathObject *bmo, int row, int col)
static PyObject * Matrix_resize_4x4(MatrixObject *self)
static int Matrix_ass_subscript(MatrixObject *self, PyObject *item, PyObject *value)
static int mathutils_matrix_row_set_index(BaseMathObject *bmo, int row, int col)
static PyObject * Matrix_invert_safe(MatrixObject *self)
static int mathutils_matrix_col_get(BaseMathObject *bmo, int col)
static PyObject * Matrix_item_col(MatrixObject *self, int col)
static PyObject * Matrix_to_euler(MatrixObject *self, PyObject *args)
static PyObject * Matrix_imul(PyObject *m1, PyObject *m2)
static PyObject * Matrix_translation_get(MatrixObject *self, void *UNUSED(closure))
static void matrix_transpose_internal(float mat_dst_fl[], const MatrixObject *mat_src)
static void matrix_identity_internal(MatrixObject *self)
static PyObject * Matrix_normalize(MatrixObject *self)
static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNUSED(closure))
static PyObject * Matrix_add(PyObject *m1, PyObject *m2)
static PyObject * matrix__apply_to_copy(PyObject *(*matrix_func)(MatrixObject *), MatrixObject *self)
PyObject * Matrix_CreatePyObject_wrap(float *mat, const ushort num_col, const ushort num_row, PyTypeObject *base_type)
static PyObject * Matrix_to_quaternion(MatrixObject *self)
static int mathutils_matrix_row_check(BaseMathObject *bmo)
static PyObject * Matrix_mul(PyObject *m1, PyObject *m2)
static int MatrixAccess_clear(MatrixAccessObject *self)
static float matrix_determinant_internal(const MatrixObject *self)
static PyObject * Matrix_str(MatrixObject *self)
static PyObject * Matrix_row_get(MatrixObject *self, void *UNUSED(closure))
static PyObject * Matrix_to_3x3(MatrixObject *self)
PyDoc_STRVAR(C_Matrix_Identity_doc, ".. classmethod:: Identity(size)\n" "\n" " Create an identity matrix.\n" "\n" " :arg size: The size of the identity matrix to construct [2, 4].\n" " :type size: int\n" " :return: A new identity matrix.\n" " :rtype: :class:`Matrix`\n")
static void matrix_unit_internal(MatrixObject *self)
Mathutils_Callback mathutils_matrix_col_cb
static void adjoint_matrix_n(float *mat_dst, const float *mat_src, const ushort dim)
static bool matrix_invert_is_compat(const MatrixObject *self)
static PyObject * Matrix_inverted_noargs(MatrixObject *self)
static int mathutils_matrix_translation_set_index(BaseMathObject *bmo, int col, int row)
PyTypeObject matrix_access_Type
static PyObject * Matrix_is_orthogonal_get(MatrixObject *self, void *UNUSED(closure))
PyObject * Matrix_CreatePyObject_alloc(float *mat, const ushort num_col, const ushort num_row, PyTypeObject *base_type)
static PyNumberMethods Matrix_NumMethods
static PyObject * C_Matrix_Translation(PyObject *cls, PyObject *value)
static PyObject * Matrix_transposed(MatrixObject *self)
static PyObject * Matrix_col_get(MatrixObject *self, void *UNUSED(closure))
static PyObject * MatrixAccess_iter(MatrixAccessObject *self)
static PyObject * Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closure))
static PyObject * C_Matrix_Rotation(PyObject *cls, PyObject *args)
static PyObject * Matrix_is_orthogonal_axis_vectors_get(MatrixObject *self, void *UNUSED(closure))
static PySequenceMethods Matrix_SeqMethods
static PyObject * Matrix_decompose(MatrixObject *self)
static PyObject * Matrix_subscript(MatrixObject *self, PyObject *item)
static int mathutils_matrix_col_get_index(BaseMathObject *bmo, int col, int row)
static PyObject * Matrix_repr(MatrixObject *self)
static PyObject * C_Matrix_Scale(PyObject *cls, PyObject *args)
static PyObject * MatrixAccess_slice(MatrixAccessObject *self, int begin, int end)
static int mathutils_matrix_translation_get_index(BaseMathObject *bmo, int col, int row)
static PyObject * Matrix_to_NxN(MatrixObject *self, const int num_col, const int num_row)
static void matrix_invert_with_det_n_internal(float *mat_dst, const float *mat_src, const float det, const ushort dim)
static PyObject * Matrix_deepcopy(MatrixObject *self, PyObject *args)
static PyObject * Matrix_rotate(MatrixObject *self, PyObject *value)
static PyObject * Matrix_item_row(MatrixObject *self, int row)
void matrix_as_3x3(float mat[3][3], MatrixObject *self)
static bool Matrix_ParseCheck(MatrixObject *pymat)
static int MatrixAccess_len(MatrixAccessObject *self)
static PyMappingMethods Matrix_AsMapping
static PyObject * Matrix_copy(MatrixObject *self)
static void matrix_3x3_as_4x4(float mat[16])
int Matrix_Parse2x2(PyObject *o, void *p)
Mathutils_Callback mathutils_matrix_row_cb
static int mathutils_matrix_translation_get(BaseMathObject *bmo, int col)
static int MatrixAccess_traverse(MatrixAccessObject *self, visitproc visit, void *arg)
static int Matrix_ass_item_row(MatrixObject *self, int row, PyObject *value)
Mathutils_Callback mathutils_matrix_translation_cb
static PyObject * Matrix_inverted_safe(MatrixObject *self)
static PyObject * Matrix_is_negative_get(MatrixObject *self, void *UNUSED(closure))
static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value)
int Matrix_Parse4x4(PyObject *o, void *p)
static PyObject * C_Matrix_Diagonal(PyObject *cls, PyObject *value)
uchar mathutils_matrix_col_cb_index
static int Matrix_ass_item_col(MatrixObject *self, int col, PyObject *value)
uchar mathutils_matrix_row_cb_index
static PyObject * Matrix_invert(MatrixObject *self, PyObject *args)
static PyObject * Matrix_imatmul(PyObject *m1, PyObject *m2)
static void matrix_invert_raise_degenerate(void)
static PyObject * Matrix_to_scale(MatrixObject *self)
PyObject * Matrix_CreatePyObject(const float *mat, const ushort num_col, const ushort num_row, PyTypeObject *base_type)
static int MatrixAccess_ass_subscript(MatrixAccessObject *self, PyObject *item, PyObject *value)
static int mathutils_matrix_row_get(BaseMathObject *bmo, int row)
static int matrix_col_vector_check(MatrixObject *mat, VectorObject *vec, int col)
static PyObject * Matrix_normalized(MatrixObject *self)
static PyObject * Matrix_adjugated(MatrixObject *self)
static PyObject * Matrix_to_translation(MatrixObject *self)
static PyObject * C_Matrix_Shear(PyObject *cls, PyObject *args)
static bool matrix_invert_args_check(const MatrixObject *self, PyObject *args, bool check_type)
static int mathutils_matrix_translation_check(BaseMathObject *bmo)
static void MatrixAccess_dealloc(MatrixAccessObject *self)
static PyObject * Matrix_inverted(MatrixObject *self, PyObject *args)
static PyObject * Matrix_adjugate(MatrixObject *self)
static struct PyMethodDef Matrix_methods[]
static int mathutils_matrix_col_check(BaseMathObject *bmo)
static void matrix_copy(MatrixObject *mat_dst, const MatrixObject *mat_src)
static PyObject * Matrix_zero(MatrixObject *self)
static PyObject * Matrix_matmul(PyObject *m1, PyObject *m2)
static Py_hash_t Matrix_hash(MatrixObject *self)
static PyObject * Matrix_transpose(MatrixObject *self)
static int mathutils_matrix_col_set_index(BaseMathObject *bmo, int col, int row)
static PyObject * MatrixAccess_subscript(MatrixAccessObject *self, PyObject *item)
static int mathutils_matrix_translation_set(BaseMathObject *bmo, int col)
static PyObject * Matrix_to_2x2(MatrixObject *self)
static PyObject * Matrix_determinant(MatrixObject *self)
static PyObject * Matrix_sub(PyObject *m1, PyObject *m2)
static PyObject * Matrix_copy_notest(MatrixObject *self, const float *matrix)
static PyObject * MatrixAccess_CreatePyObject(MatrixObject *matrix, const eMatrixAccess_t type)
static void matrix_invert_safe_internal(const MatrixObject *self, float *r_mat)
static PyObject * Matrix_slice(MatrixObject *self, int begin, int end)
static PyObject * Matrix_identity(MatrixObject *self)
uchar mathutils_matrix_translation_cb_index
#define MATRIX_COL_PTR(_mat, _col)
#define MatrixObject_Check(v)
#define MATRIX_ITEM_INDEX_NUMROW(_totrow, _row, _col)
#define MATRIX_ITEM(_mat, _row, _col)
PyObject * Quaternion_CreatePyObject(const float quat[4], PyTypeObject *base_type)
PyObject * Vector_CreatePyObject(const float *vec, const int size, PyTypeObject *base_type)
PyObject * Vector_CreatePyObject_cb(PyObject *cb_user, int size, uchar cb_type, uchar cb_subtype)
#define VectorObject_Check(v)
int PyC_CheckArgs_DeepCopy(PyObject *args)
#define PyTuple_SET_ITEMS(op_arg,...)
PyObject_HEAD MatrixObject * matrix_user
ccl_device_inline float dot(const float2 &a, const float2 &b)