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