Blendshape profiling tools?

I am looking for a way to query the deltas of each vertex moved in a blendshape. I know this info is stored int he blendshape node, but how can I access it with Python? Please tell me I don’t need to walk the alias list and turn on each morph and measure a distance of all verts from the base pos.

The positions for each target are stored in the blendshape node, but as far as I can tell you’ll still have to do the final calculation of how much a vertex will be transformed based upon combined shapes, envelope, and weights.

--> blendShape.inputTarget[0].inputTargetGroup

Is a compound attribute that stores information relating to each target. Target meaning each discrete, alias’d shape in the blendshape weights.

--> blendShape.inputTarget[0].inputTargetGroup[#].inputTargetItem

A compound attribute that refers to different shapes that make up a target. If you only have one shape per target (no intermediates), there will only be one index here. Each intermediate shape for the target will add another index. The indices for this are a bit odd. A shape that turns on at a weight of 1 has an index of 6000. An intermediate that is enabled at 0.5, has a weight of 5500.
From the docs:

index = wt * 1000 + 5000. Thus a weight of 1 corresponds to the index 6000. An inbetween placed at a weight of 0.5 would be at the index 5500.

So if we have one target shape, the target positions for that shape are stored:

--> blendShape.inputTarget[0].inputTargetGroup[0].inputTargetItem[6000].inputPointsTarget

Things get a bit confusing when you starting calculating painted weights. The weights (when painted for a target) are stored on:

--> blendShape.inputTarget[0].inputTargetGroup[0].targetWeights

The docs say this attribute stores “The weights themselves, in the same order as the components deformed by the deformation.”, but if I paint weights on .vtx[3], I will only see one entry in that list. I’m not sure how to get the correlation between that value and the component it’s weights affect.

(All from: blendShape node)

I had tried using this inputPointsTarget, but it always returns ‘None’, here’s an example:

print cmds.listConnections('head_mesh_blendShapes.inputTarget[0].inputTargetGroup[228].inputTargetItem[6000].inputGeomTarget')
>> [u'head_mesh__neck_swallow2']
print cmds.getAttr('head_mesh_blendShapes.inputTarget[0].inputTargetGroup[228].inputTargetItem[6000].inputPointsTarget')
>> None

I can watch this shape fire, can see the vert delta in the mesh that feeds into the blendShape node, and it’s frustrating that this value returns ‘None’. We aren’t painting weights or anything fancy, though we do have a ton of shapes and fixers.

Thanks for your help,

inputPointsTarget will always be None for a specific weight, if the same weight has an incoming connection to inputGeomTarget. The blendShape node will recalculate the vertex deltas every frame so long as that connection remains. This obviously slows down playback, so what you can do is delete the target shape, and the deltas will then get baked to inputPointsTarget. Only the modified verts will be stored, so you’ll need to get the list of modified verts from the componentList attribute.

As for the painted weights, targetWeights is an array with a one-to-one correlation with the number of vertices. So if you have the number of vertices and query each element of targetWeights (or a specific index), you’ll have the painted weight values.

Hope that helps.

Ah that’s what it was. I was just looking at the getAttr output of targetWeights, not querying the index of the vertex I had painted.

Thanks.

@senkusha - thanks for the info, but in a test scene with connections and geom targets, it returns delta info. In the scene with my face, not.