Maya 2022 API | Getting skin weights

Hi everyone,

I’ve been looking at the API documentation and playing around with it in the evenings.

I can’t figure out how to get skin weights using OpenMayaAnim.MFnSkinCluster.getWeights(), the documentation seems a little vague:
https://help.autodesk.com/view/MAYAUL/2022/ENU/?guid=Maya_SDK_py_ref_class_open_maya_anim_1_1_m_fn_skin_cluster_html

shape - must be the skinned mesh.
components - could this be the joint?
influence - could this be the vertex id?

I’m probably too tired to do this in the evening, but would anyone be able to point me in the right direction?

Thanks,
Ross

“shape” is the MDagPath to the skinned mesh.

“components” is probably gonna be built by a subclass of MFnComponent (IIRC, it’ll be MFnSingleIndexedComponent), and will be the vertices to return weights for.

“influence” is the index of the joint for this particular skincluster that you want to return weights for. Pass the joint as an MObject to MFnSkinCluster.indexForInfluenceObject to get that index.

1 Like

If you’d like an example to study, you can see how mGear does it, derived from a Chad Vernon tool.

mgear4/skin.py at master · mgear-dev/mgear4 · GitHub

And as for Chad Vernon’s tool, I’m not sure if it was a tool, or the results of this course: Writing a Production-Ready Skin Exporter (cgcircuit.com)

1 Like

So, it’s weird, for sure, to do this via the API. Here’s the secret sauce I learned:

import re
import maya.api.OpenMaya as om2

meshShapeName = "myMeshShape"
selList = om2.MSelectionList()
selList.add(meshShapeName )
meshDagPath = selList.getDagPath(0)

verts = [big list of "myMeshShape.vert[#'s]" you want to query weights on]
indices = [int(re.findall(r'\d+', vert)[-1]) for vert in verts]
singleIdComp = om2.MFnSingleIndexedComponent()
vertexComp = singleIdComp.create(om2.MFn.kMeshVertComponent) # MObject
singleIdComp.addElements(indices)

mFnSkinCluster  = None
mItDependencyGraph = om2.MItDependencyGraph(meshDagPath.node(),
                                            om2.MItDependencyGraph.kDownstream,
                                            om2.MItDependencyGraph.kPlugLevel)
while not mItDependencyGraph.isDone():
    mObject = mItDependencyGraph.currentNode()
    if mObject.hasFn(om2.MFn.kSkinClusterFilter):
        mFnSkinCluster  = oma2.MFnSkinCluster(mObject)
        break
    mItDependencyGraph.next()

weights, numInfs = mFnSkinCluster.getWeights(meshDagPath, vertexComp)

BTW, if you’re looking for a quality skinning tool with UI and full API support, allow me to plug my Skinner tool:

2 Likes

Thanks for all your responses, it’s been really helpful!
I have some time to play with tools this weekend so I’ll definitely give your skinning tool a go @ak_eric

I have script I’ve been testing
but If I add or remove any joints, I can’t apply the skin weight, I get an error:

RuntimeError: (kInvalidParameter): Object is incompatible with this method

I did try and check for matching influences(haven’t posted that). But what I’ve done doesn’t seem to work… the learning curve for the API is definitely steeper.

import maya.api.OpenMaya as om
import maya.api.OpenMayaAnim as oma
import re
#SHAPENAME = 'character2Shape'
#SKINCLUSTER = 'skinCluster1'

def get_parameters(SHAPENAME, SKINCLUSTER):
    # get shape
    mesh_path = om.MSelectionList().add(SHAPENAME).getDagPath(0)
    
    # get skin cluster
    skin_cluster = oma.MFnSkinCluster(om.MSelectionList().add(SKINCLUSTER).getDependNode(0))
    
    # get components
    inf_dags = skin_cluster.influenceObjects()
    inf_index = om.MIntArray()
    for x in range(len(inf_dags)):
        inf_index.append(int(skin_cluster.indexForInfluenceObject(inf_dags[x])))
    
    # get influences
    component = om.MFnSingleIndexedComponent()
    vertex_comp = component.create(om.MFn.kMeshVertComponent)
    indices = [int(re.findall(r'\d+', vert)[-1]) for vert in mc.ls(f'{SHAPENAME}.vtx[*]', fl=1)]
    component.addElements(indices)
    
    return mesh_path, vertex_comp, inf_index, inf_dags, skin_cluster

# get skin weights
path, comp, infs, dags, sk = get_parameters('characterShape', 'skinCluster1')

weights = sk.getWeights(path, comp, infs)


# set skin weights
path2, comp2, infs2, dags2, sk2 = get_parameters('character2Shape', 'skinCluster2')

sk2.setWeights(path2, comp2, infs2, weights)