Faster way to find number of influences - Maya

Hi,

I’m looking to optimize my process for finding verts with an influence over a certain number. I’m currently using a vert-scrubbing loop using cmds.skinPercent, and wondering if someone has a better way to do it. Any ideas how to do this faster?

#—Get the number of verticies
vertCount=cmds.polyEvaluate( ‘myMesh’ , v=True)

#—Sift through the verts looking for influences above 4
for i in range(0, vertCount):

numOfVertInfluences = cmds.skinPercent( 'mySkinCluster' , 'myMesh' + '.vtx[' + str(i) +']' , q=True , value=True , ignoreBelow=0.001 ) 
#---If the number of influences is above 4 then select the vert
if (len(numOfVertInfluences) > 4 ) :
    cmds.select(skinName[0] + '.vtx[' + str(i) +']' , add=True)

print(‘Selected verts have more than 4 influences.’)

Thanks and any suggestions are welcome!

just a shot from the hip, you might be able to get some savings from using a list comprehension and string.format or %


mesh = 'myMesh'
cluster = 'mySkinCluster'
threshold = 4
vertcount = cmds.polyEvaluate(mesh, v=True)
verts = [v for v in xrange(vertcount) if cmds.skinPercent(cluster, '%s.vtx[%i]' % (mesh, v)) > threshold]

This is a cool way to do it. Thanks for the reply! Doesn’t save me any time unfortunately. I may be too picky, though. my below method takes between 6 and 7 seconds.

Much Thanks!


mesh = 'myMesh'       
cluster = 'MySkinCluster'

#---Get the number of verticies
vertCount=cmds.polyEvaluate( mesh , v=True)

#---Sift through the verts looking for influences above 4
for i in range(0, vertCount):
    
    numOfVertInfluences = cmds.skinPercent( cluster , mesh + '.vtx[' + str(i) +']' , q=True , value=True , ignoreBelow=0.001 ) 
    #---If the number of influences is above 4 then select the vert
    if (len(numOfVertInfluences) > 4 ) :
        cmds.select(mesh + '.vtx[' + str(i) +']' , add=True)

print('Selected verts have more than 4 influences.') 


the list comprehension wasn’t faster? How many verts/bones is in your test?

Running the following on a mesh with 100k verts and a dozen bones was almost instant:


mesh = 'pPlane1'
[v for v in xrange(676) if len(cmds.skinPercent('skinCluster1', '%s.vtx[%i]' % (mesh, v), query=True, value=True, ib=0.001)) > 0]

why not using simply this ?

cmds.getAttr(‘skinCluster1.weightList[:].weights[0]’)

weightList[:] for all vertices

weights[0] for the first bone, you can use as well other number or range

“the list comprehension wasn’t faster? How many verts/bones is in your test?”

I have 256 bones and 18k verts. EDIT: I’ve looked at it again and list comprehension method is a little faster, by a second or two.

Thanks a million for the help!

Does the list comprehension thing also work for setting weights? I wrote a tool which crops the influence weights down to 4, but the only way I’ve been able to set the weights so far is by using skinPercent on each individual vert. It took over 10 minutes to crop the weights on a full character :stuck_out_tongue:

[QUOTE=Twiggy;27619]Does the list comprehension thing also work for setting weights? I wrote a tool which crops the influence weights down to 4, but the only way I’ve been able to set the weights so far is by using skinPercent on each individual vert. It took over 10 minutes to crop the weights on a full character :P[/QUOTE]

I can’t speak directly to your question, but can share my experience with my weight influence pruning tool. I use a loop w/ skinPercent and getting meshes down to 4 influences on a 18k vert mesh only takes a minute for me. Below is the loop I use, maybe I’m doing something different?

Discovering Offending Verts


    for i in range(0, vertCount):
        numOfVertInfluences = cmds.skinPercent( str(skinClusterName[0]) , skinName[0] + '.vtx[' + str(i) +']' , q=True , value=True , ignoreBelow=0.001 )
        if (len(numOfVertInfluences) > myNumInfluences ) :
            cmds.select(skinName[0] + '.vtx[' + str(i) +']' , add=True)


After discovering the bad verts, I iterate on only those verts:



     for vert in badVerts:
            #unlock all influences on the vert
            influenceNames = pm.skinPercent(skinClusterName[0], vert , query=True, transform=None) 
            for influence in influenceNames:
                cmds.setAttr( influence + '.liw' , 0 )

            #---loop to get this down to 4 influences
            numOfInfluences = len(pm.skinPercent( skinClusterName[0], vert , ignoreBelow=0.001, query=True, value=True ))
            
            for num in range(0,numOfInfluences - myNumInfluences):
                vertValues = pm.skinPercent( skinClusterName[0], vert , ignoreBelow=0.00001, query=True, value=True )
                influenceNames = pm.skinPercent(skinClusterName[0], vert , query=True, ignoreBelow=0.00001, transform=None)           
                lowestValue = vertValues[0]
                lowestInfluence = influenceNames[0]
            
                for i in range(0,len(vertValues)) :
                    if lowestValue >= vertValues[i]:
                        lowestValue = vertValues[i]
                        lowestInfluence = influenceNames[i]
                cmds.skinPercent( skinClusterName[0], vert, transformValue=[(lowestInfluence, 0)])


Maybe this is helpful for you? This is how I do it anyway.

> tonthebone

Just tested your method, it’s definitely a lot quicker, nice one!

you could look into using the python api. it’s more verbose/tedious code, but you can get a significant speed increase over the python mel commands.