tsStickyLips tool

This tool will let you easily create a sticky lips setup for your character. The setup created is based on a wire deformer.


1. Download the script from this link: tsStickyLips.rar;

2. Copy file tsStickyLips.pyc into your maya scripts/ folder;

3. From the script editor, in a python tab type:

import tsStickyLips



As the sticky lips deformation lies on top of other deformations, this should be your very last step in facial rigging.

1. Select top edges for the uplip and press ‘<<<’;

2.  Select top edges for the bottomlip and press ‘<<<’;

3. Press ‘Create stickyLips’ button.

The script will create a copy of the geometry with sticky lips setup. You can hide the previous geo and go rendering with this copy.


Optional parameters:

The tool provides automatically on weighting the wire deformer influence areas. Two optional parameters can be tweaked to change how the weighting is done:

- Selection growth: Grows vertex selection before setting weight influence to 1;

- Smoothness: How many times the weighting should be smoothed.


Here’s the source code of the main procedure for the tech guys:

def createStyckyLips(top_edges, bottom_edges, selection_growth = 2, smoothing=8):
 base_mesh = top_edges[0].split(".")[0]

 # Create curve on top edge sel on duplicated mesh
 top_curve = cmds.polyToCurve(form=2, degree=1)[0]
 top_curve_shape = cmds.listRelatives(top_curve, c=1)[0]

 # Create curve on bottom edge sel on duplicated mesh
 bottom_curve = cmds.polyToCurve(form=2, degree=1)[0]
 bottom_curve_shape = cmds.listRelatives(bottom_curve, c=1)[0]

 # Create wire average curve
 avg_node = cmds.createNode("avgCurves")
 cmds.setAttr(avg_node + ".automaticWeight", 0)
 cmds.setAttr(avg_node + ".automaticWeight", 0)
 avg_curve = cmds.duplicate(top_curve)[0]
 avg_curve_shape = cmds.listRelatives(avg_curve, c=1)[0]
 cmds.connectAttr(top_curve_shape + ".worldSpace[0]", avg_node + ".inputCurve1", force=1)
 cmds.connectAttr(bottom_curve_shape + ".worldSpace[0]", avg_node + ".inputCurve2", force=1)
 cmds.connectAttr(avg_node + ".outputCurve", avg_curve_shape + ".create", force=1)

 #Create duplicate mesh with inputs
 dup_mesh = mel.eval("polyDuplicateAndConnect;")[0]
 dup_top_edges = [x.replace(base_mesh, dup_mesh) for x in top_edges]
 dup_bottom_edges = [x.replace(base_mesh, dup_mesh) for x in bottom_edges]

 # Create wire deformer on duplicate mesh
 wire_deformer = mel.eval("wire -gw false -en 1.000000 -ce 0.000000 -li 0.000000 -w " + avg_curve + " " + dup_mesh +";")[0]
 base_wire = avg_curve + "BaseWire"
 base_wire_shape = cmds.listRelatives(base_wire, c=1)[0]
 cmds.connectAttr(avg_node + ".outputCurve", base_wire_shape + ".create", force=1)

 # Set wire deformer params
 cmds.setAttr( wire_deformer + ".scale[0]", 0)
 cmds.setAttr( wire_deformer + ".envelope", 1.2)
 editAttrs(wire_deformer, ["ce","te","li","ro","sc[0]"], l=1, k=0, cb=0)

 #Set weights

 #Zero all weights
 mel.eval("artAttrToolScript 4 \"" + wire_deformer +"\";")
 mel.eval("artAttrPaintOperation artAttrCtx Replace;")
 mel.eval("artAttrCtx -e -value 0 `currentCtx`;")
 mel.eval("artAttrCtx -e -clear `currentCtx`;")

 #Select vertices
 mel.eval("changeSelectMode -component;")
 mel.eval("hilite -r " + dup_mesh + " ;")
 mel.eval("setComponentPickMask \"Line\" true;")
 cmds.select(dup_top_edges, dup_bottom_edges)

 for i in range(selection_growth):

 #Set weights for region to 1
 mel.eval("artAttrValues artAttrContext;")

 mel.eval("artAttrToolScript 4 \"" + wire_deformer +"\";")
 mel.eval("artAttrPaintOperation artAttrCtx Replace;")
 mel.eval("artAttrCtx -e -value 1 `currentCtx`;")
 mel.eval("artAttrCtx -e -clear `currentCtx`;")

 #Smooth n times
 mel.eval("artAttrValues artAttrContext;")
 mel.eval("artAttrPaintOperation artAttrCtx Smooth;")

 for i in range(smoothing):
 mel.eval("artAttrCtx -e -clear `currentCtx`;")

 mel.eval("changeSelectMode -object;")

 # Group,rename all objects
 main_grp = cmds.group(em=1, w=1, n=resolveName("GRP_sticky"))
 cmds.setAttr(main_grp + ".visibility", 0)
 editAttrs(main_grp, ["tx","ty","tz","rx","ry","rz","sx","sy","sz"], l=1, k=0, cb=0)

 top_curve = cmds.rename(top_curve, resolveName("CRV_sticky_top"))
 bottom_curve = cmds.rename(bottom_curve, resolveName("CRV_sticky_bottom"))
 avg_curve = cmds.rename(avg_curve, resolveName("CRV_wire"))
 base_wire = cmds.rename(base_wire, resolveName(avg_curve + "BaseWire"))

 cmds.parent(top_curve, bottom_curve, avg_curve, base_wire, main_grp)
 if cmds.listRelatives(dup_mesh, p=1):
 cmds.parent(dup_mesh, w=1)

 wire_deformer = cmds.rename(wire_deformer, resolveName("stickyWire"))

