Search code examples
pythonapimatrixmaya

Maya Python API Scaling a matrix about another matrix


So I have two matrices in maya. I want to reflect one matrix about the x and y of that other matrix.

So as an example:

Object 1's matrix is as such: [1.0, 0.0, 0.0, 0.0, 0.0, 0.70710678118654746, 0.70710678118654757, 0.0, 0.0, -0.70710678118654757, 0.70710678118654746, 0.0, 0.0, 0.0, 0.0, 1.0] This is an object at the origin rotated 45 degrees along the x.

Object 2's matrix is as such: [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 2.0, 2.0, 2.0, 1.0] Sitting at 2,2,2 in worldspace with no rotation values.

When reflected on scaleX of object1 we get a matrix like this: [1.0, 0.0, -0.0, 0.0, -0.0, 0.70710678118654746, -0.70710678118654757, 0.0, 0.0, 0.70710678118654757, 0.70710678118654746, 0.0, 2.0, 2.8284271247461898, -2.2204460492503131e-16, 1.0]

This is just me querying matrices when I'm manually reflecting the object's scale. What would the method be for doing this in python API?

I'm assuming some way with MTransformationMatrix but aren't able to figure that one out.

Any help would be greatly appreciated!


Solution

  • Typically you'd create a MMatrix or MTransformationMatrix in the API and multiply them together in series to get the transformation you want. The hassle is getting the values from Python into those classes, which requires the dreaded MScriptUtil

    import maya.OpenMaya as OpenMaya
    import maya.cds as cmds
    
    
    def APIMatrix ( valList ):  # where vallist is a list of floats
        mat = OpenMaya.MMatrix()
        OpenMaya.MScriptUtil.createMatrixFromList( valList, mat )
        return mat
    

    Would create an MMatrix from a list of python numbers, for example. In Pymel things are easier using the Matrix class:

    import pymel.datatypes as dt
    
    i = dt.Matrix() # creates an identity matrix
    m = dt.Matrix ( list_of_values) # use supplied numbers
    

    Once you've multiplied your matrices you can apply them with the xform command:

    cmds.xform(item, m = my_new_matrix)
    

    or in pymel:

    import pymel.core as pm
    pm.xform(item, my_new_pymel_matrix)
    

    MMatrix is a raw matrix - just numbers for doing math MTransformationMatrix is more like the actual transform of an object : it offers methods for, eg, poking numbers into the translation or rotation without knowing which matrix members to twiddle by hand:

    def get_obj_quaternion ( mayaTransform, worldSpace=True ):
        '''
        gets the rotation quat for the supplied dag node in world or local space
        '''
        #convert from mMatrix to MTransformationMatrix....
        mMatrix = matrix_from_transform( mayaTransform, worldSpace=worldSpace )
        mTransformMtx = OpenMaya.MTransformationMatrix( mMatrix )
    
        # MscriptUtil. Sigh
        xPtr = OpenMaya.MScriptUtil(0.0)
        x = xPtr.asDoublePtr()
    
        yPtr = OpenMaya.MScriptUtil(0.0)
        y = yPtr.asDoublePtr()
    
        zPtr = OpenMaya.MScriptUtil(0.0)
        z = zPtr.asDoublePtr()
    
        wPtr = OpenMaya.MScriptUtil(0.0)
        w = wPtr.asDoublePtr()
    
        mTransformMtx.getRotationQuaternion( x, y, z, w )
        # getRotationQuaternion is an MTransformationMatrix method
    
        #convert them back to normal python floats
        x = OpenMaya.MScriptUtil().getDouble( x )
        y = OpenMaya.MScriptUtil().getDouble( y )
        z = OpenMaya.MScriptUtil().getDouble( z )
        w = OpenMaya.MScriptUtil().getDouble( w )
    
        return x, y, z, w
    

    So in your case you'd want to :

    1) get the matrix of your target object

    2) get the matrix of your reflection object

    3) make a reflection matrix, for example :

     -1  0  0  0
      0  1  0  0 
      0  0 -1  0
      0  0  0  1
    

    is the reflection matrix for reflecting the X and Z axes

    4) Reflect target as:

    reflected_matrix = reflectXZMatrix * reflectionObjectMatrix
    result = target_matrix * reflected_matrix
    cmds.xform( target_object, m = result)
    

    This is a minimalist version using only MMatrices - if you needed to construct the matrix yourself, an MTransformationMatrix would let you set up a rotation or scale matrix without manually managing the numbers in the matrices.