I started working on an eye rig solution based on Marco Giordano’s work. All credit goes to him for coming up with it. I had seen it once before, but learned the technique through Wade Ryer’s course. The setup works by having locators ride a curve and joints pointing towards those locators. When you then deform the curve, the locators move, which in turn move the joints, which in turn moves the skin. The beauty about this set up is that it really feels like the eye lids are sliding over the eye ball. I’ve added some driven behavior for looking up, down, left and right and the whole things feels really good when you move it.
Because this is something I’d like to add to more of my rigs, I started scripting out the process. I’m still working on it, but wanted to add a little update on the whole thing anyway 🙂
I’m just adding this here on my site because I always need to find it in older scripts and I don’t want to keep digging for it. So, as far as I know, there’s no easy way to set an enum attribute by a string value in Python. You can only set it by index value, which doesn’t do you much good if you don’t know the index of the value you need. In case you need it here’s a quick little function to use a string value to set the enum:
Setting up space switching on a rig, be it for orientation or props or something else, can be quite an elaborate process. Having to set up the different empty groups/locators, constraints and setting up the actual switch through set driven keys gets boring real fast. So I wanted to show off this little tool that allows you to very quickly set up space switching on your rig.
You can use any transform node to act as the parent of your spaces. Select the controller you want to add the switch to and make sure the spaces you want are also selected in the tool. If you use offset/driven/parent/whatever groups for your controller, you can tell the tool how many nodes it should travel up the hierarchy to add the constraints to.
import pymel.core as pm
ignore_below = 0.0001
meshes = pm.selected()
if len(meshes) > 0:
for mesh in meshes:
#use a quickie MEL command to get the skincluster
skin = pm.mel.eval('findRelatedSkinCluster %s' % mesh)
#get the max allowed influenced for the current skinCluster
max_influences = pm.PyNode(skin).getMaximumInfluences()
#empty list to hold a pair for transform value
transform_value = 
#get the total number of vertices in the selected mesh
total_verts = pm.polyEvaluate(vertex=True)
for i in xrange(0, total_verts):
transform_value = 
vertex = "%s.vtx[%s]" % (mesh, i)
trans = "%s %s" % (skin, vertex)
influences = pm.skinPercent(skin, vertex, ignoreBelow = ignore_below, query = True, transform = None)
values = pm.skinPercent(skin, vertex, ignoreBelow = ignore_below, query = True, value = True)
# if there are more entries in the transform values list than we have allowed influences
# we know we're going to have to delete some
if len(transform_value) > max_influences:
#sort the transform value list from small to big, based on the second entry of the pair (value)
transform_value.sort(key = lambda list: list)
#add a transform value pair to our list
for j in xrange(0, len(influences)):
tv = [influences[j], values[j]]
#figure out how many extra influences there are
extra_influences = len(transform_value) - max_influences
print "Found %s influences too many on %s" % (extra_influences, vertex)
#loop through all these extra influences
for k in xrange(0, extra_influences):
joint_name = str(transform_value[k])
value = transform_value[k]
#and set their influence to 0
print "Removing: %s, value: %s" % (joint_name, value)
pm.skinPercent(skin, vertex, transformValue = [joint_name, 0], normalize = True)
I adapted a script that was written in MEL to remove extra influences on particular vertices on a skinned mesh. Mostly because it didn’t always work on my machine and I didn’t want to try and figure out why… I don’t like having to edit MEL code and avoid it where I can 🙂
When you set up your skinCluster and very carefully tell Maya to not go over your maximum allowed influences per vert, Maya doesn’t always listen. Most likely floating point rounding errors creep in when painting skin weights and normalizing the skinCluster. Most times you don’t know really care about these extra influences because their values are usually extremely small ( < 0.001). However, if for whatever reason you need to get rid of these extremely small values and don't want to prune weights, you can use something like this to remove only the smallest influences depending on how many influences are allowed for your skinCluster.
The game that I’ve been part of for the last 18 months has finally officially launched world wide in the Google Play Store and on the Apple App Store. I’m incredibly proud of all the work that has gone into making this game a reality. I think we really pushed the limit of what real time strategy and world building games look and play like on mobile devices. Building on the amazing work people did before I joined the studio, we took the animation and technology to a new level.
Be sure to download it on your mobile device and have fun with it!