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