Lattice -> Joints

It’s not perfect, but here’s a small script that samples a lattice and tries to set joint weights based on the influence of each lattice point.

Given a set of lattice vertices and a model influenced by these vertices it will create joints at every lattice point, bind a skin and set the weights.

Usage: just edit the variables at the top & run the script. It’s slapped together really quickly.

It moves every lattice point one by one & stores the amount of movement that occured per vertex, which is basically the weight of this point for that vertex.

Issues: Small weights are completely vanishing, you could try dividing the sampled movement by the amout of movement to get a 0-1 weight, then apply an inverse s-curve or pow / sqrt to that value and use it as weight instead.

Requirements: to set all weights really fast I use a custom “skinWeightsHandler” command, you can write your own ‘set all weights for all joints and then normalize’ routine or get the plugin by installing Perry Leijten’s skinning tools for which I originally made this plugin.

model = r'polySurface1'
influences = (r'ffd1Lattice.pt[0][0][0]',
r'ffd1Lattice.pt[0][0][1]',
r'ffd1Lattice.pt[0][1][0]',
r'ffd1Lattice.pt[0][1][1]',
r'ffd1Lattice.pt[1][0][0]',
r'ffd1Lattice.pt[1][0][1]',
r'ffd1Lattice.pt[1][1][0]',
r'ffd1Lattice.pt[1][1][1]')

def sample(model):
    return cmds.xform(model + '.vtx[*]', q=True, ws=True, t=True)[1::3]

def difference(list, list2):
    stack = [0] * len(list)
    for i in range(len(list)):
        stack[i] = abs(list2[i] - list[i])
    return stack

def gather(model, influences):
    original = sample(model)
    weights = {}
    for influence in influences:
        cmds.undoInfo(ock=True)
        cmds.xform(influence, ws=True, r=True, t=[0, 1000, 0])
        weights[influence] = difference(sample(model), original)
        cmds.undoInfo(cck=True)
        cmds.undo()
    return weights

weights = gather(model, influences)
# generate joints
joints = []
for influence in influences:
    pos = cmds.xform(influence, q=True, ws=True, t=True)
    cmds.select(cl=True)
    joints.append(cmds.joint())
    cmds.xform(joints[-1], ws=True, t=pos)
# concatenate weights in the right way
vertexCount = len(weights.values()[0])
influenceCount = len(influences)
vertexWeights = [0] * (vertexCount * influenceCount)
for i in xrange(vertexCount):
    tw = 0
    for j, influence in enumerate(influences):
        vertexWeights[i * influenceCount + j] = weights[influence][i]
        tw += weights[influence][i]
    if not tw:
        # weight is 0
        continue
    for j in xrange(influenceCount):
        vertexWeights[i * influenceCount + j] /= tw
# expand to shape
if not cmds.ls(model, type='mesh'):
    model = cmds.listRelatives(model, c=True, type='mesh')[0]
# bind skin
cmds.select(model, joints)
skinCluster = cmds.skinCluster()
# set weights
cmds.SkinWeights([model, skinCluster],  nwt=vertexWeights)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>