Monday, March 28, 2016

Tutorial - Using Open Maya to set vertex positions to match UV coordinates (easy)

This is the first tutorial that should lead to creating your own UV blendshape deformer in Maya. I am doing this as many people asked me for my UV blendshape deformer.

In this tutorial I will show how to write a simple Python script that uses OpenMaya to set the positions of points from a mesh to match the UV coordinates of each point. As one vertex can have multiple UV coordinates (as many possible UV coordinates as faces connected to the vertex), I will be using only the first UV coordinate in this script.

Let´s start with the basics: import maya cmds and OpenMaya:
import maya.cmds as cmds
import maya.OpenMaya as om


Now we can create some geometry (e.g. a sphere) in our scene:
cmds.polySphere(r= 1.0, ch=True)


We now need to get the Dag path to the selected object (the sphere we have just created):
sel = om.MSelectionList()
om.MGlobal.getActiveSelectionList(sel)
myMeshDagPath = om.MDagPath()
sel.getDagPath(0, myMeshDagPath)


Time to iterate over all vertices of the mesh (with MItMeshVertex) and set each vertex position to the 2d position of the first uv coordinate:
... create the vertex iterator
myMeshVtxIt = om.MItMeshVertex(myMeshDagPath)
... then we iterate using a while condition until the iterator has not reached the last vertex (isDone())
while not myMeshVtxIt.isDone():
    myMeshVtxIt.next()
... we read the u and v coordinate of each iterated vertex

while not myMeshVtxIt.isDone():
    uCoords = om.MFloatArray()
    vCoords = om.MFloatArray()
    faceIDs = om.MIntArray()
    myMeshVtxIt.getUVs(uCoords, vCoords, faceIDs)
    myMeshVtxIt.next()
... we create a new 3d point coordinate (MPoint) using the UV coordinates:

while not myMeshVtxIt.isDone():
    uCoords = om.MFloatArray()
    vCoords = om.MFloatArray()
    faceIDs = om.MIntArray()
    myMeshVtxIt.getUVs(uCoords, vCoords, faceIDs)
    newVertexPosition = om.MPoint(uCoords[0], 0.0, vCoords[0])
    myMeshVtxIt.setPosition(newVertexPosition, om.MSpace.kObject)
    myMeshVtxIt.next()


Finally here the complete code:
import maya.cmds as cmds
import maya.OpenMaya as om

cmds.polySphere(r= 1.0, ch=True)

sel = om.MSelectionList()
om.MGlobal.getActiveSelectionList(sel)
myMeshDagPath = om.MDagPath()
sel.getDagPath(0, myMeshDagPath)

myMeshFn = om.MFnMesh(myMeshDagPath)

myMeshVtxIt = om.MItMeshVertex(myMeshDagPath)
while not myMeshVtxIt.isDone():
    uCoords = om.MFloatArray()
    vCoords = om.MFloatArray()
    faceIDs = om.MIntArray()
    myMeshVtxIt.getUVs(uCoords, vCoords, faceIDs)
    newVertexPosition = om.MPoint(uCoords[0], 0.0, vCoords[0])
    myMeshVtxIt.setPosition(newVertexPosition, om.MSpace.kObject)
    myMeshVtxIt.next()


Now you can take out the line that creates the sphere and make it work with any geometry you have selected in the scene.
You should now add some check to this code, the most basic being checking if the selected object is a mesh!

Continue to the next tutorial in this series here.

No comments:

Post a Comment