Thursday 3 April 2014

Vector Matrix multiplication in Maya

Multiply PyMel vectors by matrices will not give you the result you might expect. Try a simple operation like this:
import pymel.core as pm
pm.polySphere() # Make a sphere.
pm.move((0,1,0)) # Move 1 unit up.
wm = pm.SCENE.pSphere1.getMatrix(worldSpace=True) # Get the local->world space matrix.
v = pm.dt.Vector((0,0,0)) # Create a zero vector.
print v*wm # Multiply the zero vector by the matrix and print the resulting vector.
At this point you'd expect to get (0, 1, 0) - the result of multiplying a (0,0,0) vector by a matrix that translates points by 1 in the Y axis. Instead you'll get (0,0,0). The reason is PyMel's vectors are only 3 components long, and the matrix is 4x4. Mathematically that's a no-no, but PyMel is happy to do it, but what you're getting is only the rotation and scale contained in the matrix affecting the vector. These are contained in the 3x3 part of the matrix while translation lives in the fourth row.
To get the translation you need to add the w component. However trying to initialize a PyMel Vector object with 4 components is not possible. Instead you need to use the VectorN class. If we do that in the code above, it will work as expected:
v = pm.dt.VectorN((0,0,0,1)) # Create a zero vector.
Alternatively you can use the Point class, which describes a 4-component vector:
v = pm.dt.Point((0,0,0))