Have fun!



Maya Tutorial: Pixar Presto like on surface controllers

A very quick tutorial to show a technique to achieve controllers stick on mesh just like seen in Pixar Presto presentations.

Very fast as based only on wraps (of lowpoly meshes) and blendshapes. If you don’t want to use wraps, you can use a script to connect the position of closest vertices between target mesh and the wrapped mesh.

You can use follicles or rivets to stick the transform on the surface and script jobs to emphasize the control’s color when selected.

It’s my very first tutorial where talking, apologize for my English.

Procedural spider rig

Rig made for a tv mini series.
Set up of various expression to drive the procedural walking.
Each leg has its own procedural expression, so the local distance during walking are correctly evaluated for each leg.
Model: Adam Muratoff, Anthem Fx.

Rig made for a tv mini series.Set up of various expression to drive the procedural walking. Each leg has its own procedural expression, so the local distance during walking are correctly evaluated for each leg.
Model: Adam Muratoff, Anthem Fx.


While rebuilding entirely the website, I took some spare time to create this illustration.
Enjoy it and keep crawling around for the new website ;)


Hi all,
My work and other stuff kept me away from updating the website for a long time.
I am going to come up with a new webiste in the next weeks, with update contents and free tools for you.
Stay tuned!

tsPoseSpaceDeformer demo

This is a demo of one of my latest tools. It is inspired to the Michael Comet’s pose space deformer plugin, but with a substantial difference: no extra plugin is needed.
The pose space deformation is realized by creating a corrective blendshape target driven by a node network.
Here is how it works:

- Select your mesh in the binding pose. The tool will store the character pose as base pose;
- Put your character in a problematic pose and press ‘Start sculpting’. A proxy mesh (the green one) is generated and lets you correct the mesh geometry to the desired shape. Once finished hit ‘Finalize scuplting’;
- The next phase is connecting the corrective shape to your pose. You can choose between 3 different ways: (Attribute) Expression, (Attribute) Node network, (Joint) Radial distance.
The first two work basically in the same way, except the first is a combination of an expression and a node network, while the second one is fully network based. Each attribute determining the pose
is considered as a coordinate in a hyperspace. The blendtarget weight is the result of the normalized projection of the current pose vector on the “target pose – base pose” vector.
The third way, instead working on the single attributes, it works on influence basis. The blendshape weight is the result of a combination of the radial distance between the base pose and the target pose for each influence determining the pose.
- You can choose wich attributes/influences determine the pose on the Attribute list tab. The tool automatically proposes the influences that changed their coordinates from the base pose to the current pose.
- There is an option for pruning the blendshape weights (You can see the auto pruned target maps in the video): very useful if you end up creating tons of corrective shapes and you don’t want to loose performance;
- From the mirror frame, you can enable/disable the creation of the mirror blendshape;
- Finally, to connect the blendshape and its mirror, just click on “Create corrective blendshape”.
- Once finished, you can tweak the weights of your targets along the deformation by editing the ramp shaders driving them.

Future developments:

- High res sculpting for displacement map generation and driving.

Thanks for watching


tsFrameBlendshapes tool

This tool is part of my personal toolset.
It let’s you easily create, connect and animate animation based corrective blendshapes,.
Just go to the frame you want to correct/deform, hit “Sculpt” and edit the shape of your mesh. The cool thing is that the script works on pose: you can sculpt the corrective shape in any pose, then the script will bring back your deformed mesh in base pose automatically to create your corrective shape.
Coded in python.