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