Search code examples
pythonmatrixrotationmaya

Maya python get correct matrix decomposition from point on curve


I'm pretty rusty with my matrix math and am a bit lost as far as how to correctly calculate the 3x3 rotation matrix using the vectors from a maya point on curve info node. I am able to get the position in the 4x4 matrix easily because that is just simply putting the position vector into the right matrix values.

I've read quite a bit on it on google, but different sources seem to say different things about how to construct it correctly.

At the moment I think I want to be constructing a matrix like this but am not sure if this is correct:

TanU.x  TanU.y  TanU.z 0
Norm.x  Norm.y  Norm.z 0
TanV.x  TanV.y  TanV.z 0
pos.x   pos.y   pos.z  1

From my point on curve node I have vectors for: Position Normal Tangent

I'm not sure how to get the tangentu and tangentv. Think this is based on the u and v space when calculating mesh Normals?

I am trying to get results similar to the example at the bottom of the page here just to get started, but once I've got it working I've got a bunch of uses for a correct 4x4 matrix that will help me out a ton: http://www.chrisevans3d.com/pub_blog/maya-python-vector-math-primer/#comment-191332

Unfortunately in the example you can't see what is being hooked up to the cross products which is all I really need.

Any advice or help is much appreciated!


Solution

  • If you have the normal and tangent of the point on curve you just need the cross vector of those two for your third vector. The order of those vectors is convention driven, not set in stone -- but to get a good matrix back you need three vectors at right angles to each other.

    Assuming you have a normal and a tangent:

    from maya.api.OpenMaya import MVector, MMatrix
    import maya.cmds as cmds
    
    normal_vector = MVector(*cmds.getAttr('pointOnCurveInfo1.result.normal')).normal()
    tangent_vector = MVector(*cmds.getAttr('pointOnCurveInfo1.result.tangent')).normal()
    cross_vector = normal_vector ^ tangent_vector
    position = MVector(*cmds.getAttr('pointOnCurveInfo1.result.position'))
    matrix = (
     tangent_vector[0], tangent_vector[1], tangent_vector[2], 0,
         normal_vector [0], normal_vector [1], normal_vector[2],  0,
         cross_vector[0],   cross_vector[1],   cross_vector[2],   0,
         position[0],       position[1],       position[2],       1
    )
    
     # if you want it in api form so you can do multiplies, etc:
    api_matrix = MMatrix(matrix)
    
    api_matrix
    

    If you're doing it like Chris's example you'd need a CrossProduct node hooked up to the pointOnCurveInfo's normal and tangents to do the same thing