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