Matrix.translation wrapper vector, continent accessing to matrix[3][0:3].
[blender.git] / source / blender / python / mathutils / mathutils_Matrix.c
1 /*
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * Contributor(s): Michel Selten & Joseph Gilbert
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/python/mathutils/mathutils_Matrix.c
28  *  \ingroup pymathutils
29  */
30
31
32 #include <Python.h>
33
34 #include "mathutils.h"
35
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38 #include "BLI_string.h"
39 #include "BLI_dynstr.h"
40
41 static PyObject *Matrix_copy(MatrixObject *self);
42 static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value);
43 static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self);
44
45 /* matrix vector callbacks */
46 int mathutils_matrix_vector_cb_index= -1;
47
48 static int mathutils_matrix_vector_check(BaseMathObject *bmo)
49 {
50         MatrixObject *self= (MatrixObject *)bmo->cb_user;
51         return BaseMath_ReadCallback(self);
52 }
53
54 static int mathutils_matrix_vector_get(BaseMathObject *bmo, int col)
55 {
56         MatrixObject *self= (MatrixObject *)bmo->cb_user;
57         int row;
58
59         if (BaseMath_ReadCallback(self) == -1)
60                 return -1;
61
62         for (row=0; row < self->num_row; row++) {
63                 bmo->data[row] = MATRIX_ITEM(self, row, col);
64         }
65
66         return 0;
67 }
68
69 static int mathutils_matrix_vector_set(BaseMathObject *bmo, int col)
70 {
71         MatrixObject *self= (MatrixObject *)bmo->cb_user;
72         int row;
73
74         if (BaseMath_ReadCallback(self) == -1)
75                 return -1;
76
77         for (row=0; row < self->num_row; row++) {
78                 MATRIX_ITEM(self, row, col) = bmo->data[row];
79         }
80
81         (void)BaseMath_WriteCallback(self);
82         return 0;
83 }
84
85 static int mathutils_matrix_vector_get_index(BaseMathObject *bmo, int col, int row)
86 {
87         MatrixObject *self= (MatrixObject *)bmo->cb_user;
88
89         if (BaseMath_ReadCallback(self) == -1)
90                 return -1;
91
92         bmo->data[row]= MATRIX_ITEM(self, row, col);
93         return 0;
94 }
95
96 static int mathutils_matrix_vector_set_index(BaseMathObject *bmo, int col, int row)
97 {
98         MatrixObject *self= (MatrixObject *)bmo->cb_user;
99
100         if (BaseMath_ReadCallback(self) == -1)
101                 return -1;
102
103         MATRIX_ITEM(self, row, col) = bmo->data[row];
104
105         (void)BaseMath_WriteCallback(self);
106         return 0;
107 }
108
109 Mathutils_Callback mathutils_matrix_vector_cb = {
110         mathutils_matrix_vector_check,
111         mathutils_matrix_vector_get,
112         mathutils_matrix_vector_set,
113         mathutils_matrix_vector_get_index,
114         mathutils_matrix_vector_set_index
115 };
116 /* matrix vector callbacks, this is so you can do matrix[i][j] = val  */
117
118 /* matrix row callbacks */
119 int mathutils_matrix_column_cb_index= -1;
120
121 static int mathutils_matrix_column_check(BaseMathObject *bmo)
122 {
123         MatrixObject *self= (MatrixObject *)bmo->cb_user;
124         return BaseMath_ReadCallback(self);
125 }
126
127 static int mathutils_matrix_column_get(BaseMathObject *bmo, int col)
128 {
129         MatrixObject *self= (MatrixObject *)bmo->cb_user;
130         int num_row;
131         int row;
132
133         if (BaseMath_ReadCallback(self) == -1)
134                 return -1;
135
136         /* for 'translation' size will always be '3' even on 4x4 vec */
137         num_row = MIN2(self->num_row, ((VectorObject *)bmo)->size);
138
139         for (row = 0; row < num_row; row++) {
140                 bmo->data[row] = MATRIX_ITEM(self, row, col);
141         }
142
143         return 0;
144 }
145
146 static int mathutils_matrix_column_set(BaseMathObject *bmo, int col)
147 {
148         MatrixObject *self= (MatrixObject *)bmo->cb_user;
149         int num_row;
150         int row;
151
152         if (BaseMath_ReadCallback(self) == -1)
153                 return -1;
154
155         /* for 'translation' size will always be '3' even on 4x4 vec */
156         num_row = MIN2(self->num_row, ((VectorObject *)bmo)->size);
157
158         for (row = 0; row < num_row; row++) {
159                 MATRIX_ITEM(self, row, col) = bmo->data[row];
160         }
161
162         (void)BaseMath_WriteCallback(self);
163         return 0;
164 }
165
166 static int mathutils_matrix_column_get_index(BaseMathObject *bmo, int col, int row)
167 {
168         MatrixObject *self= (MatrixObject *)bmo->cb_user;
169
170         if (BaseMath_ReadCallback(self) == -1)
171                 return -1;
172
173         bmo->data[row]= MATRIX_ITEM(self, row, col);
174         return 0;
175 }
176
177 static int mathutils_matrix_column_set_index(BaseMathObject *bmo, int col, int row)
178 {
179         MatrixObject *self= (MatrixObject *)bmo->cb_user;
180
181         if (BaseMath_ReadCallback(self) == -1)
182                 return -1;
183
184         MATRIX_ITEM(self, row, col) = bmo->data[row];
185
186         (void)BaseMath_WriteCallback(self);
187         return 0;
188 }
189
190 Mathutils_Callback mathutils_matrix_column_cb = {
191         mathutils_matrix_column_check,
192         mathutils_matrix_column_get,
193         mathutils_matrix_column_set,
194         mathutils_matrix_column_get_index,
195         mathutils_matrix_column_set_index
196 };
197 /* matrix column callbacks, this is so you can do matrix.translation = Vector()  */
198
199 //----------------------------------mathutils.Matrix() -----------------
200 //mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
201 //create a new matrix type
202 static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
203 {
204         if (kwds && PyDict_Size(kwds)) {
205                 PyErr_SetString(PyExc_TypeError,
206                                 "Matrix(): "
207                                 "takes no keyword args");
208                 return NULL;
209         }
210
211         switch (PyTuple_GET_SIZE(args)) {
212                 case 0:
213                         return Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, type);
214                 case 1:
215                 {
216                         PyObject *arg= PyTuple_GET_ITEM(args, 0);
217
218                         /* -1 is an error, size checks will accunt for this */
219                         const unsigned short num_col= PySequence_Size(arg);
220
221                         if (num_col >= 2 && num_col <= 4) {
222                                 PyObject *item= PySequence_GetItem(arg, 0);
223                                 const unsigned short num_row= PySequence_Size(item);
224                                 Py_XDECREF(item);
225
226                                 if (num_row >= 2 && num_row <= 4) {
227                                         /* sane row & col size, new matrix and assign as slice  */
228                                         PyObject *matrix= Matrix_CreatePyObject(NULL, num_col, num_row, Py_NEW, type);
229                                         if (Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) {
230                                                 return matrix;
231                                         }
232                                         else { /* matrix ok, slice assignment not */
233                                                 Py_DECREF(matrix);
234                                         }
235                                 }
236                         }
237                 }
238         }
239
240         /* will overwrite error */
241         PyErr_SetString(PyExc_TypeError,
242                         "Matrix(): "
243                         "expects no args or 2-4 numeric sequences");
244         return NULL;
245 }
246
247 static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self)
248 {
249         PyObject *ret= Matrix_copy(self);
250         PyObject *ret_dummy= matrix_func(ret);
251         if (ret_dummy) {
252                 Py_DECREF(ret_dummy);
253                 return (PyObject *)ret;
254         }
255         else { /* error */
256                 Py_DECREF(ret);
257                 return NULL;
258         }
259 }
260
261 /* when a matrix is 4x4 size but initialized as a 3x3, re-assign values for 4x4 */
262 static void matrix_3x3_as_4x4(float mat[16])
263 {
264         mat[10] = mat[8];
265         mat[9] = mat[7];
266         mat[8] = mat[6];
267         mat[7] = 0.0f;
268         mat[6] = mat[5];
269         mat[5] = mat[4];
270         mat[4] = mat[3];
271         mat[3] = 0.0f;
272 }
273
274 /*-----------------------CLASS-METHODS----------------------------*/
275
276 //mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
277 PyDoc_STRVAR(C_Matrix_Rotation_doc,
278 ".. classmethod:: Rotation(angle, size, axis)\n"
279 "\n"
280 "   Create a matrix representing a rotation.\n"
281 "\n"
282 "   :arg angle: The angle of rotation desired, in radians.\n"
283 "   :type angle: float\n"
284 "   :arg size: The size of the rotation matrix to construct [2, 4].\n"
285 "   :type size: int\n"
286 "   :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object\n"
287 "      (optional when size is 2).\n"
288 "   :type axis: string or :class:`Vector`\n"
289 "   :return: A new rotation matrix.\n"
290 "   :rtype: :class:`Matrix`\n"
291 );
292 static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args)
293 {
294         PyObject *vec= NULL;
295         const char *axis= NULL;
296         int matSize;
297         double angle; /* use double because of precision problems at high values */
298         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
299                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
300
301         if (!PyArg_ParseTuple(args, "di|O", &angle, &matSize, &vec)) {
302                 PyErr_SetString(PyExc_TypeError,
303                                 "Matrix.Rotation(angle, size, axis): "
304                                 "expected float int and a string or vector");
305                 return NULL;
306         }
307
308         if (vec && PyUnicode_Check(vec)) {
309                 axis= _PyUnicode_AsString((PyObject *)vec);
310                 if (axis==NULL || axis[0]=='\0' || axis[1]!='\0' || axis[0] < 'X' || axis[0] > 'Z') {
311                         PyErr_SetString(PyExc_ValueError,
312                                         "Matrix.Rotation(): "
313                                         "3rd argument axis value must be a 3D vector "
314                                         "or a string in 'X', 'Y', 'Z'");
315                         return NULL;
316                 }
317                 else {
318                         /* use the string */
319                         vec= NULL;
320                 }
321         }
322
323         angle= angle_wrap_rad(angle);
324
325         if (matSize != 2 && matSize != 3 && matSize != 4) {
326                 PyErr_SetString(PyExc_ValueError,
327                                 "Matrix.Rotation(): "
328                                 "can only return a 2x2 3x3 or 4x4 matrix");
329                 return NULL;
330         }
331         if (matSize == 2 && (vec != NULL)) {
332                 PyErr_SetString(PyExc_ValueError,
333                                 "Matrix.Rotation(): "
334                                 "cannot create a 2x2 rotation matrix around arbitrary axis");
335                 return NULL;
336         }
337         if ((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) {
338                 PyErr_SetString(PyExc_ValueError,
339                                 "Matrix.Rotation(): "
340                                 "axis of rotation for 3d and 4d matrices is required");
341                 return NULL;
342         }
343
344         /* check for valid vector/axis above */
345         if (vec) {
346                 float tvec[3];
347
348                 if (mathutils_array_parse(tvec, 3, 3, vec, "Matrix.Rotation(angle, size, axis), invalid 'axis' arg") == -1)
349                         return NULL;
350
351                 axis_angle_to_mat3((float (*)[3])mat, tvec, angle);
352         }
353         else if (matSize == 2) {
354                 const float angle_cos= cosf(angle);
355                 const float angle_sin= sinf(angle);
356
357                 //2D rotation matrix
358                 mat[0] =  angle_cos;
359                 mat[1] =  angle_sin;
360                 mat[2] = -angle_sin;
361                 mat[3] =  angle_cos;
362         }
363         else {
364                 /* valid axis checked above */
365                 single_axis_angle_to_mat3((float (*)[3])mat, axis[0], angle);
366         }
367
368         if (matSize == 4) {
369                 matrix_3x3_as_4x4(mat);
370         }
371         //pass to matrix creation
372         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
373 }
374
375
376 PyDoc_STRVAR(C_Matrix_Translation_doc,
377 ".. classmethod:: Translation(vector)\n"
378 "\n"
379 "   Create a matrix representing a translation.\n"
380 "\n"
381 "   :arg vector: The translation vector.\n"
382 "   :type vector: :class:`Vector`\n"
383 "   :return: An identity matrix with a translation.\n"
384 "   :rtype: :class:`Matrix`\n"
385 );
386 static PyObject *C_Matrix_Translation(PyObject *cls, PyObject *value)
387 {
388         float mat[16], tvec[3];
389
390         if (mathutils_array_parse(tvec, 3, 4, value, "mathutils.Matrix.Translation(vector), invalid vector arg") == -1)
391                 return NULL;
392
393         /* create a identity matrix and add translation */
394         unit_m4((float(*)[4]) mat);
395         copy_v3_v3(mat + 12, tvec); /* 12, 13, 14 */
396         return Matrix_CreatePyObject(mat, 4, 4, Py_NEW, (PyTypeObject *)cls);
397 }
398 //----------------------------------mathutils.Matrix.Scale() -------------
399 //mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
400 PyDoc_STRVAR(C_Matrix_Scale_doc,
401 ".. classmethod:: Scale(factor, size, axis)\n"
402 "\n"
403 "   Create a matrix representing a scaling.\n"
404 "\n"
405 "   :arg factor: The factor of scaling to apply.\n"
406 "   :type factor: float\n"
407 "   :arg size: The size of the scale matrix to construct [2, 4].\n"
408 "   :type size: int\n"
409 "   :arg axis: Direction to influence scale. (optional).\n"
410 "   :type axis: :class:`Vector`\n"
411 "   :return: A new scale matrix.\n"
412 "   :rtype: :class:`Matrix`\n"
413 );
414 static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args)
415 {
416         PyObject *vec= NULL;
417         int vec_size;
418         float tvec[3];
419         float factor;
420         int matSize;
421         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
422                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
423
424         if (!PyArg_ParseTuple(args, "fi|O:Matrix.Scale", &factor, &matSize, &vec)) {
425                 return NULL;
426         }
427         if (matSize != 2 && matSize != 3 && matSize != 4) {
428                 PyErr_SetString(PyExc_ValueError,
429                                 "Matrix.Scale(): "
430                                 "can only return a 2x2 3x3 or 4x4 matrix");
431                 return NULL;
432         }
433         if (vec) {
434                 vec_size= (matSize == 2 ? 2 : 3);
435                 if (mathutils_array_parse(tvec, vec_size, vec_size, vec, "Matrix.Scale(factor, size, axis), invalid 'axis' arg") == -1) {
436                         return NULL;
437                 }
438         }
439         if (vec == NULL) {      //scaling along axis
440                 if (matSize == 2) {
441                         mat[0] = factor;
442                         mat[3] = factor;
443                 }
444                 else {
445                         mat[0] = factor;
446                         mat[4] = factor;
447                         mat[8] = factor;
448                 }
449         }
450         else { //scaling in arbitrary direction
451                 //normalize arbitrary axis
452                 float norm = 0.0f;
453                 int x;
454                 for (x = 0; x < vec_size; x++) {
455                         norm += tvec[x] * tvec[x];
456                 }
457                 norm = (float) sqrt(norm);
458                 for (x = 0; x < vec_size; x++) {
459                         tvec[x] /= norm;
460                 }
461                 if (matSize == 2) {
462                         mat[0] = 1 + ((factor - 1) *(tvec[0] * tvec[0]));
463                         mat[1] =     ((factor - 1) *(tvec[0] * tvec[1]));
464                         mat[2] =     ((factor - 1) *(tvec[0] * tvec[1]));
465                         mat[3] = 1 + ((factor - 1) *(tvec[1] * tvec[1]));
466                 }
467                 else {
468                         mat[0] = 1 + ((factor - 1) *(tvec[0] * tvec[0]));
469                         mat[1] =     ((factor - 1) *(tvec[0] * tvec[1]));
470                         mat[2] =     ((factor - 1) *(tvec[0] * tvec[2]));
471                         mat[3] =     ((factor - 1) *(tvec[0] * tvec[1]));
472                         mat[4] = 1 + ((factor - 1) *(tvec[1] * tvec[1]));
473                         mat[5] =     ((factor - 1) *(tvec[1] * tvec[2]));
474                         mat[6] =     ((factor - 1) *(tvec[0] * tvec[2]));
475                         mat[7] =     ((factor - 1) *(tvec[1] * tvec[2]));
476                         mat[8] = 1 + ((factor - 1) *(tvec[2] * tvec[2]));
477                 }
478         }
479         if (matSize == 4) {
480                 matrix_3x3_as_4x4(mat);
481         }
482         //pass to matrix creation
483         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
484 }
485 //----------------------------------mathutils.Matrix.OrthoProjection() ---
486 //mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc.
487 PyDoc_STRVAR(C_Matrix_OrthoProjection_doc,
488 ".. classmethod:: OrthoProjection(axis, size)\n"
489 "\n"
490 "   Create a matrix to represent an orthographic projection.\n"
491 "\n"
492 "   :arg axis: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
493 "      where a single axis is for a 2D matrix.\n"
494 "      Or a vector for an arbitrary axis\n"
495 "   :type axis: string or :class:`Vector`\n"
496 "   :arg size: The size of the projection matrix to construct [2, 4].\n"
497 "   :type size: int\n"
498 "   :return: A new projection matrix.\n"
499 "   :rtype: :class:`Matrix`\n"
500 );
501 static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args)
502 {
503         PyObject *axis;
504
505         int matSize, x;
506         float norm = 0.0f;
507         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
508                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
509
510         if (!PyArg_ParseTuple(args, "Oi:Matrix.OrthoProjection", &axis, &matSize)) {
511                 return NULL;
512         }
513         if (matSize != 2 && matSize != 3 && matSize != 4) {
514                 PyErr_SetString(PyExc_ValueError,
515                                 "Matrix.OrthoProjection(): "
516                                 "can only return a 2x2 3x3 or 4x4 matrix");
517                 return NULL;
518         }
519
520         if (PyUnicode_Check(axis)) {    //ortho projection onto cardinal plane
521                 Py_ssize_t plane_len;
522                 const char *plane= _PyUnicode_AsStringAndSize(axis, &plane_len);
523                 if (matSize == 2) {
524                         if (plane_len == 1 && plane[0]=='X') {
525                                 mat[0]= 1.0f;
526                         }
527                         else if (plane_len == 1 && plane[0]=='Y') {
528                                 mat[3]= 1.0f;
529                         }
530                         else {
531                                 PyErr_Format(PyExc_ValueError,
532                                              "Matrix.OrthoProjection(): "
533                                              "unknown plane, expected: X, Y, not '%.200s'",
534                                              plane);
535                                 return NULL;
536                         }
537                 }
538                 else {
539                         if (plane_len == 2 && plane[0]=='X' && plane[1]=='Y') {
540                                 mat[0]= 1.0f;
541                                 mat[4]= 1.0f;
542                         }
543                         else if (plane_len == 2 && plane[0]=='X' && plane[1]=='Z') {
544                                 mat[0]= 1.0f;
545                                 mat[8]= 1.0f;
546                         }
547                         else if (plane_len == 2 && plane[0]=='Y' && plane[1]=='Z') {
548                                 mat[4]= 1.0f;
549                                 mat[8]= 1.0f;
550                         }
551                         else {
552                                 PyErr_Format(PyExc_ValueError,
553                                              "Matrix.OrthoProjection(): "
554                                              "unknown plane, expected: XY, XZ, YZ, not '%.200s'",
555                                              plane);
556                                 return NULL;
557                         }
558                 }
559         }
560         else {
561                 //arbitrary plane
562
563                 int vec_size= (matSize == 2 ? 2 : 3);
564                 float tvec[4];
565
566                 if (mathutils_array_parse(tvec, vec_size, vec_size, axis,
567                                           "Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1)
568                 {
569                         return NULL;
570                 }
571
572                 //normalize arbitrary axis
573                 for (x = 0; x < vec_size; x++) {
574                         norm += tvec[x] * tvec[x];
575                 }
576                 norm = (float) sqrt(norm);
577                 for (x = 0; x < vec_size; x++) {
578                         tvec[x] /= norm;
579                 }
580                 if (matSize == 2) {
581                         mat[0] = 1 - (tvec[0] * tvec[0]);
582                         mat[1] = -(tvec[0] * tvec[1]);
583                         mat[2] = -(tvec[0] * tvec[1]);
584                         mat[3] = 1 - (tvec[1] * tvec[1]);
585                 }
586                 else if (matSize > 2) {
587                         mat[0] = 1 - (tvec[0] * tvec[0]);
588                         mat[1] = -(tvec[0] * tvec[1]);
589                         mat[2] = -(tvec[0] * tvec[2]);
590                         mat[3] = -(tvec[0] * tvec[1]);
591                         mat[4] = 1 - (tvec[1] * tvec[1]);
592                         mat[5] = -(tvec[1] * tvec[2]);
593                         mat[6] = -(tvec[0] * tvec[2]);
594                         mat[7] = -(tvec[1] * tvec[2]);
595                         mat[8] = 1 - (tvec[2] * tvec[2]);
596                 }
597         }
598         if (matSize == 4) {
599                 matrix_3x3_as_4x4(mat);
600         }
601         //pass to matrix creation
602         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
603 }
604
605 PyDoc_STRVAR(C_Matrix_Shear_doc,
606 ".. classmethod:: Shear(plane, size, factor)\n"
607 "\n"
608 "   Create a matrix to represent an shear transformation.\n"
609 "\n"
610 "   :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n"
611 "      where a single axis is for a 2D matrix only.\n"
612 "   :type plane: string\n"
613 "   :arg size: The size of the shear matrix to construct [2, 4].\n"
614 "   :type size: int\n"
615 "   :arg factor: The factor of shear to apply. For a 3 or 4 *size* matrix\n"
616 "      pass a pair of floats corrasponding with the *plane* axis.\n"
617 "   :type factor: float or float pair\n"
618 "   :return: A new shear matrix.\n"
619 "   :rtype: :class:`Matrix`\n"
620 );
621 static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args)
622 {
623         int matSize;
624         const char *plane;
625         PyObject *fac;
626         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
627                 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
628
629         if (!PyArg_ParseTuple(args, "siO:Matrix.Shear", &plane, &matSize, &fac)) {
630                 return NULL;
631         }
632         if (matSize != 2 && matSize != 3 && matSize != 4) {
633                 PyErr_SetString(PyExc_ValueError,
634                                 "Matrix.Shear(): "
635                                 "can only return a 2x2 3x3 or 4x4 matrix");
636                 return NULL;
637         }
638
639         if (matSize == 2) {
640                 float const factor= PyFloat_AsDouble(fac);
641
642                 if (factor==-1.0f && PyErr_Occurred()) {
643                         PyErr_SetString(PyExc_TypeError,
644                                         "Matrix.Shear(): "
645                                         "the factor to be a float");
646                         return NULL;
647                 }
648
649                 /* unit */
650                 mat[0] = 1.0f;
651                 mat[3] = 1.0f;
652
653                 if (strcmp(plane, "X") == 0) {
654                         mat[2] = factor;
655                 }
656                 else if (strcmp(plane, "Y") == 0) {
657                         mat[1] = factor;
658                 }
659                 else {
660                         PyErr_SetString(PyExc_ValueError,
661                                         "Matrix.Shear(): "
662                                         "expected: X, Y or wrong matrix size for shearing plane");
663                         return NULL;
664                 }
665         }
666         else {
667                 /* 3 or 4, apply as 3x3, resize later if needed */
668                 float factor[2];
669
670                 if (mathutils_array_parse(factor, 2, 2, fac, "Matrix.Shear()") < 0) {
671                         return NULL;
672                 }
673
674                 /* unit */
675                 mat[0] = 1.0f;
676                 mat[4] = 1.0f;
677                 mat[8] = 1.0f;
678
679                 if (strcmp(plane, "XY") == 0) {
680                         mat[6] = factor[0];
681                         mat[7] = factor[1];
682                 }
683                 else if (strcmp(plane, "XZ") == 0) {
684                         mat[3] = factor[0];
685                         mat[5] = factor[1];
686                 }
687                 else if (strcmp(plane, "YZ") == 0) {
688                         mat[1] = factor[0];
689                         mat[2] = factor[1];
690                 }
691                 else {
692                         PyErr_SetString(PyExc_ValueError,
693                                         "Matrix.Shear(): "
694                                         "expected: X, Y, XY, XZ, YZ");
695                         return NULL;
696                 }
697         }
698
699         if (matSize == 4) {
700                 matrix_3x3_as_4x4(mat);
701         }
702         //pass to matrix creation
703         return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls);
704 }
705
706 void matrix_as_3x3(float mat[3][3], MatrixObject *self)
707 {
708         copy_v3_v3(mat[0], MATRIX_COL_PTR(self, 0));
709         copy_v3_v3(mat[1], MATRIX_COL_PTR(self, 1));
710         copy_v3_v3(mat[2], MATRIX_COL_PTR(self, 2));
711 }
712
713 /* assumes rowsize == colsize is checked and the read callback has run */
714 static float matrix_determinant_internal(MatrixObject *self)
715 {
716         if (self->num_col == 2) {
717                 return determinant_m2(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1),
718                                       MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1));
719         }
720         else if (self->num_col == 3) {
721                 return determinant_m3(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1), MATRIX_ITEM(self, 0, 2),
722                                       MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1), MATRIX_ITEM(self, 1, 2),
723                                       MATRIX_ITEM(self, 2, 0), MATRIX_ITEM(self, 2, 1), MATRIX_ITEM(self, 2, 2));
724         }
725         else {
726                 return determinant_m4((float (*)[4])self->matrix);
727         }
728 }
729
730
731 /*-----------------------------METHODS----------------------------*/
732 PyDoc_STRVAR(Matrix_to_quaternion_doc,
733 ".. method:: to_quaternion()\n"
734 "\n"
735 "   Return a quaternion representation of the rotation matrix.\n"
736 "\n"
737 "   :return: Quaternion representation of the rotation matrix.\n"
738 "   :rtype: :class:`Quaternion`\n"
739 );
740 static PyObject *Matrix_to_quaternion(MatrixObject *self)
741 {
742         float quat[4];
743
744         if (BaseMath_ReadCallback(self) == -1)
745                 return NULL;
746
747         /*must be 3-4 cols, 3-4 rows, square matrix*/
748         if ((self->num_row < 3) || (self->num_col < 3) || (self->num_row != self->num_col)) {
749                 PyErr_SetString(PyExc_ValueError,
750                                 "Matrix.to_quat(): "
751                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
752                 return NULL;
753         }
754         if (self->num_row == 3) {
755                 mat3_to_quat(quat, (float (*)[3])self->matrix);
756         }
757         else {
758                 mat4_to_quat(quat, (float (*)[4])self->matrix);
759         }
760
761         return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
762 }
763
764 /*---------------------------matrix.toEuler() --------------------*/
765 PyDoc_STRVAR(Matrix_to_euler_doc,
766 ".. method:: to_euler(order, euler_compat)\n"
767 "\n"
768 "   Return an Euler representation of the rotation matrix\n"
769 "   (3x3 or 4x4 matrix only).\n"
770 "\n"
771 "   :arg order: Optional rotation order argument in\n"
772 "      ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n"
773 "   :type order: string\n"
774 "   :arg euler_compat: Optional euler argument the new euler will be made\n"
775 "      compatible with (no axis flipping between them).\n"
776 "      Useful for converting a series of matrices to animation curves.\n"
777 "   :type euler_compat: :class:`Euler`\n"
778 "   :return: Euler representation of the matrix.\n"
779 "   :rtype: :class:`Euler`\n"
780 );
781 static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args)
782 {
783         const char *order_str= NULL;
784         short order= EULER_ORDER_XYZ;
785         float eul[3], eul_compatf[3];
786         EulerObject *eul_compat = NULL;
787
788         float tmat[3][3];
789         float (*mat)[3];
790
791         if (BaseMath_ReadCallback(self) == -1)
792                 return NULL;
793
794         if (!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat))
795                 return NULL;
796
797         if (eul_compat) {
798                 if (BaseMath_ReadCallback(eul_compat) == -1)
799                         return NULL;
800
801                 copy_v3_v3(eul_compatf, eul_compat->eul);
802         }
803
804         /*must be 3-4 cols, 3-4 rows, square matrix*/
805         if (self->num_row ==3 && self->num_col ==3) {
806                 mat= (float (*)[3])self->matrix;
807         }
808         else if (self->num_row ==4 && self->num_col ==4) {
809                 copy_m3_m4(tmat, (float (*)[4])self->matrix);
810                 mat= tmat;
811         }
812         else {
813                 PyErr_SetString(PyExc_ValueError,
814                                 "Matrix.to_euler(): "
815                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
816                 return NULL;
817         }
818
819         if (order_str) {
820                 order= euler_order_from_string(order_str, "Matrix.to_euler()");
821
822                 if (order == -1)
823                         return NULL;
824         }
825
826         if (eul_compat) {
827                 if (order == 1) mat3_to_compatible_eul(eul, eul_compatf, mat);
828                 else                    mat3_to_compatible_eulO(eul, eul_compatf, order, mat);
829         }
830         else {
831                 if (order == 1) mat3_to_eul(eul, mat);
832                 else                    mat3_to_eulO(eul, order, mat);
833         }
834
835         return Euler_CreatePyObject(eul, order, Py_NEW, NULL);
836 }
837
838 PyDoc_STRVAR(Matrix_resize_4x4_doc,
839 ".. method:: resize_4x4()\n"
840 "\n"
841 "   Resize the matrix to 4x4.\n"
842 );
843 static PyObject *Matrix_resize_4x4(MatrixObject *self)
844 {
845         float mat[16];
846         int col;
847
848         if (self->wrapped==Py_WRAP) {
849                 PyErr_SetString(PyExc_TypeError,
850                                 "Matrix.resize_4x4(): "
851                                 "cannot resize wrapped data - make a copy and resize that");
852                 return NULL;
853         }
854         if (self->cb_user) {
855                 PyErr_SetString(PyExc_TypeError,
856                                 "Matrix.resize_4x4(): "
857                                 "cannot resize owned data - make a copy and resize that");
858                 return NULL;
859         }
860
861         self->matrix = PyMem_Realloc(self->matrix, (sizeof(float) * 16));
862         if (self->matrix == NULL) {
863                 PyErr_SetString(PyExc_MemoryError,
864                                 "Matrix.resize_4x4(): "
865                                 "problem allocating pointer space");
866                 return NULL;
867         }
868
869         unit_m4((float (*)[4])mat);
870
871         for (col = 0; col < self->num_col; col++) {
872                 memcpy(mat + (4 * col), MATRIX_COL_PTR(self, col), self->num_row * sizeof(float));
873         }
874
875         copy_m4_m4((float (*)[4])self->matrix, (float (*)[4])mat);
876
877         self->num_col = 4;
878         self->num_row = 4;
879
880         Py_RETURN_NONE;
881 }
882
883 PyDoc_STRVAR(Matrix_to_4x4_doc,
884 ".. method:: to_4x4()\n"
885 "\n"
886 "   Return a 4x4 copy of this matrix.\n"
887 "\n"
888 "   :return: a new matrix.\n"
889 "   :rtype: :class:`Matrix`\n"
890 );
891 static PyObject *Matrix_to_4x4(MatrixObject *self)
892 {
893         if (BaseMath_ReadCallback(self) == -1)
894                 return NULL;
895
896         if (self->num_row==4 && self->num_col==4) {
897                 return Matrix_CreatePyObject(self->matrix, 4, 4, Py_NEW, Py_TYPE(self));
898         }
899         else if (self->num_row==3 && self->num_col==3) {
900                 float mat[4][4];
901                 copy_m4_m3(mat, (float (*)[3])self->matrix);
902                 return Matrix_CreatePyObject((float *)mat, 4, 4, Py_NEW, Py_TYPE(self));
903         }
904         /* TODO, 2x2 matrix */
905
906         PyErr_SetString(PyExc_TypeError,
907                         "Matrix.to_4x4(): "
908                         "inappropriate matrix size");
909         return NULL;
910 }
911
912 PyDoc_STRVAR(Matrix_to_3x3_doc,
913 ".. method:: to_3x3()\n"
914 "\n"
915 "   Return a 3x3 copy of this matrix.\n"
916 "\n"
917 "   :return: a new matrix.\n"
918 "   :rtype: :class:`Matrix`\n"
919 );
920 static PyObject *Matrix_to_3x3(MatrixObject *self)
921 {
922         float mat[3][3];
923
924         if (BaseMath_ReadCallback(self) == -1)
925                 return NULL;
926
927         if ((self->num_row < 3) || (self->num_col < 3)) {
928                 PyErr_SetString(PyExc_TypeError,
929                                 "Matrix.to_3x3(): inappropriate matrix size");
930                 return NULL;
931         }
932
933         matrix_as_3x3(mat, self);
934
935         return Matrix_CreatePyObject((float *)mat, 3, 3, Py_NEW, Py_TYPE(self));
936 }
937
938 PyDoc_STRVAR(Matrix_to_translation_doc,
939 ".. method:: to_translation()\n"
940 "\n"
941 "   Return a the translation part of a 4 row matrix.\n"
942 "\n"
943 "   :return: Return a the translation of a matrix.\n"
944 "   :rtype: :class:`Vector`\n"
945 );
946 static PyObject *Matrix_to_translation(MatrixObject *self)
947 {
948         if (BaseMath_ReadCallback(self) == -1)
949                 return NULL;
950
951         if ((self->num_row < 3) || self->num_col < 4) {
952                 PyErr_SetString(PyExc_TypeError,
953                                 "Matrix.to_translation(): "
954                                 "inappropriate matrix size");
955                 return NULL;
956         }
957
958         return Vector_CreatePyObject(MATRIX_COL_PTR(self, 3), 3, Py_NEW, NULL);
959 }
960
961 PyDoc_STRVAR(Matrix_to_scale_doc,
962 ".. method:: to_scale()\n"
963 "\n"
964 "   Return a the scale part of a 3x3 or 4x4 matrix.\n"
965 "\n"
966 "   :return: Return a the scale of a matrix.\n"
967 "   :rtype: :class:`Vector`\n"
968 "\n"
969 "   .. note:: This method does not return negative a scale on any axis because it is not possible to obtain this data from the matrix alone.\n"
970 );
971 static PyObject *Matrix_to_scale(MatrixObject *self)
972 {
973         float rot[3][3];
974         float mat[3][3];
975         float size[3];
976
977         if (BaseMath_ReadCallback(self) == -1)
978                 return NULL;
979
980         /*must be 3-4 cols, 3-4 rows, square matrix*/
981         if ((self->num_row < 3) || (self->num_col < 3)) {
982                 PyErr_SetString(PyExc_TypeError,
983                                 "Matrix.to_scale(): "
984                                 "inappropriate matrix size, 3x3 minimum size");
985                 return NULL;
986         }
987
988         matrix_as_3x3(mat, self);
989
990         /* compatible mat4_to_loc_rot_size */
991         mat3_to_rot_size(rot, size, mat);
992
993         return Vector_CreatePyObject(size, 3, Py_NEW, NULL);
994 }
995
996 /*---------------------------matrix.invert() ---------------------*/
997 PyDoc_STRVAR(Matrix_invert_doc,
998 ".. method:: invert()\n"
999 "\n"
1000 "   Set the matrix to its inverse.\n"
1001 "\n"
1002 "   .. note:: :exc:`ValueError` exception is raised.\n"
1003 "\n"
1004 "   .. seealso:: <http://en.wikipedia.org/wiki/Inverse_matrix>\n"
1005 );
1006 static PyObject *Matrix_invert(MatrixObject *self)
1007 {
1008
1009         int x, y, z = 0;
1010         float det = 0.0f;
1011         float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f,
1012                          0.0f, 0.0f, 0.0f, 0.0f,
1013                          0.0f, 0.0f, 0.0f, 0.0f,
1014                          0.0f, 0.0f, 0.0f, 1.0f};
1015
1016         if (BaseMath_ReadCallback(self) == -1)
1017                 return NULL;
1018
1019         if (self->num_col != self->num_row) {
1020                 PyErr_SetString(PyExc_TypeError,
1021                                 "Matrix.invert(ed): "
1022                                 "only square matrices are supported");
1023                 return NULL;
1024         }
1025
1026         /*calculate the determinant*/
1027         det = matrix_determinant_internal(self);
1028
1029         if (det != 0) {
1030                 /*calculate the classical adjoint*/
1031                 if (self->num_col == 2) {
1032                         mat[0] =  MATRIX_ITEM(self, 1, 1);
1033                         mat[1] = -MATRIX_ITEM(self, 0, 1);
1034                         mat[2] = -MATRIX_ITEM(self, 1, 0);
1035                         mat[3] =  MATRIX_ITEM(self, 0, 0);
1036                 }
1037                 else if (self->num_col == 3) {
1038                         adjoint_m3_m3((float (*)[3]) mat,(float (*)[3])self->matrix);
1039                 }
1040                 else if (self->num_col == 4) {
1041                         adjoint_m4_m4((float (*)[4]) mat, (float (*)[4])self->matrix);
1042                 }
1043                 /*divide by determinate*/
1044                 for (x = 0; x < (self->num_col * self->num_row); x++) {
1045                         mat[x] /= det;
1046                 }
1047                 /*set values*/
1048                 for (x = 0; x < self->num_col; x++) {
1049                         for (y = 0; y < self->num_row; y++) {
1050                                 MATRIX_ITEM(self, y, x) = mat[z];
1051                                 z++;
1052                         }
1053                 }
1054                 /*transpose
1055                 Matrix_transpose(self);*/
1056         }
1057         else {
1058                 PyErr_SetString(PyExc_ValueError,
1059                                 "Matrix.invert(ed): "
1060                                 "matrix does not have an inverse");
1061                 return NULL;
1062         }
1063
1064         (void)BaseMath_WriteCallback(self);
1065         Py_RETURN_NONE;
1066 }
1067
1068 PyDoc_STRVAR(Matrix_inverted_doc,
1069 ".. method:: inverted()\n"
1070 "\n"
1071 "   Return an inverted copy of the matrix.\n"
1072 "\n"
1073 "   :return: the  inverted matrix.\n"
1074 "   :rtype: :class:`Matrix`\n"
1075 "\n"
1076 "   .. note:: :exc:`ValueError` exception is raised.\n"
1077 );
1078 static PyObject *Matrix_inverted(MatrixObject *self)
1079 {
1080         return matrix__apply_to_copy((PyNoArgsFunction)Matrix_invert, self);
1081 }
1082
1083 PyDoc_STRVAR(Matrix_rotate_doc,
1084 ".. method:: rotate(other)\n"
1085 "\n"
1086 "   Rotates the matrix a by another mathutils value.\n"
1087 "\n"
1088 "   :arg other: rotation component of mathutils value\n"
1089 "   :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
1090 "\n"
1091 "   .. note:: If any of the columns are not unit length this may not have desired results.\n"
1092 );
1093 static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value)
1094 {
1095         float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
1096
1097         if (BaseMath_ReadCallback(self) == -1)
1098                 return NULL;
1099
1100         if (mathutils_any_to_rotmat(other_rmat, value, "matrix.rotate(value)") == -1)
1101                 return NULL;
1102
1103         if (self->num_row != 3 || self->num_col != 3) {
1104                 PyErr_SetString(PyExc_TypeError,
1105                                 "Matrix.rotate(): "
1106                                 "must have 3x3 dimensions");
1107                 return NULL;
1108         }
1109
1110         matrix_as_3x3(self_rmat, self);
1111         mul_m3_m3m3(rmat, other_rmat, self_rmat);
1112
1113         copy_m3_m3((float (*)[3])(self->matrix), rmat);
1114
1115         (void)BaseMath_WriteCallback(self);
1116         Py_RETURN_NONE;
1117 }
1118
1119 /*---------------------------matrix.decompose() ---------------------*/
1120 PyDoc_STRVAR(Matrix_decompose_doc,
1121 ".. method:: decompose()\n"
1122 "\n"
1123 "   Return the location, rotaion and scale components of this matrix.\n"
1124 "\n"
1125 "   :return: loc, rot, scale triple.\n"
1126 "   :rtype: (:class:`Vector`, :class:`Quaternion`, :class:`Vector`)"
1127 );
1128 static PyObject *Matrix_decompose(MatrixObject *self)
1129 {
1130         PyObject *ret;
1131         float loc[3];
1132         float rot[3][3];
1133         float quat[4];
1134         float size[3];
1135
1136         if (self->num_row != 4 || self->num_col != 4) {
1137                 PyErr_SetString(PyExc_TypeError,
1138                                 "Matrix.decompose(): "
1139                                 "inappropriate matrix size - expects 4x4 matrix");
1140                 return NULL;
1141         }
1142
1143         if (BaseMath_ReadCallback(self) == -1)
1144                 return NULL;
1145
1146         mat4_to_loc_rot_size(loc, rot, size, (float (*)[4])self->matrix);
1147         mat3_to_quat(quat, rot);
1148
1149         ret= PyTuple_New(3);
1150         PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(loc, 3, Py_NEW, NULL));
1151         PyTuple_SET_ITEM(ret, 1, Quaternion_CreatePyObject(quat, Py_NEW, NULL));
1152         PyTuple_SET_ITEM(ret, 2, Vector_CreatePyObject(size, 3, Py_NEW, NULL));
1153
1154         return ret;
1155 }
1156
1157
1158
1159 PyDoc_STRVAR(Matrix_lerp_doc,
1160 ".. function:: lerp(other, factor)\n"
1161 "\n"
1162 "   Returns the interpolation of two matrices.\n"
1163 "\n"
1164 "   :arg other: value to interpolate with.\n"
1165 "   :type other: :class:`Matrix`\n"
1166 "   :arg factor: The interpolation value in [0.0, 1.0].\n"
1167 "   :type factor: float\n"
1168 "   :return: The interpolated rotation.\n"
1169 "   :rtype: :class:`Matrix`\n"
1170 );
1171 static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args)
1172 {
1173         MatrixObject *mat2 = NULL;
1174         float fac, mat[MATRIX_MAX_DIM*MATRIX_MAX_DIM];
1175
1176         if (!PyArg_ParseTuple(args, "O!f:lerp", &matrix_Type, &mat2, &fac))
1177                 return NULL;
1178
1179         if (self->num_col != mat2->num_col || self->num_row != mat2->num_row) {
1180                 PyErr_SetString(PyExc_ValueError,
1181                                 "Matrix.lerp(): "
1182                                 "expects both matrix objects of the same dimensions");
1183                 return NULL;
1184         }
1185
1186         if (BaseMath_ReadCallback(self) == -1 || BaseMath_ReadCallback(mat2) == -1)
1187                 return NULL;
1188
1189         /* TODO, different sized matrix */
1190         if (self->num_col==4 && self->num_row==4) {
1191                 blend_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac);
1192         }
1193         else if (self->num_col==3 && self->num_row==3) {
1194                 blend_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac);
1195         }
1196         else {
1197                 PyErr_SetString(PyExc_ValueError,
1198                                 "Matrix.lerp(): "
1199                                 "only 3x3 and 4x4 matrices supported");
1200                 return NULL;
1201         }
1202
1203         return Matrix_CreatePyObject(mat, self->num_col, self->num_row, Py_NEW, Py_TYPE(self));
1204 }
1205
1206 /*---------------------------matrix.determinant() ----------------*/
1207 PyDoc_STRVAR(Matrix_determinant_doc,
1208 ".. method:: determinant()\n"
1209 "\n"
1210 "   Return the determinant of a matrix.\n"
1211 "\n"
1212 "   :return: Return a the determinant of a matrix.\n"
1213 "   :rtype: float\n"
1214 "\n"
1215 "   .. seealso:: <http://en.wikipedia.org/wiki/Determinant>\n"
1216 );
1217 static PyObject *Matrix_determinant(MatrixObject *self)
1218 {
1219         if (BaseMath_ReadCallback(self) == -1)
1220                 return NULL;
1221
1222         if (self->num_col != self->num_row) {
1223                 PyErr_SetString(PyExc_TypeError,
1224                                 "Matrix.determinant(): "
1225                                 "only square matrices are supported");
1226                 return NULL;
1227         }
1228
1229         return PyFloat_FromDouble((double)matrix_determinant_internal(self));
1230 }
1231 /*---------------------------matrix.transpose() ------------------*/
1232 PyDoc_STRVAR(Matrix_transpose_doc,
1233 ".. method:: transpose()\n"
1234 "\n"
1235 "   Set the matrix to its transpose.\n"
1236 "\n"
1237 "   .. seealso:: <http://en.wikipedia.org/wiki/Transpose>\n"
1238 );
1239 static PyObject *Matrix_transpose(MatrixObject *self)
1240 {
1241         if (BaseMath_ReadCallback(self) == -1)
1242                 return NULL;
1243
1244         if (self->num_col != self->num_row) {
1245                 PyErr_SetString(PyExc_TypeError,
1246                                 "Matrix.transpose(d): "
1247                                 "only square matrices are supported");
1248                 return NULL;
1249         }
1250
1251         if (self->num_col == 2) {
1252                 const float t = MATRIX_ITEM(self, 1, 0);
1253                 MATRIX_ITEM(self, 1, 0) = MATRIX_ITEM(self, 0, 1);
1254                 MATRIX_ITEM(self, 0, 1) = t;
1255         }
1256         else if (self->num_col == 3) {
1257                 transpose_m3((float (*)[3])self->matrix);
1258         }
1259         else {
1260                 transpose_m4((float (*)[4])self->matrix);
1261         }
1262
1263         (void)BaseMath_WriteCallback(self);
1264         Py_RETURN_NONE;
1265 }
1266
1267 PyDoc_STRVAR(Matrix_transposed_doc,
1268 ".. method:: transposed()\n"
1269 "\n"
1270 "   Return a new, transposed matrix.\n"
1271 "\n"
1272 "   :return: a transposed matrix\n"
1273 "   :rtype: :class:`Matrix`\n"
1274 );
1275 static PyObject *Matrix_transposed(MatrixObject *self)
1276 {
1277         return matrix__apply_to_copy((PyNoArgsFunction)Matrix_transpose, self);
1278 }
1279
1280 /*---------------------------matrix.zero() -----------------------*/
1281 PyDoc_STRVAR(Matrix_zero_doc,
1282 ".. method:: zero()\n"
1283 "\n"
1284 "   Set all the matrix values to zero.\n"
1285 "\n"
1286 "   :return: an instance of itself\n"
1287 "   :rtype: :class:`Matrix`\n"
1288 );
1289 static PyObject *Matrix_zero(MatrixObject *self)
1290 {
1291         fill_vn_fl(self->matrix, self->num_col * self->num_row, 0.0f);
1292
1293         if (BaseMath_WriteCallback(self) == -1)
1294                 return NULL;
1295
1296         Py_RETURN_NONE;
1297 }
1298 /*---------------------------matrix.identity(() ------------------*/
1299 PyDoc_STRVAR(Matrix_identity_doc,
1300 ".. method:: identity()\n"
1301 "\n"
1302 "   Set the matrix to the identity matrix.\n"
1303 "\n"
1304 "   .. note:: An object with zero location and rotation, a scale of one,\n"
1305 "      will have an identity matrix.\n"
1306 "\n"
1307 "   .. seealso:: <http://en.wikipedia.org/wiki/Identity_matrix>\n"
1308 );
1309 static PyObject *Matrix_identity(MatrixObject *self)
1310 {
1311         if (BaseMath_ReadCallback(self) == -1)
1312                 return NULL;
1313
1314         if (self->num_col != self->num_row) {
1315                 PyErr_SetString(PyExc_TypeError,
1316                                 "Matrix.identity(): "
1317                                 "only square matrices are supported");
1318                 return NULL;
1319         }
1320
1321         if (self->num_col == 2) {
1322                 MATRIX_ITEM(self, 0, 0) = 1.0f;
1323                 MATRIX_ITEM(self, 0, 1) = 0.0f;
1324                 MATRIX_ITEM(self, 1, 0) = 0.0f;
1325                 MATRIX_ITEM(self, 1, 1) = 1.0f;
1326         }
1327         else if (self->num_col == 3) {
1328                 unit_m3((float (*)[3])self->matrix);
1329         }
1330         else {
1331                 unit_m4((float (*)[4])self->matrix);
1332         }
1333
1334         if (BaseMath_WriteCallback(self) == -1)
1335                 return NULL;
1336
1337         Py_RETURN_NONE;
1338 }
1339
1340 /*---------------------------Matrix.copy() ------------------*/
1341 PyDoc_STRVAR(Matrix_copy_doc,
1342 ".. method:: copy()\n"
1343 "\n"
1344 "   Returns a copy of this matrix.\n"
1345 "\n"
1346 "   :return: an instance of itself\n"
1347 "   :rtype: :class:`Matrix`\n"
1348 );
1349 static PyObject *Matrix_copy(MatrixObject *self)
1350 {
1351         if (BaseMath_ReadCallback(self) == -1)
1352                 return NULL;
1353
1354         return Matrix_CreatePyObject((float (*))self->matrix, self->num_col, self->num_row, Py_NEW, Py_TYPE(self));
1355 }
1356
1357 /*----------------------------print object (internal)-------------*/
1358 /*print the object to screen*/
1359 static PyObject *Matrix_repr(MatrixObject *self)
1360 {
1361         int col, row;
1362         PyObject *rows[MATRIX_MAX_DIM]= {NULL};
1363
1364         if (BaseMath_ReadCallback(self) == -1)
1365                 return NULL;
1366
1367         for (col = 0; col < self->num_col; col++) {
1368                 rows[col]= PyTuple_New(self->num_row);
1369                 for (row = 0; row < self->num_row; row++) {
1370                         PyTuple_SET_ITEM(rows[col], row, PyFloat_FromDouble(MATRIX_ITEM(self, row, col)));
1371                 }
1372         }
1373         switch (self->num_col) {
1374         case 2: return PyUnicode_FromFormat("Matrix((%R,\n"
1375                                                                                 "        %R))", rows[0], rows[1]);
1376
1377         case 3: return PyUnicode_FromFormat("Matrix((%R,\n"
1378                                                                                 "        %R,\n"
1379                                                                                 "        %R))", rows[0], rows[1], rows[2]);
1380
1381         case 4: return PyUnicode_FromFormat("Matrix((%R,\n"
1382                                                                                 "        %R,\n"
1383                                                                                 "        %R,\n"
1384                                                                                 "        %R))", rows[0], rows[1], rows[2], rows[3]);
1385         }
1386
1387         Py_FatalError("Matrix(): invalid row size!");
1388         return NULL;
1389 }
1390
1391 static PyObject* Matrix_str(MatrixObject *self)
1392 {
1393         DynStr *ds;
1394
1395         int maxsize[MATRIX_MAX_DIM];
1396         int row, col;
1397
1398         char dummy_buf[1];
1399
1400         if (BaseMath_ReadCallback(self) == -1)
1401                 return NULL;
1402
1403         ds= BLI_dynstr_new();
1404
1405         /* First determine the maximum width for each column */
1406         for (col = 0; col < self->num_col; col++) {
1407                 maxsize[col]= 0;
1408                 for (row = 0; row < self->num_row; row++) {
1409                         int size= BLI_snprintf(dummy_buf, sizeof(dummy_buf), "%.4f", MATRIX_ITEM(self, row, col));
1410                         maxsize[col]= MAX2(maxsize[col], size);
1411                 }
1412         }
1413
1414         /* Now write the unicode string to be printed */
1415         BLI_dynstr_appendf(ds, "<Matrix %dx%d (", self->num_row, self->num_col);
1416         for (row = 0; row < self->num_row; row++) {
1417                 for (col = 0; col < self->num_col; col++) {
1418                         BLI_dynstr_appendf(ds, col ? ", %*.4f" : "%*.4f", maxsize[col], MATRIX_ITEM(self, row, col));
1419                 }
1420                 BLI_dynstr_append(ds, row + 1 != self->num_row ? ")\n             " : ")");
1421         }
1422         BLI_dynstr_append(ds, ">");
1423
1424         return mathutils_dynstr_to_py(ds); /* frees ds */
1425 }
1426
1427 static PyObject* Matrix_richcmpr(PyObject *a, PyObject *b, int op)
1428 {
1429         PyObject *res;
1430         int ok= -1; /* zero is true */
1431
1432         if (MatrixObject_Check(a) && MatrixObject_Check(b)) {
1433                 MatrixObject *matA= (MatrixObject*)a;
1434                 MatrixObject *matB= (MatrixObject*)b;
1435
1436                 if (BaseMath_ReadCallback(matA) == -1 || BaseMath_ReadCallback(matB) == -1)
1437                         return NULL;
1438
1439                 ok=     (       (matA->num_row == matB->num_row) &&
1440                                 (matA->num_col == matB->num_col) &&
1441                                 EXPP_VectorsAreEqual(matA->matrix, matB->matrix, (matA->num_col * matA->num_row), 1)
1442                         ) ? 0 : -1;
1443         }
1444
1445         switch (op) {
1446         case Py_NE:
1447                 ok = !ok; /* pass through */
1448         case Py_EQ:
1449                 res = ok ? Py_False : Py_True;
1450                 break;
1451
1452         case Py_LT:
1453         case Py_LE:
1454         case Py_GT:
1455         case Py_GE:
1456                 res = Py_NotImplemented;
1457                 break;
1458         default:
1459                 PyErr_BadArgument();
1460                 return NULL;
1461         }
1462
1463         return Py_INCREF(res), res;
1464 }
1465
1466 /*---------------------SEQUENCE PROTOCOLS------------------------
1467   ----------------------------len(object)------------------------
1468   sequence length*/
1469 static int Matrix_len(MatrixObject *self)
1470 {
1471         return (self->num_col);
1472 }
1473 /*----------------------------object[]---------------------------
1474   sequence accessor (get)
1475   the wrapped vector gives direct access to the matrix data*/
1476 static PyObject *Matrix_item(MatrixObject *self, int i)
1477 {
1478         if (BaseMath_ReadCallback(self) == -1)
1479                 return NULL;
1480
1481         if (i < 0 || i >= self->num_col) {
1482                 PyErr_SetString(PyExc_IndexError,
1483                                 "matrix[attribute]: "
1484                                 "array index out of range");
1485                 return NULL;
1486         }
1487         return Vector_CreatePyObject_cb((PyObject *)self, self->num_row, mathutils_matrix_vector_cb_index, i);
1488 }
1489 /*----------------------------object[]-------------------------
1490   sequence accessor (set) */
1491
1492 static int Matrix_ass_item(MatrixObject *self, int i, PyObject *value)
1493 {
1494         float vec[4];
1495         if (BaseMath_ReadCallback(self) == -1)
1496                 return -1;
1497
1498         if (i >= self->num_col || i < 0) {
1499                 PyErr_SetString(PyExc_IndexError,
1500                                 "matrix[attribute] = x: bad column");
1501                 return -1;
1502         }
1503
1504         if (mathutils_array_parse(vec, self->num_row, self->num_row, value, "matrix[i] = value assignment") < 0) {
1505                 return -1;
1506         }
1507
1508         memcpy(MATRIX_COL_PTR(self, i), vec, self->num_row * sizeof(float));
1509
1510         (void)BaseMath_WriteCallback(self);
1511         return 0;
1512 }
1513
1514 /*----------------------------object[z:y]------------------------
1515   sequence slice (get)*/
1516 static PyObject *Matrix_slice(MatrixObject *self, int begin, int end)
1517 {
1518
1519         PyObject *tuple;
1520         int count;
1521
1522         if (BaseMath_ReadCallback(self) == -1)
1523                 return NULL;
1524
1525         CLAMP(begin, 0, self->num_col);
1526         CLAMP(end, 0, self->num_col);
1527         begin= MIN2(begin, end);
1528
1529         tuple= PyTuple_New(end - begin);
1530         for (count= begin; count < end; count++) {
1531                 PyTuple_SET_ITEM(tuple, count - begin,
1532                                 Vector_CreatePyObject_cb((PyObject *)self, self->num_row, mathutils_matrix_vector_cb_index, count));
1533
1534         }
1535
1536         return tuple;
1537 }
1538 /*----------------------------object[z:y]------------------------
1539   sequence slice (set)*/
1540 static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value)
1541 {
1542         PyObject *value_fast= NULL;
1543
1544         if (BaseMath_ReadCallback(self) == -1)
1545                 return -1;
1546
1547         CLAMP(begin, 0, self->num_col);
1548         CLAMP(end, 0, self->num_col);
1549         begin = MIN2(begin, end);
1550
1551         /* non list/tuple cases */
1552         if (!(value_fast=PySequence_Fast(value, "matrix[begin:end] = value"))) {
1553                 /* PySequence_Fast sets the error */
1554                 return -1;
1555         }
1556         else {
1557                 const int size= end - begin;
1558                 int i;
1559                 float mat[16];
1560
1561                 if (PySequence_Fast_GET_SIZE(value_fast) != size) {
1562                         Py_DECREF(value_fast);
1563                         PyErr_SetString(PyExc_ValueError,
1564                                         "matrix[begin:end] = []: "
1565                                         "size mismatch in slice assignment");
1566                         return -1;
1567                 }
1568
1569                 /*parse sub items*/
1570                 for (i = 0; i < size; i++) {
1571                         /*parse each sub sequence*/
1572                         PyObject *item= PySequence_Fast_GET_ITEM(value_fast, i);
1573
1574                         if (mathutils_array_parse(&mat[i * self->num_row], self->num_row, self->num_row, item,
1575                                                   "matrix[begin:end] = value assignment") < 0)
1576                         {
1577                                 return -1;
1578                         }
1579                 }
1580
1581                 Py_DECREF(value_fast);
1582
1583                 /*parsed well - now set in matrix*/
1584                 memcpy(self->matrix + (begin * self->num_row), mat, sizeof(float) * (size * self->num_row));
1585
1586                 (void)BaseMath_WriteCallback(self);
1587                 return 0;
1588         }
1589 }
1590 /*------------------------NUMERIC PROTOCOLS----------------------
1591   ------------------------obj + obj------------------------------*/
1592 static PyObject *Matrix_add(PyObject *m1, PyObject *m2)
1593 {
1594         float mat[16];
1595         MatrixObject *mat1 = NULL, *mat2 = NULL;
1596
1597         mat1 = (MatrixObject*)m1;
1598         mat2 = (MatrixObject*)m2;
1599
1600         if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
1601                 PyErr_Format(PyExc_TypeError,
1602                              "Matrix addition: (%s + %s) "
1603                              "invalid type for this operation",
1604                              Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
1605                 return NULL;
1606         }
1607
1608         if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1)
1609                 return NULL;
1610
1611         if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) {
1612                 PyErr_SetString(PyExc_TypeError,
1613                                 "Matrix addition: "
1614                                 "matrices must have the same dimensions for this operation");
1615                 return NULL;
1616         }
1617
1618         add_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
1619
1620         return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
1621 }
1622 /*------------------------obj - obj------------------------------
1623   subtraction*/
1624 static PyObject *Matrix_sub(PyObject *m1, PyObject *m2)
1625 {
1626         float mat[16];
1627         MatrixObject *mat1 = NULL, *mat2 = NULL;
1628
1629         mat1 = (MatrixObject*)m1;
1630         mat2 = (MatrixObject*)m2;
1631
1632         if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) {
1633                 PyErr_Format(PyExc_TypeError,
1634                              "Matrix subtraction: (%s - %s) "
1635                              "invalid type for this operation",
1636                              Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name
1637                              );
1638                 return NULL;
1639         }
1640
1641         if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1)
1642                 return NULL;
1643
1644         if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) {
1645                 PyErr_SetString(PyExc_TypeError,
1646                                 "Matrix addition: "
1647                                 "matrices must have the same dimensions for this operation");
1648                 return NULL;
1649         }
1650
1651         sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row);
1652
1653         return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
1654 }
1655 /*------------------------obj * obj------------------------------
1656   mulplication*/
1657 static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar)
1658 {
1659         float tmat[16];
1660         mul_vn_vn_fl(tmat, mat->matrix, mat->num_col * mat->num_row, scalar);
1661         return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_NEW, Py_TYPE(mat));
1662 }
1663
1664 static PyObject *Matrix_mul(PyObject *m1, PyObject *m2)
1665 {
1666         float scalar;
1667         int vec_size;
1668
1669         MatrixObject *mat1 = NULL, *mat2 = NULL;
1670
1671         if (MatrixObject_Check(m1)) {
1672                 mat1 = (MatrixObject*)m1;
1673                 if (BaseMath_ReadCallback(mat1) == -1)
1674                         return NULL;
1675         }
1676         if (MatrixObject_Check(m2)) {
1677                 mat2 = (MatrixObject*)m2;
1678                 if (BaseMath_ReadCallback(mat2) == -1)
1679                         return NULL;
1680         }
1681
1682         if (mat1 && mat2) {
1683                 /*MATRIX * MATRIX*/
1684                 float mat[16]= {0.0f, 0.0f, 0.0f, 0.0f,
1685                                                 0.0f, 0.0f, 0.0f, 0.0f,
1686                                                 0.0f, 0.0f, 0.0f, 0.0f,
1687                                                 0.0f, 0.0f, 0.0f, 1.0f};
1688                 double dot = 0.0f;
1689                 int col, row, item;
1690
1691                 if (mat1->num_col != mat2->num_row) {
1692                         PyErr_SetString(PyExc_ValueError,
1693                                                         "matrix1 * matrix2: matrix1 number of columns "
1694                                                         "and the matrix2 number of rows must be the same");
1695                         return NULL;
1696                 }
1697
1698                 for (col = 0; col < mat2->num_col; col++) {
1699                         for (row = 0; row < mat1->num_row; row++) {
1700                                 for (item = 0; item < mat1->num_col; item++) {
1701                                         dot += MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col);
1702                                 }
1703                                 mat[(col * mat1->num_row) + row] = (float)dot;
1704                                 dot = 0.0f;
1705                         }
1706                 }
1707
1708                 return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1));
1709         }
1710         else if (mat2) {
1711                 /*FLOAT/INT * MATRIX */
1712                 if (((scalar= PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred())==0) {
1713                         return matrix_mul_float(mat2, scalar);
1714                 }
1715         }
1716         else if (mat1) {
1717                 /* MATRIX * VECTOR */
1718                 if (VectorObject_Check(m2)) {
1719                         VectorObject *vec2= (VectorObject *)m2;
1720                         float tvec[4];
1721                         if (BaseMath_ReadCallback(vec2) == -1)
1722                                 return NULL;
1723                         if (column_vector_multiplication(tvec, vec2, mat1) == -1) {
1724                                 return NULL;
1725                         }
1726
1727                         if (mat1->num_col == 4 && vec2->size == 3) {
1728                                 vec_size = 3;
1729                         }
1730                         else {
1731                                 vec_size = mat1->num_row;
1732                         }
1733
1734                         return Vector_CreatePyObject(tvec, vec_size, Py_NEW, Py_TYPE(m2));
1735                 }
1736                 /*FLOAT/INT * MATRIX */
1737                 else if (((scalar= PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred())==0) {
1738                         return matrix_mul_float(mat1, scalar);
1739                 }
1740         }
1741         else {
1742                 BLI_assert(!"internal error");
1743         }
1744
1745         PyErr_Format(PyExc_TypeError,
1746                      "Matrix multiplication: "
1747                      "not supported between '%.200s' and '%.200s' types",
1748                      Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name);
1749         return NULL;
1750 }
1751 static PyObject* Matrix_inv(MatrixObject *self)
1752 {
1753         if (BaseMath_ReadCallback(self) == -1)
1754                 return NULL;
1755
1756         return Matrix_invert(self);
1757 }
1758
1759 /*-----------------PROTOCOL DECLARATIONS--------------------------*/
1760 static PySequenceMethods Matrix_SeqMethods = {
1761         (lenfunc) Matrix_len,                                           /* sq_length */
1762         (binaryfunc) NULL,                                                      /* sq_concat */
1763         (ssizeargfunc) NULL,                                            /* sq_repeat */
1764         (ssizeargfunc) Matrix_item,                                     /* sq_item */
1765         (ssizessizeargfunc) NULL,                                       /* sq_slice, deprecated */
1766         (ssizeobjargproc) Matrix_ass_item,                      /* sq_ass_item */
1767         (ssizessizeobjargproc) NULL,                            /* sq_ass_slice, deprecated */
1768         (objobjproc) NULL,                                                      /* sq_contains */
1769         (binaryfunc) NULL,                                                      /* sq_inplace_concat */
1770         (ssizeargfunc) NULL,                                            /* sq_inplace_repeat */
1771 };
1772
1773
1774 static PyObject *Matrix_subscript(MatrixObject* self, PyObject* item)
1775 {
1776         if (PyIndex_Check(item)) {
1777                 Py_ssize_t i;
1778                 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
1779                 if (i == -1 && PyErr_Occurred())
1780                         return NULL;
1781                 if (i < 0)
1782                         i += self->num_col;
1783                 return Matrix_item(self, i);
1784         }
1785         else if (PySlice_Check(item)) {
1786                 Py_ssize_t start, stop, step, slicelength;
1787
1788                 if (PySlice_GetIndicesEx((void *)item, self->num_col, &start, &stop, &step, &slicelength) < 0)
1789                         return NULL;
1790
1791                 if (slicelength <= 0) {
1792                         return PyTuple_New(0);
1793                 }
1794                 else if (step == 1) {
1795                         return Matrix_slice(self, start, stop);
1796                 }
1797                 else {
1798                         PyErr_SetString(PyExc_IndexError,
1799                                         "slice steps not supported with matrices");
1800                         return NULL;
1801                 }
1802         }
1803         else {
1804                 PyErr_Format(PyExc_TypeError,
1805                              "matrix indices must be integers, not %.200s",
1806                              Py_TYPE(item)->tp_name);
1807                 return NULL;
1808         }
1809 }
1810
1811 static int Matrix_ass_subscript(MatrixObject* self, PyObject* item, PyObject* value)
1812 {
1813         if (PyIndex_Check(item)) {
1814                 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
1815                 if (i == -1 && PyErr_Occurred())
1816                         return -1;
1817                 if (i < 0)
1818                         i += self->num_col;
1819                 return Matrix_ass_item(self, i, value);
1820         }
1821         else if (PySlice_Check(item)) {
1822                 Py_ssize_t start, stop, step, slicelength;
1823
1824                 if (PySlice_GetIndicesEx((void *)item, self->num_col, &start, &stop, &step, &slicelength) < 0)
1825                         return -1;
1826
1827                 if (step == 1)
1828                         return Matrix_ass_slice(self, start, stop, value);
1829                 else {
1830                         PyErr_SetString(PyExc_IndexError,
1831                                         "slice steps not supported with matrices");
1832                         return -1;
1833                 }
1834         }
1835         else {
1836                 PyErr_Format(PyExc_TypeError,
1837                              "matrix indices must be integers, not %.200s",
1838                              Py_TYPE(item)->tp_name);
1839                 return -1;
1840         }
1841 }
1842
1843 static PyMappingMethods Matrix_AsMapping = {
1844         (lenfunc)Matrix_len,
1845         (binaryfunc)Matrix_subscript,
1846         (objobjargproc)Matrix_ass_subscript
1847 };
1848
1849
1850 static PyNumberMethods Matrix_NumMethods = {
1851                 (binaryfunc)    Matrix_add,     /*nb_add*/
1852                 (binaryfunc)    Matrix_sub,     /*nb_subtract*/
1853                 (binaryfunc)    Matrix_mul,     /*nb_multiply*/
1854                 NULL,                                                   /*nb_remainder*/
1855                 NULL,                                                   /*nb_divmod*/
1856                 NULL,                                                   /*nb_power*/
1857                 (unaryfunc)     0,      /*nb_negative*/
1858                 (unaryfunc)     0,      /*tp_positive*/
1859                 (unaryfunc)     0,      /*tp_absolute*/
1860                 (inquiry)       0,      /*tp_bool*/
1861                 (unaryfunc)     Matrix_inv,     /*nb_invert*/
1862                 NULL,                           /*nb_lshift*/
1863                 (binaryfunc)0,  /*nb_rshift*/
1864                 NULL,                           /*nb_and*/
1865                 NULL,                           /*nb_xor*/
1866                 NULL,                           /*nb_or*/
1867                 NULL,                           /*nb_int*/
1868                 NULL,                           /*nb_reserved*/
1869                 NULL,                           /*nb_float*/
1870                 NULL,                           /* nb_inplace_add */
1871                 NULL,                           /* nb_inplace_subtract */
1872                 NULL,                           /* nb_inplace_multiply */
1873                 NULL,                           /* nb_inplace_remainder */
1874                 NULL,                           /* nb_inplace_power */
1875                 NULL,                           /* nb_inplace_lshift */
1876                 NULL,                           /* nb_inplace_rshift */
1877                 NULL,                           /* nb_inplace_and */
1878                 NULL,                           /* nb_inplace_xor */
1879                 NULL,                           /* nb_inplace_or */
1880                 NULL,                           /* nb_floor_divide */
1881                 NULL,                           /* nb_true_divide */
1882                 NULL,                           /* nb_inplace_floor_divide */
1883                 NULL,                           /* nb_inplace_true_divide */
1884                 NULL,                           /* nb_index */
1885 };
1886
1887 static PyObject *Matrix_getRowSize(MatrixObject *self, void *UNUSED(closure))
1888 {
1889         return PyLong_FromLong((long) self->num_col);
1890 }
1891
1892 static PyObject *Matrix_getColSize(MatrixObject *self, void *UNUSED(closure))
1893 {
1894         return PyLong_FromLong((long) self->num_row);
1895 }
1896
1897 static PyObject *Matrix_translation_get(MatrixObject *self, void *UNUSED(closure))
1898 {
1899         PyObject *ret;
1900
1901         if (BaseMath_ReadCallback(self) == -1)
1902                 return NULL;
1903
1904         /*must be 4x4 square matrix*/
1905         if (self->num_row != 4 || self->num_col != 4) {
1906                 PyErr_SetString(PyExc_AttributeError,
1907                                 "Matrix.translation: "
1908                                 "inappropriate matrix size, must be 4x4");
1909                 return NULL;
1910         }
1911
1912         ret = (PyObject *)Vector_CreatePyObject_cb((PyObject *)self, 3, mathutils_matrix_column_cb_index, 3);
1913
1914         return ret;
1915 }
1916
1917 static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNUSED(closure))
1918 {
1919         float tvec[3];
1920
1921         if (BaseMath_ReadCallback(self) == -1)
1922                 return -1;
1923
1924         /*must be 4x4 square matrix*/
1925         if (self->num_row != 4 || self->num_col != 4) {
1926                 PyErr_SetString(PyExc_AttributeError,
1927                                 "Matrix.translation: "
1928                                 "inappropriate matrix size, must be 4x4");
1929                 return -1;
1930         }
1931
1932         if ((mathutils_array_parse(tvec, 3, 3, value, "Matrix.translation")) == -1)
1933                 return -1;
1934
1935         copy_v3_v3(((float (*)[4])self->matrix)[3], tvec);
1936
1937         (void)BaseMath_WriteCallback(self);
1938
1939         return 0;
1940 }
1941
1942 static PyObject *Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closure))
1943 {
1944         float mat[3][3];
1945
1946         if (BaseMath_ReadCallback(self) == -1)
1947                 return NULL;
1948
1949         /*must be 3-4 cols, 3-4 rows, square matrix*/
1950         if ((self->num_row < 3) || (self->num_col < 3)) {
1951                 PyErr_SetString(PyExc_AttributeError,
1952                                 "Matrix.median_scale: "
1953                                 "inappropriate matrix size, 3x3 minimum");
1954                 return NULL;
1955         }
1956
1957         matrix_as_3x3(mat, self);
1958
1959         return PyFloat_FromDouble(mat3_to_scale(mat));
1960 }
1961
1962 static PyObject *Matrix_is_negative_get(MatrixObject *self, void *UNUSED(closure))
1963 {
1964         if (BaseMath_ReadCallback(self) == -1)
1965                 return NULL;
1966
1967         /*must be 3-4 cols, 3-4 rows, square matrix*/
1968         if (self->num_row == 4 && self->num_col == 4)
1969                 return PyBool_FromLong(is_negative_m4((float (*)[4])self->matrix));
1970         else if (self->num_row == 3 && self->num_col == 3)
1971                 return PyBool_FromLong(is_negative_m3((float (*)[3])self->matrix));
1972         else {
1973                 PyErr_SetString(PyExc_AttributeError,
1974                                 "Matrix.is_negative: "
1975                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
1976                 return NULL;
1977         }
1978 }
1979
1980 static PyObject *Matrix_is_orthogonal_get(MatrixObject *self, void *UNUSED(closure))
1981 {
1982         if (BaseMath_ReadCallback(self) == -1)
1983                 return NULL;
1984
1985         /*must be 3-4 cols, 3-4 rows, square matrix*/
1986         if (self->num_row == 4 && self->num_col == 4)
1987                 return PyBool_FromLong(is_orthogonal_m4((float (*)[4])self->matrix));
1988         else if (self->num_row == 3 && self->num_col == 3)
1989                 return PyBool_FromLong(is_orthogonal_m3((float (*)[3])self->matrix));
1990         else {
1991                 PyErr_SetString(PyExc_AttributeError,
1992                                 "Matrix.is_orthogonal: "
1993                                 "inappropriate matrix size - expects 3x3 or 4x4 matrix");
1994                 return NULL;
1995         }
1996 }
1997
1998 /*****************************************************************************/
1999 /* Python attributes get/set structure:                                      */
2000 /*****************************************************************************/
2001 static PyGetSetDef Matrix_getseters[] = {
2002         {(char *)"row_size", (getter)Matrix_getRowSize, (setter)NULL, (char *)"The row size of the matrix (readonly).\n\n:type: int", NULL},
2003         {(char *)"col_size", (getter)Matrix_getColSize, (setter)NULL, (char *)"The column size of the matrix (readonly).\n\n:type: int", NULL},
2004         {(char *)"median_scale", (getter)Matrix_median_scale_get, (setter)NULL, (char *)"The average scale applied to each axis (readonly).\n\n:type: float", NULL},
2005         {(char *)"translation", (getter)Matrix_translation_get, (setter)Matrix_translation_set, (char *)"The translation component of the matrix.\n\n:type: Vector", NULL},
2006         {(char *)"is_negative", (getter)Matrix_is_negative_get, (setter)NULL, (char *)"True if this matrix results in a negative scale, 3x3 and 4x4 only, (readonly).\n\n:type: bool", NULL},
2007         {(char *)"is_orthogonal", (getter)Matrix_is_orthogonal_get, (setter)NULL, (char *)"True if this matrix is orthogonal, 3x3 and 4x4 only, (readonly).\n\n:type: bool", NULL},
2008         {(char *)"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, (char *)BaseMathObject_Wrapped_doc, NULL},
2009         {(char *)"owner",(getter)BaseMathObject_getOwner, (setter)NULL, (char *)BaseMathObject_Owner_doc, NULL},
2010         {NULL, NULL, NULL, NULL, NULL}  /* Sentinel */
2011 };
2012
2013 /*-----------------------METHOD DEFINITIONS ----------------------*/
2014 static struct PyMethodDef Matrix_methods[] = {
2015         /* derived values */
2016         {"determinant", (PyCFunction) Matrix_determinant, METH_NOARGS, Matrix_determinant_doc},
2017         {"decompose", (PyCFunction) Matrix_decompose, METH_NOARGS, Matrix_decompose_doc},
2018
2019         /* in place only */
2020         {"zero", (PyCFunction) Matrix_zero, METH_NOARGS, Matrix_zero_doc},
2021         {"identity", (PyCFunction) Matrix_identity, METH_NOARGS, Matrix_identity_doc},
2022
2023         /* operate on original or copy */
2024         {"transpose", (PyCFunction) Matrix_transpose, METH_NOARGS, Matrix_transpose_doc},
2025         {"transposed", (PyCFunction) Matrix_transposed, METH_NOARGS, Matrix_transposed_doc},
2026         {"invert", (PyCFunction) Matrix_invert, METH_NOARGS, Matrix_invert_doc},
2027         {"inverted", (PyCFunction) Matrix_inverted, METH_NOARGS, Matrix_inverted_doc},
2028         {"to_3x3", (PyCFunction) Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc},
2029         // TODO. {"resize_3x3", (PyCFunction) Matrix_resize3x3, METH_NOARGS, Matrix_resize3x3_doc},
2030         {"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc},
2031         {"resize_4x4", (PyCFunction) Matrix_resize_4x4, METH_NOARGS, Matrix_resize_4x4_doc},
2032         {"rotate", (PyCFunction) Matrix_rotate, METH_O, Matrix_rotate_doc},
2033
2034         /* return converted representation */
2035         {"to_euler", (PyCFunction) Matrix_to_euler, METH_VARARGS, Matrix_to_euler_doc},
2036         {"to_quaternion", (PyCFunction) Matrix_to_quaternion, METH_NOARGS, Matrix_to_quaternion_doc},
2037         {"to_scale", (PyCFunction) Matrix_to_scale, METH_NOARGS, Matrix_to_scale_doc},
2038         {"to_translation", (PyCFunction) Matrix_to_translation, METH_NOARGS, Matrix_to_translation_doc},
2039
2040         /* operation between 2 or more types  */
2041         {"lerp", (PyCFunction) Matrix_lerp, METH_VARARGS, Matrix_lerp_doc},
2042         {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
2043         {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc},
2044
2045         /* class methods */
2046         {"Rotation", (PyCFunction) C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc},
2047         {"Scale", (PyCFunction) C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc},
2048         {"Shear", (PyCFunction) C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc},
2049         {"Translation", (PyCFunction) C_Matrix_Translation, METH_O | METH_CLASS, C_Matrix_Translation_doc},
2050         {"OrthoProjection", (PyCFunction) C_Matrix_OrthoProjection,  METH_VARARGS | METH_CLASS, C_Matrix_OrthoProjection_doc},
2051         {NULL, NULL, 0, NULL}
2052 };
2053
2054 /*------------------PY_OBECT DEFINITION--------------------------*/
2055 PyDoc_STRVAR(matrix_doc,
2056 "This object gives access to Matrices in Blender."
2057 );
2058 PyTypeObject matrix_Type = {
2059         PyVarObject_HEAD_INIT(NULL, 0)
2060         "mathutils.Matrix",                                     /*tp_name*/
2061         sizeof(MatrixObject),                           /*tp_basicsize*/
2062         0,                                                                      /*tp_itemsize*/
2063         (destructor)BaseMathObject_dealloc,     /*tp_dealloc*/
2064         NULL,                                                           /*tp_print*/
2065         NULL,                                                           /*tp_getattr*/
2066         NULL,                                                           /*tp_setattr*/
2067         NULL,                                                           /*tp_compare*/
2068         (reprfunc) Matrix_repr,                         /*tp_repr*/
2069         &Matrix_NumMethods,                                     /*tp_as_number*/
2070         &Matrix_SeqMethods,                                     /*tp_as_sequence*/
2071         &Matrix_AsMapping,                                      /*tp_as_mapping*/
2072         NULL,                                                           /*tp_hash*/
2073         NULL,                                                           /*tp_call*/
2074         (reprfunc) Matrix_str,                          /*tp_str*/
2075         NULL,                                                           /*tp_getattro*/
2076         NULL,                                                           /*tp_setattro*/
2077         NULL,                                                           /*tp_as_buffer*/
2078         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
2079         matrix_doc,                                                     /*tp_doc*/
2080         (traverseproc)BaseMathObject_traverse,  //tp_traverse
2081         (inquiry)BaseMathObject_clear,  //tp_clear
2082         (richcmpfunc)Matrix_richcmpr,           /*tp_richcompare*/
2083         0,                                                                      /*tp_weaklistoffset*/
2084         NULL,                                                           /*tp_iter*/
2085         NULL,                                                           /*tp_iternext*/
2086         Matrix_methods,                                         /*tp_methods*/
2087         NULL,                                                           /*tp_members*/
2088         Matrix_getseters,                                       /*tp_getset*/
2089         NULL,                                                           /*tp_base*/
2090         NULL,                                                           /*tp_dict*/
2091         NULL,                                                           /*tp_descr_get*/
2092         NULL,                                                           /*tp_descr_set*/
2093         0,                                                                      /*tp_dictoffset*/
2094         NULL,                                                           /*tp_init*/
2095         NULL,                                                           /*tp_alloc*/
2096         Matrix_new,                                                     /*tp_new*/
2097         NULL,                                                           /*tp_free*/
2098         NULL,                                                           /*tp_is_gc*/
2099         NULL,                                                           /*tp_bases*/
2100         NULL,                                                           /*tp_mro*/
2101         NULL,                                                           /*tp_cache*/
2102         NULL,                                                           /*tp_subclasses*/
2103         NULL,                                                           /*tp_weaklist*/
2104         NULL                                                            /*tp_del*/
2105 };
2106
2107 /* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
2108  * (i.e. it was allocated elsewhere by MEM_mallocN())
2109  * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
2110  * (i.e. it must be created here with PyMEM_malloc()) */
2111 PyObject *Matrix_CreatePyObject(float *mat,
2112                                 const unsigned short num_col, const unsigned short num_row,
2113                                 int type, PyTypeObject *base_type)
2114 {
2115         MatrixObject *self;
2116
2117         /* matrix objects can be any 2-4row x 2-4col matrix */
2118         if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) {
2119                 PyErr_SetString(PyExc_RuntimeError,
2120                                 "Matrix(): "
2121                                 "row and column sizes must be between 2 and 4");
2122                 return NULL;
2123         }
2124
2125         self= base_type ? (MatrixObject *)base_type->tp_alloc(base_type, 0) :
2126                           (MatrixObject *)PyObject_GC_New(MatrixObject, &matrix_Type);
2127
2128         if (self) {
2129                 self->num_col = num_col;
2130                 self->num_row = num_row;
2131
2132                 /* init callbacks as NULL */
2133                 self->cb_user= NULL;
2134                 self->cb_type= self->cb_subtype= 0;
2135
2136                 if (type == Py_WRAP) {
2137                         self->matrix = mat;
2138                         self->wrapped = Py_WRAP;
2139                 }
2140                 else if (type == Py_NEW) {
2141                         self->matrix = PyMem_Malloc(num_col * num_row * sizeof(float));
2142                         if (self->matrix == NULL) { /*allocation failure*/
2143                                 PyErr_SetString(PyExc_MemoryError,
2144                                                 "Matrix(): "
2145                                                 "problem allocating pointer space");
2146                                 return NULL;
2147                         }
2148
2149                         if (mat) {      /*if a float array passed*/
2150                                 memcpy(self->matrix, mat, num_col * num_row * sizeof(float));
2151                         }
2152                         else if (num_col == num_row) {
2153                                 /* or if no arguments are passed return identity matrix for square matrices */
2154                                 PyObject *ret_dummy= Matrix_identity(self);
2155                                 Py_DECREF(ret_dummy);
2156                         }
2157                         else {
2158                                 /* otherwise zero everything */
2159                                 memset(self->matrix, 0, num_col * num_row * sizeof(float));
2160                         }
2161                         self->wrapped = Py_NEW;
2162                 }
2163                 else {
2164                         Py_FatalError("Matrix(): invalid type!");
2165                         return NULL;
2166                 }
2167         }
2168         return (PyObject *) self;
2169 }
2170
2171 PyObject *Matrix_CreatePyObject_cb(PyObject *cb_user, int rowSize, int colSize, int cb_type, int cb_subtype)
2172 {
2173         MatrixObject *self= (MatrixObject *)Matrix_CreatePyObject(NULL, rowSize, colSize, Py_NEW, NULL);
2174         if (self) {
2175                 Py_INCREF(cb_user);
2176                 self->cb_user=                  cb_user;
2177                 self->cb_type=                  (unsigned char)cb_type;
2178                 self->cb_subtype=               (unsigned char)cb_subtype;
2179                 PyObject_GC_Track(self);
2180         }
2181         return (PyObject *) self;
2182 }