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