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