diff --git a/release/scripts/io/export_fbx.py b/release/scripts/io/export_fbx.py index 5c2e0cb5f95..c040861941a 100644 --- a/release/scripts/io/export_fbx.py +++ b/release/scripts/io/export_fbx.py @@ -55,7 +55,7 @@ import math # math.pi import shutil # for file copying import bpy -from mathutils import Vector, Euler, Matrix, RotationMatrix +from mathutils import Vector, Euler, Matrix def copy_file(source, dest): # XXX - remove, can use shutil @@ -107,19 +107,19 @@ def eulerRadToDeg(eul): mtx4_identity = Matrix() # testing -mtx_x90 = RotationMatrix( math.pi/2, 3, 'X') # used -#mtx_x90n = RotationMatrix(-90, 3, 'x') -#mtx_y90 = RotationMatrix( 90, 3, 'y') -#mtx_y90n = RotationMatrix(-90, 3, 'y') -#mtx_z90 = RotationMatrix( 90, 3, 'z') -#mtx_z90n = RotationMatrix(-90, 3, 'z') +mtx_x90 = Matrix.Rotation( math.pi/2, 3, 'X') # used +#mtx_x90n = Matrix.Rotation(-90, 3, 'x') +#mtx_y90 = Matrix.Rotation( 90, 3, 'y') +#mtx_y90n = Matrix.Rotation(-90, 3, 'y') +#mtx_z90 = Matrix.Rotation( 90, 3, 'z') +#mtx_z90n = Matrix.Rotation(-90, 3, 'z') -#mtx4_x90 = RotationMatrix( 90, 4, 'x') -mtx4_x90n = RotationMatrix(-math.pi/2, 4, 'X') # used -#mtx4_y90 = RotationMatrix( 90, 4, 'y') -mtx4_y90n = RotationMatrix(-math.pi/2, 4, 'Y') # used -mtx4_z90 = RotationMatrix( math.pi/2, 4, 'Z') # used -mtx4_z90n = RotationMatrix(-math.pi/2, 4, 'Z') # used +#mtx4_x90 = Matrix.Rotation( 90, 4, 'x') +mtx4_x90n = Matrix.Rotation(-math.pi/2, 4, 'X') # used +#mtx4_y90 = Matrix.Rotation( 90, 4, 'y') +mtx4_y90n = Matrix.Rotation(-math.pi/2, 4, 'Y') # used +mtx4_z90 = Matrix.Rotation( math.pi/2, 4, 'Z') # used +mtx4_z90n = Matrix.Rotation(-math.pi/2, 4, 'Z') # used # def strip_path(p): # return p.split('\\')[-1].split('/')[-1] @@ -562,7 +562,7 @@ def write(filename, batch_objects = None, \ elif type =='CAMERA': # elif ob and type =='Camera': y = matrix_rot * Vector((0.0, 1.0, 0.0)) - matrix_rot = RotationMatrix(math.pi/2, 3, y) * matrix_rot + matrix_rot = Matrix.Rotation(math.pi/2, 3, y) * matrix_rot return matrix_rot @@ -664,7 +664,7 @@ def write(filename, batch_objects = None, \ rot = tuple(matrix_rot.to_euler()) elif ob and ob.type =='Camera': y = matrix_rot * Vector((0.0, 1.0, 0.0)) - matrix_rot = RotationMatrix(math.pi/2, 3, y) * matrix_rot + matrix_rot = Matrix.Rotation(math.pi/2, 3, y) * matrix_rot rot = tuple(matrix_rot.to_euler()) else: rot = tuple(matrix_rot.to_euler()) diff --git a/release/scripts/io/export_obj.py b/release/scripts/io/export_obj.py index 5603f52d1a4..5e951f06406 100644 --- a/release/scripts/io/export_obj.py +++ b/release/scripts/io/export_obj.py @@ -363,7 +363,7 @@ def write_file(filepath, objects, scene, file.write('mtllib %s\n' % ( mtlfilepath.split('\\')[-1].split('/')[-1] )) if EXPORT_ROTX90: - mat_xrot90= mathutils.RotationMatrix(-math.pi/2, 4, 'X') + mat_xrot90= mathutils.Matrix.Rotation(-math.pi/2, 4, 'X') # Initialize totals, these are updated each object totverts = totuvco = totno = 1 diff --git a/release/scripts/io/export_x3d.py b/release/scripts/io/export_x3d.py index 5fe48a2550a..607f38be6f7 100644 --- a/release/scripts/io/export_x3d.py +++ b/release/scripts/io/export_x3d.py @@ -81,7 +81,7 @@ from export_3ds import create_derived_objects, free_derived_objects # DEG2RAD=0.017453292519943295 -MATWORLD= mathutils.RotationMatrix(-90, 4, 'X') +MATWORLD= mathutils.Matrix.Rotation(-90, 4, 'X') #################################### # Global Variables diff --git a/release/scripts/io/import_anim_bvh.py b/release/scripts/io/import_anim_bvh.py index ba9b8a1f91d..3a807680700 100644 --- a/release/scripts/io/import_anim_bvh.py +++ b/release/scripts/io/import_anim_bvh.py @@ -23,7 +23,7 @@ from math import radians import bpy import mathutils -from mathutils import Vector, Euler, Matrix, RotationMatrix, TranslationMatrix +from mathutils import Vector, Euler, Matrix class bvh_node_class(object): @@ -78,7 +78,7 @@ MATRIX_IDENTITY_4x4 = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, def eulerRotate(x, y, z, rot_order): # Clamp all values between 0 and 360, values outside this raise an error. - mats = [RotationMatrix(x, 3, 'X'), RotationMatrix(y, 3, 'Y'), RotationMatrix(z, 3, 'Z')] + mats = [Matrix.Rotation(x, 3, 'X'), Matrix.Rotation(y, 3, 'Y'), Matrix.Rotation(z, 3, 'Z')] return (MATRIX_IDENTITY_3x3 * mats[rot_order[0]] * (mats[rot_order[1]] * (mats[rot_order[2]]))).to_euler() # Should work but doesnt! @@ -529,7 +529,7 @@ def bvh_node_dict2armature(context, bvh_nodes, ROT_MODE='XYZ', IMPORT_START_FRAM prev_euler[i] = euler if bvh_node.has_loc: - pose_bone.location = (bone_rest_matrix_inv * TranslationMatrix(Vector((lx, ly, lz)) - bvh_node.rest_head_local)).translation_part() + pose_bone.location = (bone_rest_matrix_inv * Matrix.Translation(Vector((lx, ly, lz)) - bvh_node.rest_head_local)).translation_part() if bvh_node.has_loc: pose_bone.keyframe_insert("location") diff --git a/release/scripts/io/import_scene_3ds.py b/release/scripts/io/import_scene_3ds.py index fe242ca1f29..12c99c0ff46 100644 --- a/release/scripts/io/import_scene_3ds.py +++ b/release/scripts/io/import_scene_3ds.py @@ -771,7 +771,7 @@ def process_next_chunk(file, previous_chunk, importedObjects, IMAGE_SEARCH): #print contextMatrix_rot contextMatrix_rot.invert() #print contextMatrix_rot - #contextMatrix_tx = Blender.mathutils.TranslationMatrix(0.5 * Blender.mathutils.Vector(data[9:])) + #contextMatrix_tx = mathutils.Matrix.Translation(0.5 * Blender.mathutils.Vector(data[9:])) #contextMatrix_tx.invert() #tx.invert() diff --git a/release/scripts/modules/add_object_utils.py b/release/scripts/modules/add_object_utils.py index 9031121060a..41c05ce9d8a 100644 --- a/release/scripts/modules/add_object_utils.py +++ b/release/scripts/modules/add_object_utils.py @@ -25,11 +25,11 @@ import mathutils def add_object_align_init(context, operator): if operator and operator.properties.is_property_set("location") and operator.properties.is_property_set("rotation"): - location = mathutils.TranslationMatrix(mathutils.Vector(operator.properties.location)) + location = mathutils.Matrix.Translation(mathutils.Vector(operator.properties.location)) rotation = mathutils.Euler(operator.properties.rotation).to_matrix().resize4x4() else: # TODO, local view cursor! - location = mathutils.TranslationMatrix(context.scene.cursor_location) + location = mathutils.Matrix.Translation(context.scene.cursor_location) if context.user_preferences.edit.object_align == 'VIEW' and context.space_data.type == 'VIEW_3D': rotation = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4() diff --git a/release/scripts/modules/rigify/spine_pivot_flex.py b/release/scripts/modules/rigify/spine_pivot_flex.py index 86f2399f7ff..c4c9886e2e2 100644 --- a/release/scripts/modules/rigify/spine_pivot_flex.py +++ b/release/scripts/modules/rigify/spine_pivot_flex.py @@ -147,7 +147,7 @@ def deform(obj, definitions, base_names, options): def main(obj, bone_definition, base_names, options): - from mathutils import Vector, RotationMatrix + from mathutils import Vector, Matrix from math import radians, pi arm = obj.data @@ -264,7 +264,7 @@ def main(obj, bone_definition, base_names, options): # Rotate the rev chain 180 about the by the first bones center point pivot = (rv_chain.spine_01_e.head + rv_chain.spine_01_e.tail) * 0.5 - matrix = RotationMatrix(radians(180), 3, 'X') + matrix = Matrix.Rotation(radians(180), 3, 'X') for i, attr in enumerate(rv_chain.attr_names): # similar to neck spine_e = getattr(rv_chain, attr + "_e") # use the first bone as the pivot diff --git a/release/scripts/modules/rigify/tail_control.py b/release/scripts/modules/rigify/tail_control.py index f34bde92dee..a629487c0c8 100644 --- a/release/scripts/modules/rigify/tail_control.py +++ b/release/scripts/modules/rigify/tail_control.py @@ -22,7 +22,7 @@ import bpy from rigify import RigifyError from rigify_utils import bone_class_instance, copy_bone_simple from rna_prop_ui import rna_idprop_ui_prop_get -from mathutils import Vector, RotationMatrix +from mathutils import Vector, Matrix from math import radians, pi # not used, defined for completeness diff --git a/release/scripts/op/uvcalc_smart_project.py b/release/scripts/op/uvcalc_smart_project.py index fbda1955013..bbd0102fc61 100644 --- a/release/scripts/op/uvcalc_smart_project.py +++ b/release/scripts/op/uvcalc_smart_project.py @@ -22,7 +22,7 @@ # -from mathutils import Matrix, Vector, RotationMatrix +from mathutils import Matrix, Vector import time import geometry import bpy @@ -275,15 +275,15 @@ def testNewVecLs2DRotIsBetter(vecs, mat=-1, bestAreaSoFar = -1): # Takes a list of faces that make up a UV island and rotate # until they optimally fit inside a square. -ROTMAT_2D_POS_90D = RotationMatrix( radians(90.0), 2) -ROTMAT_2D_POS_45D = RotationMatrix( radians(45.0), 2) +ROTMAT_2D_POS_90D = Matrix.Rotation( radians(90.0), 2) +ROTMAT_2D_POS_45D = Matrix.Rotation( radians(45.0), 2) RotMatStepRotation = [] rot_angle = 22.5 #45.0/2 while rot_angle > 0.1: RotMatStepRotation.append([\ - RotationMatrix( radians(rot_angle), 2),\ - RotationMatrix( radians(-rot_angle), 2)]) + Matrix.Rotation( radians(rot_angle), 2),\ + Matrix.Rotation( radians(-rot_angle), 2)]) rot_angle = rot_angle/2.0 diff --git a/release/scripts/templates/gamelogic.py b/release/scripts/templates/gamelogic.py index b31d5d95987..21a901c091b 100644 --- a/release/scripts/templates/gamelogic.py +++ b/release/scripts/templates/gamelogic.py @@ -6,7 +6,7 @@ # for keyboard event comparison # import GameKeys -# support for Vector(), Matrix() types and advanced functions like ScaleMatrix(...) and RotationMatrix(...) +# support for Vector(), Matrix() types and advanced functions like Matrix.Scale(...) and Matrix.Rotation(...) # import mathutils # for functions like getWindowWidth(), getWindowHeight() diff --git a/source/blender/python/generic/mathutils.c b/source/blender/python/generic/mathutils.c index 2bfd9a6d0c6..ada5bac8c2a 100644 --- a/source/blender/python/generic/mathutils.c +++ b/source/blender/python/generic/mathutils.c @@ -46,6 +46,13 @@ * - Vector.toTrackQuat --> Vector.to_track_quat * - Quaternion * Quaternion --> cross product (not dot product) * + * moved into class functions. + * - Mathutils.RotationMatrix -> mathutils.Matrix.Rotation + * - Mathutils.ScaleMatrix -> mathutils.Matrix.Scale + * - Mathutils.ShearMatrix -> mathutils.Matrix.Shear + * - Mathutils.TranslationMatrix -> mathutils.Matrix.Translation + * - Mathutils.OrthoProjectionMatrix -> mathutils.Matrix.OrthoProjection + * * Moved to Geometry module: Intersect, TriangleArea, TriangleNormal, QuadNormal, LineIntersect */ @@ -94,434 +101,7 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject * } //----------------------------------MATRIX FUNCTIONS-------------------- -//----------------------------------mathutils.RotationMatrix() ---------- -//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. -static char M_Mathutils_RotationMatrix_doc[] = -".. function:: RotationMatrix(angle, size, axis)\n" -"\n" -" Create a matrix representing a rotation.\n" -"\n" -" :arg angle: The angle of rotation desired, in radians.\n" -" :type angle: float\n" -" :arg size: The size of the rotation matrix to construct [2, 4].\n" -" :type size: int\n" -" :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object (optional when size is 2).\n" -" :type axis: string or :class:`Vector`\n" -" :return: A new rotation matrix.\n" -" :rtype: :class:`Matrix`\n"; -static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args) -{ - VectorObject *vec= NULL; - char *axis= NULL; - int matSize; - float angle = 0.0f; - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - - if(!PyArg_ParseTuple(args, "fi|O", &angle, &matSize, &vec)) { - PyErr_SetString(PyExc_TypeError, "mathutils.RotationMatrix(angle, size, axis): expected float int and a string or vector\n"); - return NULL; - } - - if(vec && !VectorObject_Check(vec)) { - axis= _PyUnicode_AsString((PyObject *)vec); - if(axis==NULL || axis[0]=='\0' || axis[1]!='\0' || axis[0] < 'X' || axis[0] > 'Z') { - PyErr_SetString(PyExc_TypeError, "mathutils.RotationMatrix(): 3rd argument axis value must be a 3D vector or a string in 'X', 'Y', 'Z'\n"); - return NULL; - } - else { - /* use the string */ - vec= NULL; - } - } - - while (angle<-(Py_PI*2)) - angle+=(Py_PI*2); - while (angle>(Py_PI*2)) - angle-=(Py_PI*2); - - if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); - return NULL; - } - if(matSize == 2 && (vec != NULL)) { - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): cannot create a 2x2 rotation matrix around arbitrary axis\n"); - return NULL; - } - if((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) { - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): please choose an axis of rotation for 3d and 4d matrices\n"); - return NULL; - } - if(vec) { - if(vec->size != 3) { - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): the vector axis must be a 3D vector\n"); - return NULL; - } - - if(!BaseMath_ReadCallback(vec)) - return NULL; - - } - - /* check for valid vector/axis above */ - if(vec) { - axis_angle_to_mat3( (float (*)[3])mat,vec->vec, angle); - } - else if(matSize == 2) { - //2D rotation matrix - mat[0] = (float) cos (angle); - mat[1] = (float) sin (angle); - mat[2] = -((float) sin(angle)); - mat[3] = (float) cos(angle); - } else if(strcmp(axis, "X") == 0) { - //rotation around X - mat[0] = 1.0f; - mat[4] = (float) cos(angle); - mat[5] = (float) sin(angle); - mat[7] = -((float) sin(angle)); - mat[8] = (float) cos(angle); - } else if(strcmp(axis, "Y") == 0) { - //rotation around Y - mat[0] = (float) cos(angle); - mat[2] = -((float) sin(angle)); - mat[4] = 1.0f; - mat[6] = (float) sin(angle); - mat[8] = (float) cos(angle); - } else if(strcmp(axis, "Z") == 0) { - //rotation around Z - mat[0] = (float) cos(angle); - mat[1] = (float) sin(angle); - mat[3] = -((float) sin(angle)); - mat[4] = (float) cos(angle); - mat[8] = 1.0f; - } - else { - /* should never get here */ - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): unknown error\n"); - return NULL; - } - - if(matSize == 4) { - //resize matrix - mat[10] = mat[8]; - mat[9] = mat[7]; - mat[8] = mat[6]; - mat[7] = 0.0f; - mat[6] = mat[5]; - mat[5] = mat[4]; - mat[4] = mat[3]; - mat[3] = 0.0f; - } - //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); -} - -static char M_Mathutils_TranslationMatrix_doc[] = -".. function:: TranslationMatrix(vector)\n" -"\n" -" Create a matrix representing a translation.\n" -"\n" -" :arg vector: The translation vector.\n" -" :type vector: :class:`Vector`\n" -" :return: An identity matrix with a translation.\n" -" :rtype: :class:`Matrix`\n"; - -static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * vec) -{ - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - - if(!VectorObject_Check(vec)) { - PyErr_SetString(PyExc_TypeError, "mathutils.TranslationMatrix(): expected vector\n"); - return NULL; - } - if(vec->size != 3 && vec->size != 4) { - PyErr_SetString(PyExc_TypeError, "mathutils.TranslationMatrix(): vector must be 3D or 4D\n"); - return NULL; - } - - if(!BaseMath_ReadCallback(vec)) - return NULL; - - //create a identity matrix and add translation - unit_m4((float(*)[4]) mat); - mat[12] = vec->vec[0]; - mat[13] = vec->vec[1]; - mat[14] = vec->vec[2]; - - return newMatrixObject(mat, 4, 4, Py_NEW, NULL); -} -//----------------------------------mathutils.ScaleMatrix() ------------- -//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. -static char M_Mathutils_ScaleMatrix_doc[] = -".. function:: ScaleMatrix(factor, size, axis)\n" -"\n" -" Create a matrix representing a scaling.\n" -"\n" -" :arg factor: The factor of scaling to apply.\n" -" :type factor: float\n" -" :arg size: The size of the scale matrix to construct [2, 4].\n" -" :type size: int\n" -" :arg axis: Direction to influence scale. (optional).\n" -" :type axis: :class:`Vector`\n" -" :return: A new scale matrix.\n" -" :rtype: :class:`Matrix`\n"; - -static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args) -{ - VectorObject *vec = NULL; - float norm = 0.0f, factor; - int matSize, x; - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - - if(!PyArg_ParseTuple(args, "fi|O!", &factor, &matSize, &vector_Type, &vec)) { - PyErr_SetString(PyExc_TypeError, "mathutils.ScaleMatrix(): expected float int and optional vector\n"); - return NULL; - } - if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError, "mathutils.ScaleMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); - return NULL; - } - if(vec) { - if(vec->size > 2 && matSize == 2) { - PyErr_SetString(PyExc_AttributeError, "mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n"); - return NULL; - } - - if(!BaseMath_ReadCallback(vec)) - return NULL; - - } - if(vec == NULL) { //scaling along axis - if(matSize == 2) { - mat[0] = factor; - mat[3] = factor; - } else { - mat[0] = factor; - mat[4] = factor; - mat[8] = factor; - } - } else { //scaling in arbitrary direction - //normalize arbitrary axis - for(x = 0; x < vec->size; x++) { - norm += vec->vec[x] * vec->vec[x]; - } - norm = (float) sqrt(norm); - for(x = 0; x < vec->size; x++) { - vec->vec[x] /= norm; - } - if(matSize == 2) { - mat[0] = 1 +((factor - 1) *(vec->vec[0] * vec->vec[0])); - mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1])); - mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[1])); - mat[3] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1])); - } else { - mat[0] = 1 + ((factor - 1) *(vec->vec[0] * vec->vec[0])); - mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1])); - mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[2])); - mat[3] =((factor - 1) *(vec->vec[0] * vec->vec[1])); - mat[4] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1])); - mat[5] =((factor - 1) *(vec->vec[1] * vec->vec[2])); - mat[6] =((factor - 1) *(vec->vec[0] * vec->vec[2])); - mat[7] =((factor - 1) *(vec->vec[1] * vec->vec[2])); - mat[8] = 1 + ((factor - 1) *(vec->vec[2] * vec->vec[2])); - } - } - if(matSize == 4) { - //resize matrix - mat[10] = mat[8]; - mat[9] = mat[7]; - mat[8] = mat[6]; - mat[7] = 0.0f; - mat[6] = mat[5]; - mat[5] = mat[4]; - mat[4] = mat[3]; - mat[3] = 0.0f; - } - //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); -} -//----------------------------------mathutils.OrthoProjectionMatrix() --- -//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. -static char M_Mathutils_OrthoProjectionMatrix_doc[] = -".. function:: OrthoProjectionMatrix(plane, size, axis)\n" -"\n" -" Create a matrix to represent an orthographic projection.\n" -"\n" -" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ', 'R'], where a single axis is for a 2D matrix and 'R' requires axis is given.\n" -" :type plane: string\n" -" :arg size: The size of the projection matrix to construct [2, 4].\n" -" :type size: int\n" -" :arg axis: Arbitrary perpendicular plane vector (optional).\n" -" :type axis: :class:`Vector`\n" -" :return: A new projection matrix.\n" -" :rtype: :class:`Matrix`\n"; -static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * args) -{ - VectorObject *vec = NULL; - char *plane; - int matSize, x; - float norm = 0.0f; - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - - if(!PyArg_ParseTuple(args, "si|O!", &plane, &matSize, &vector_Type, &vec)) { - PyErr_SetString(PyExc_TypeError, "mathutils.OrthoProjectionMatrix(): expected string and int and optional vector\n"); - return NULL; - } - if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError,"mathutils.OrthoProjectionMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); - return NULL; - } - if(vec) { - if(vec->size > 2 && matSize == 2) { - PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n"); - return NULL; - } - - if(!BaseMath_ReadCallback(vec)) - return NULL; - - } - if(vec == NULL) { //ortho projection onto cardinal plane - if((strcmp(plane, "X") == 0) && matSize == 2) { - mat[0] = 1.0f; - } else if((strcmp(plane, "Y") == 0) && matSize == 2) { - mat[3] = 1.0f; - } else if((strcmp(plane, "XY") == 0) && matSize > 2) { - mat[0] = 1.0f; - mat[4] = 1.0f; - } else if((strcmp(plane, "XZ") == 0) && matSize > 2) { - mat[0] = 1.0f; - mat[8] = 1.0f; - } else if((strcmp(plane, "YZ") == 0) && matSize > 2) { - mat[4] = 1.0f; - mat[8] = 1.0f; - } else { - PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): unknown plane - expected: X, Y, XY, XZ, YZ\n"); - return NULL; - } - } else { //arbitrary plane - //normalize arbitrary axis - for(x = 0; x < vec->size; x++) { - norm += vec->vec[x] * vec->vec[x]; - } - norm = (float) sqrt(norm); - for(x = 0; x < vec->size; x++) { - vec->vec[x] /= norm; - } - if((strcmp(plane, "R") == 0) && matSize == 2) { - mat[0] = 1 - (vec->vec[0] * vec->vec[0]); - mat[1] = -(vec->vec[0] * vec->vec[1]); - mat[2] = -(vec->vec[0] * vec->vec[1]); - mat[3] = 1 - (vec->vec[1] * vec->vec[1]); - } else if((strcmp(plane, "R") == 0) && matSize > 2) { - mat[0] = 1 - (vec->vec[0] * vec->vec[0]); - mat[1] = -(vec->vec[0] * vec->vec[1]); - mat[2] = -(vec->vec[0] * vec->vec[2]); - mat[3] = -(vec->vec[0] * vec->vec[1]); - mat[4] = 1 - (vec->vec[1] * vec->vec[1]); - mat[5] = -(vec->vec[1] * vec->vec[2]); - mat[6] = -(vec->vec[0] * vec->vec[2]); - mat[7] = -(vec->vec[1] * vec->vec[2]); - mat[8] = 1 - (vec->vec[2] * vec->vec[2]); - } else { - PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): unknown plane - expected: 'r' expected for axis designation\n"); - return NULL; - } - } - if(matSize == 4) { - //resize matrix - mat[10] = mat[8]; - mat[9] = mat[7]; - mat[8] = mat[6]; - mat[7] = 0.0f; - mat[6] = mat[5]; - mat[5] = mat[4]; - mat[4] = mat[3]; - mat[3] = 0.0f; - } - //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); -} - -static char M_Mathutils_ShearMatrix_doc[] = -".. function:: ShearMatrix(plane, factor, size)\n" -"\n" -" Create a matrix to represent an shear transformation.\n" -"\n" -" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'], where a single axis is for a 2D matrix.\n" -" :type plane: string\n" -" :arg factor: The factor of shear to apply.\n" -" :type factor: float\n" -" :arg size: The size of the shear matrix to construct [2, 4].\n" -" :type size: int\n" -" :return: A new shear matrix.\n" -" :rtype: :class:`Matrix`\n"; - -static PyObject *M_Mathutils_ShearMatrix(PyObject * self, PyObject * args) -{ - int matSize; - char *plane; - float factor; - float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - - if(!PyArg_ParseTuple(args, "sfi", &plane, &factor, &matSize)) { - PyErr_SetString(PyExc_TypeError,"mathutils.ShearMatrix(): expected string float and int\n"); - return NULL; - } - if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError,"mathutils.ShearMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); - return NULL; - } - - if((strcmp(plane, "X") == 0) - && matSize == 2) { - mat[0] = 1.0f; - mat[2] = factor; - mat[3] = 1.0f; - } else if((strcmp(plane, "Y") == 0) && matSize == 2) { - mat[0] = 1.0f; - mat[1] = factor; - mat[3] = 1.0f; - } else if((strcmp(plane, "XY") == 0) && matSize > 2) { - mat[0] = 1.0f; - mat[4] = 1.0f; - mat[6] = factor; - mat[7] = factor; - } else if((strcmp(plane, "XZ") == 0) && matSize > 2) { - mat[0] = 1.0f; - mat[3] = factor; - mat[4] = 1.0f; - mat[5] = factor; - mat[8] = 1.0f; - } else if((strcmp(plane, "YZ") == 0) && matSize > 2) { - mat[0] = 1.0f; - mat[1] = factor; - mat[2] = factor; - mat[4] = 1.0f; - mat[8] = 1.0f; - } else { - PyErr_SetString(PyExc_AttributeError, "mathutils.ShearMatrix(): expected: x, y, xy, xz, yz or wrong matrix size for shearing plane\n"); - return NULL; - } - if(matSize == 4) { - //resize matrix - mat[10] = mat[8]; - mat[9] = mat[7]; - mat[8] = mat[6]; - mat[7] = 0.0f; - mat[6] = mat[5]; - mat[5] = mat[4]; - mat[4] = mat[3]; - mat[3] = 0.0f; - } - //pass to matrix creation - return newMatrixObject(mat, matSize, matSize, Py_NEW, NULL); -} /* Utility functions */ @@ -647,11 +227,6 @@ void BaseMathObject_dealloc(BaseMathObject * self) /*----------------------------MODULE INIT-------------------------*/ struct PyMethodDef M_Mathutils_methods[] = { - {"RotationMatrix", (PyCFunction) M_Mathutils_RotationMatrix, METH_VARARGS, M_Mathutils_RotationMatrix_doc}, - {"ScaleMatrix", (PyCFunction) M_Mathutils_ScaleMatrix, METH_VARARGS, M_Mathutils_ScaleMatrix_doc}, - {"ShearMatrix", (PyCFunction) M_Mathutils_ShearMatrix, METH_VARARGS, M_Mathutils_ShearMatrix_doc}, - {"TranslationMatrix", (PyCFunction) M_Mathutils_TranslationMatrix, METH_O, M_Mathutils_TranslationMatrix_doc}, - {"OrthoProjectionMatrix", (PyCFunction) M_Mathutils_OrthoProjectionMatrix, METH_VARARGS, M_Mathutils_OrthoProjectionMatrix_doc}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/python/generic/mathutils_matrix.c b/source/blender/python/generic/mathutils_matrix.c index 9be50fe6349..1ef834b7a3e 100644 --- a/source/blender/python/generic/mathutils_matrix.c +++ b/source/blender/python/generic/mathutils_matrix.c @@ -181,6 +181,438 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return newMatrixObject(matrix, argSize, seqSize, Py_NEW, NULL); } +/*-----------------------CLASS-METHODS----------------------------*/ + +//----------------------------------mathutils.RotationMatrix() ---------- +//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. +static char C_Matrix_Rotation_doc[] = +".. classmethod:: Rotation(angle, size, axis)\n" +"\n" +" Create a matrix representing a rotation.\n" +"\n" +" :arg angle: The angle of rotation desired, in radians.\n" +" :type angle: float\n" +" :arg size: The size of the rotation matrix to construct [2, 4].\n" +" :type size: int\n" +" :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object (optional when size is 2).\n" +" :type axis: string or :class:`Vector`\n" +" :return: A new rotation matrix.\n" +" :rtype: :class:`Matrix`\n"; + +static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args) +{ + VectorObject *vec= NULL; + char *axis= NULL; + int matSize; + float angle = 0.0f; + float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + if(!PyArg_ParseTuple(args, "fi|O", &angle, &matSize, &vec)) { + PyErr_SetString(PyExc_TypeError, "mathutils.RotationMatrix(angle, size, axis): expected float int and a string or vector\n"); + return NULL; + } + + if(vec && !VectorObject_Check(vec)) { + axis= _PyUnicode_AsString((PyObject *)vec); + if(axis==NULL || axis[0]=='\0' || axis[1]!='\0' || axis[0] < 'X' || axis[0] > 'Z') { + PyErr_SetString(PyExc_TypeError, "mathutils.RotationMatrix(): 3rd argument axis value must be a 3D vector or a string in 'X', 'Y', 'Z'\n"); + return NULL; + } + else { + /* use the string */ + vec= NULL; + } + } + + while (angle<-(Py_PI*2)) + angle+=(Py_PI*2); + while (angle>(Py_PI*2)) + angle-=(Py_PI*2); + + if(matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); + return NULL; + } + if(matSize == 2 && (vec != NULL)) { + PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): cannot create a 2x2 rotation matrix around arbitrary axis\n"); + return NULL; + } + if((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) { + PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): please choose an axis of rotation for 3d and 4d matrices\n"); + return NULL; + } + if(vec) { + if(vec->size != 3) { + PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): the vector axis must be a 3D vector\n"); + return NULL; + } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + + } + + /* check for valid vector/axis above */ + if(vec) { + axis_angle_to_mat3( (float (*)[3])mat,vec->vec, angle); + } + else if(matSize == 2) { + //2D rotation matrix + mat[0] = (float) cos (angle); + mat[1] = (float) sin (angle); + mat[2] = -((float) sin(angle)); + mat[3] = (float) cos(angle); + } else if(strcmp(axis, "X") == 0) { + //rotation around X + mat[0] = 1.0f; + mat[4] = (float) cos(angle); + mat[5] = (float) sin(angle); + mat[7] = -((float) sin(angle)); + mat[8] = (float) cos(angle); + } else if(strcmp(axis, "Y") == 0) { + //rotation around Y + mat[0] = (float) cos(angle); + mat[2] = -((float) sin(angle)); + mat[4] = 1.0f; + mat[6] = (float) sin(angle); + mat[8] = (float) cos(angle); + } else if(strcmp(axis, "Z") == 0) { + //rotation around Z + mat[0] = (float) cos(angle); + mat[1] = (float) sin(angle); + mat[3] = -((float) sin(angle)); + mat[4] = (float) cos(angle); + mat[8] = 1.0f; + } + else { + /* should never get here */ + PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): unknown error\n"); + return NULL; + } + + if(matSize == 4) { + //resize matrix + mat[10] = mat[8]; + mat[9] = mat[7]; + mat[8] = mat[6]; + mat[7] = 0.0f; + mat[6] = mat[5]; + mat[5] = mat[4]; + mat[4] = mat[3]; + mat[3] = 0.0f; + } + //pass to matrix creation + return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); +} + + +static char C_Matrix_Translation_doc[] = +".. classmethod:: Translation(vector)\n" +"\n" +" Create a matrix representing a translation.\n" +"\n" +" :arg vector: The translation vector.\n" +" :type vector: :class:`Vector`\n" +" :return: An identity matrix with a translation.\n" +" :rtype: :class:`Matrix`\n"; + +static PyObject *C_Matrix_Translation(PyObject *cls, VectorObject * vec) +{ + float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + if(!VectorObject_Check(vec)) { + PyErr_SetString(PyExc_TypeError, "mathutils.TranslationMatrix(): expected vector\n"); + return NULL; + } + if(vec->size != 3 && vec->size != 4) { + PyErr_SetString(PyExc_TypeError, "mathutils.TranslationMatrix(): vector must be 3D or 4D\n"); + return NULL; + } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + + //create a identity matrix and add translation + unit_m4((float(*)[4]) mat); + mat[12] = vec->vec[0]; + mat[13] = vec->vec[1]; + mat[14] = vec->vec[2]; + + return newMatrixObject(mat, 4, 4, Py_NEW, (PyTypeObject *)cls); +} +//----------------------------------mathutils.ScaleMatrix() ------------- +//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. +static char C_Matrix_Scale_doc[] = +".. classmethod:: Scale(factor, size, axis)\n" +"\n" +" Create a matrix representing a scaling.\n" +"\n" +" :arg factor: The factor of scaling to apply.\n" +" :type factor: float\n" +" :arg size: The size of the scale matrix to construct [2, 4].\n" +" :type size: int\n" +" :arg axis: Direction to influence scale. (optional).\n" +" :type axis: :class:`Vector`\n" +" :return: A new scale matrix.\n" +" :rtype: :class:`Matrix`\n"; + +static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args) +{ + VectorObject *vec = NULL; + float norm = 0.0f, factor; + int matSize, x; + float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + if(!PyArg_ParseTuple(args, "fi|O!", &factor, &matSize, &vector_Type, &vec)) { + PyErr_SetString(PyExc_TypeError, "mathutils.ScaleMatrix(): expected float int and optional vector\n"); + return NULL; + } + if(matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_AttributeError, "mathutils.ScaleMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); + return NULL; + } + if(vec) { + if(vec->size > 2 && matSize == 2) { + PyErr_SetString(PyExc_AttributeError, "mathutils.ScaleMatrix(): please use 2D vectors when scaling in 2D\n"); + return NULL; + } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + + } + if(vec == NULL) { //scaling along axis + if(matSize == 2) { + mat[0] = factor; + mat[3] = factor; + } else { + mat[0] = factor; + mat[4] = factor; + mat[8] = factor; + } + } else { //scaling in arbitrary direction + //normalize arbitrary axis + for(x = 0; x < vec->size; x++) { + norm += vec->vec[x] * vec->vec[x]; + } + norm = (float) sqrt(norm); + for(x = 0; x < vec->size; x++) { + vec->vec[x] /= norm; + } + if(matSize == 2) { + mat[0] = 1 +((factor - 1) *(vec->vec[0] * vec->vec[0])); + mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1])); + mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[1])); + mat[3] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1])); + } else { + mat[0] = 1 + ((factor - 1) *(vec->vec[0] * vec->vec[0])); + mat[1] =((factor - 1) *(vec->vec[0] * vec->vec[1])); + mat[2] =((factor - 1) *(vec->vec[0] * vec->vec[2])); + mat[3] =((factor - 1) *(vec->vec[0] * vec->vec[1])); + mat[4] = 1 + ((factor - 1) *(vec->vec[1] * vec->vec[1])); + mat[5] =((factor - 1) *(vec->vec[1] * vec->vec[2])); + mat[6] =((factor - 1) *(vec->vec[0] * vec->vec[2])); + mat[7] =((factor - 1) *(vec->vec[1] * vec->vec[2])); + mat[8] = 1 + ((factor - 1) *(vec->vec[2] * vec->vec[2])); + } + } + if(matSize == 4) { + //resize matrix + mat[10] = mat[8]; + mat[9] = mat[7]; + mat[8] = mat[6]; + mat[7] = 0.0f; + mat[6] = mat[5]; + mat[5] = mat[4]; + mat[4] = mat[3]; + mat[3] = 0.0f; + } + //pass to matrix creation + return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); +} +//----------------------------------mathutils.OrthoProjectionMatrix() --- +//mat is a 1D array of floats - row[0][0],row[0][1], row[1][0], etc. +static char C_Matrix_OrthoProjection_doc[] = +".. classmethod:: OrthoProjection(plane, size, axis)\n" +"\n" +" Create a matrix to represent an orthographic projection.\n" +"\n" +" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ', 'R'], where a single axis is for a 2D matrix and 'R' requires axis is given.\n" +" :type plane: string\n" +" :arg size: The size of the projection matrix to construct [2, 4].\n" +" :type size: int\n" +" :arg axis: Arbitrary perpendicular plane vector (optional).\n" +" :type axis: :class:`Vector`\n" +" :return: A new projection matrix.\n" +" :rtype: :class:`Matrix`\n"; +static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) +{ + VectorObject *vec = NULL; + char *plane; + int matSize, x; + float norm = 0.0f; + float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + if(!PyArg_ParseTuple(args, "si|O!", &plane, &matSize, &vector_Type, &vec)) { + PyErr_SetString(PyExc_TypeError, "mathutils.OrthoProjectionMatrix(): expected string and int and optional vector\n"); + return NULL; + } + if(matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_AttributeError,"mathutils.OrthoProjectionMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); + return NULL; + } + if(vec) { + if(vec->size > 2 && matSize == 2) { + PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): please use 2D vectors when scaling in 2D\n"); + return NULL; + } + + if(!BaseMath_ReadCallback(vec)) + return NULL; + + } + if(vec == NULL) { //ortho projection onto cardinal plane + if((strcmp(plane, "X") == 0) && matSize == 2) { + mat[0] = 1.0f; + } else if((strcmp(plane, "Y") == 0) && matSize == 2) { + mat[3] = 1.0f; + } else if((strcmp(plane, "XY") == 0) && matSize > 2) { + mat[0] = 1.0f; + mat[4] = 1.0f; + } else if((strcmp(plane, "XZ") == 0) && matSize > 2) { + mat[0] = 1.0f; + mat[8] = 1.0f; + } else if((strcmp(plane, "YZ") == 0) && matSize > 2) { + mat[4] = 1.0f; + mat[8] = 1.0f; + } else { + PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): unknown plane - expected: X, Y, XY, XZ, YZ\n"); + return NULL; + } + } else { //arbitrary plane + //normalize arbitrary axis + for(x = 0; x < vec->size; x++) { + norm += vec->vec[x] * vec->vec[x]; + } + norm = (float) sqrt(norm); + for(x = 0; x < vec->size; x++) { + vec->vec[x] /= norm; + } + if((strcmp(plane, "R") == 0) && matSize == 2) { + mat[0] = 1 - (vec->vec[0] * vec->vec[0]); + mat[1] = -(vec->vec[0] * vec->vec[1]); + mat[2] = -(vec->vec[0] * vec->vec[1]); + mat[3] = 1 - (vec->vec[1] * vec->vec[1]); + } else if((strcmp(plane, "R") == 0) && matSize > 2) { + mat[0] = 1 - (vec->vec[0] * vec->vec[0]); + mat[1] = -(vec->vec[0] * vec->vec[1]); + mat[2] = -(vec->vec[0] * vec->vec[2]); + mat[3] = -(vec->vec[0] * vec->vec[1]); + mat[4] = 1 - (vec->vec[1] * vec->vec[1]); + mat[5] = -(vec->vec[1] * vec->vec[2]); + mat[6] = -(vec->vec[0] * vec->vec[2]); + mat[7] = -(vec->vec[1] * vec->vec[2]); + mat[8] = 1 - (vec->vec[2] * vec->vec[2]); + } else { + PyErr_SetString(PyExc_AttributeError, "mathutils.OrthoProjectionMatrix(): unknown plane - expected: 'r' expected for axis designation\n"); + return NULL; + } + } + if(matSize == 4) { + //resize matrix + mat[10] = mat[8]; + mat[9] = mat[7]; + mat[8] = mat[6]; + mat[7] = 0.0f; + mat[6] = mat[5]; + mat[5] = mat[4]; + mat[4] = mat[3]; + mat[3] = 0.0f; + } + //pass to matrix creation + return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); +} + +static char C_Matrix_Shear_doc[] = +".. classmethod:: Shear(plane, factor, size)\n" +"\n" +" Create a matrix to represent an shear transformation.\n" +"\n" +" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'], where a single axis is for a 2D matrix.\n" +" :type plane: string\n" +" :arg factor: The factor of shear to apply.\n" +" :type factor: float\n" +" :arg size: The size of the shear matrix to construct [2, 4].\n" +" :type size: int\n" +" :return: A new shear matrix.\n" +" :rtype: :class:`Matrix`\n"; + +static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) +{ + int matSize; + char *plane; + float factor; + float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + + if(!PyArg_ParseTuple(args, "sfi", &plane, &factor, &matSize)) { + PyErr_SetString(PyExc_TypeError,"mathutils.ShearMatrix(): expected string float and int\n"); + return NULL; + } + if(matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_AttributeError,"mathutils.ShearMatrix(): can only return a 2x2 3x3 or 4x4 matrix\n"); + return NULL; + } + + if((strcmp(plane, "X") == 0) + && matSize == 2) { + mat[0] = 1.0f; + mat[2] = factor; + mat[3] = 1.0f; + } else if((strcmp(plane, "Y") == 0) && matSize == 2) { + mat[0] = 1.0f; + mat[1] = factor; + mat[3] = 1.0f; + } else if((strcmp(plane, "XY") == 0) && matSize > 2) { + mat[0] = 1.0f; + mat[4] = 1.0f; + mat[6] = factor; + mat[7] = factor; + } else if((strcmp(plane, "XZ") == 0) && matSize > 2) { + mat[0] = 1.0f; + mat[3] = factor; + mat[4] = 1.0f; + mat[5] = factor; + mat[8] = 1.0f; + } else if((strcmp(plane, "YZ") == 0) && matSize > 2) { + mat[0] = 1.0f; + mat[1] = factor; + mat[2] = factor; + mat[4] = 1.0f; + mat[8] = 1.0f; + } else { + PyErr_SetString(PyExc_AttributeError, "mathutils.ShearMatrix(): expected: x, y, xy, xz, yz or wrong matrix size for shearing plane\n"); + return NULL; + } + if(matSize == 4) { + //resize matrix + mat[10] = mat[8]; + mat[9] = mat[7]; + mat[8] = mat[6]; + mat[7] = 0.0f; + mat[6] = mat[5]; + mat[5] = mat[4]; + mat[4] = mat[3]; + mat[3] = 0.0f; + } + //pass to matrix creation + return newMatrixObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); +} + /* assumes rowsize == colsize is checked and the read callback has run */ static float matrix_determinant(MatrixObject * self) { @@ -1326,6 +1758,13 @@ static struct PyMethodDef Matrix_methods[] = { {"to_quat", (PyCFunction) Matrix_toQuat, METH_NOARGS, Matrix_toQuat_doc}, {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, + + /* class methods */ + {"Rotation", (PyCFunction) C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc}, + {"Scale", (PyCFunction) C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc}, + {"Shear", (PyCFunction) C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc}, + {"Translation", (PyCFunction) C_Matrix_Translation, METH_O | METH_CLASS, C_Matrix_Translation_doc}, + {"OrthoProjection", (PyCFunction) C_Matrix_OrthoProjection, METH_VARARGS | METH_CLASS, C_Matrix_OrthoProjection_doc}, {NULL, NULL, 0, NULL} };