Surface Constrained Control

I’ve been toying the the concept of constraining a joint control to the surface of a skinned mesh.
This has been my result and steps I’ve taken to get here are documented below.

You can download my scene file here, the node editor should have several tabs that show these graphs.


The control hierarchy is setup like this:
The _orient can be used to setup the rest orientation of the setup.
The _auto can be driven but an RBF or anything really. More layers can be added, but they must be before _auto.



Connect the control’s translate through a multiplyDivide node and set input2 to -1. This allows us to change the transform of the control without any visual change.

Place the control setup at the location of the joint or wherever you want the rest location to be.

To constrain the control to the mesh I use a follicle in a setup like this.


The follicle shape node will need a UV coordinate to actually function so here is a little setup you can use to convert a worldspace position to a UV coordinate on a mesh.

Create a closestPointOnMesh node and a locator or any transform in worldspace. In this case I’ve made a locator and added to channels “U“ and “V“, just to make it easy to read the output.


Snap the UV_PROBE to the location of the control setup and copy the UV cords into the follicle shape node you created.


Once you have the UV coordinate in the shape node you should see the follicle transform the the same position as the UV_PROBE and the control setup. Create a pointContraint between the follicle transform and the _surface node in the control setup.

With that done we need to do a little matrix math to finalize the setup and connect the output to the joint.

We need to create a composeMatrix node (I called mine _dummyMatrix) and connect the control to it. Then we need a multMatrix node. Connect the output from the composeMatrix you just made to the multMatrix.matrixIn[0]. Next connect the world matrix of the _auto node to multMatrix.matrixIn[1]. The final matrix we need to plug in is the parentInverseMatrix of the joint, this just puts our result into the local space of the joint. Make sure you plug it into the multMatrix.matrixIn[2].
The final step is to connect the result of the multMatrix to the joint via a decompMatrix node as shown.


Some things to note, if your skin weights change it will change how the controls act as well as the final shape of your mesh. This connection is not 1:1, it is dependent on the skin cluster of the mesh. In any case, this should result in something like this.