Facial Autorig System






Before starting,

I would like to thank Niels Dervieux, Rigging Supervisor at Stim Studio,  who developped the autorigging system at Stim, which heavilly inspired me  for my  work.  I would also like to thank him for all the knowledge and wisdom he brought to me, and the possibility to explain his autorig logic here.

I would also thank Jean-Paul-Tossings, Founder and Technical Director at Polder Animation , who taught me matrices via his YouTube channel, the system with the guides is heavilly inspired from his work : https://www.youtube.com/@JeanPaulTossings/videos





For my graduation movie at ESMA, we decided to have a movie with multiple humanoid characters (One main character, and 17 “crowd” characters), and try to aim the same quality as a studio such as Illumination Studios .
As the production time is quite short, I decided to develop autorig systems for facial and body rigging in order to speed-up the process and spend more time on the deformations and retakes. The facial autorig was made after my body autorig, where I faced many challenges and learned by doing mistakes. So I basically took the entire setup and reshaped it in order to fit the facial rigging workflow.


This page will be talking about the facial autorigging system, but if you want to learn more about the workflow I used for the body, you can go here.


The autorigging system at Stim was a “procedural” way of rigging, where the autorig has many “tasks” to run (such as guides, controllers, rig etc...), in order to build the rig.
I loved this system, because it has a lot of advantages such as :

- keeping everything organized in the pipeline
- keeping all the data in .json files (so easy tweakable by the user)
- never work directly in the rig scene, so the work is never lost
- huge room for retakes
- the setup is straightforward, so really easy to understand

These advantages motivated me to reproduce this system for the production of our movie.





Summary :







The UI

For the UI, the goal was to create the simplest UI possible, and be able to dock the UI to the maya window, in order to save some space in the viewport and still be able to use the autorig. As I am a huge fan of The Matrix  (only the first two movies) I decided to do a The Matrix themed UI, that will also symbolize the fact that all my rigging setup is done with matrices.





The Tasks



    The tasks vary a bit from the facial autorig and the body autorig, but the logic stays the same.
    The user drag and drops a task, in the Tasks field, and then organizes them in order of build the rig.
    If needed, the user can also enable/disable the tasks, in order to run only specific tasks, and keep all the tasks in the ui.




    List of Facial Autorig Tasks :




Import

The first task is the import task, when dropped in the field , the usage of this task is to import something in the scene from the selected path, it could be a character model, a scene, etc...
It has a checkbox “Use NS” with a lineEdit used to input a custom namespace name, that will import the file with the custom namespace, for specific actions (mostly scriptwise).


Guides

This task is used to save guides position in the scene, it checks for every object ending with *_guide, and saves it’s position in a .json file.
On build, the Guides task is loading every position of the .json file in the scene if guide exists.


Controllers



The Controllers task is used to save every controller shape form that ends with *_ctrl suffix in a .json file. It saves shape data as well as attributes such as lineWidth, color etc...
On build, the Controllers task is creating the saved shape with its geometry data, and replacing the shape by name, with the correct color width etc..


Skinning



The skinning task is used to save the Skinning data from the scene. It saves mesh data, ngSkinTools layers, and skinCluster weights.
On build, it applies all the data in vertex order to the meshes.

Deformers

The deformers task has the same usage as the skinning task, but instead of saving Skinning data, it saves all the deformers data based on a list given in the script.
The deformers task has 2 lineEdits, one used to save the attributes of the deformer, if the user changed the values, and the second one to save the weights. 
On build, it applies all the data in vertex order to all the saved meshes based on the lineEdit path.


BCS

The BCS task is a specific task used for workflows using the BCS plugin, all this  task  does is that it saves all the inputs and outputs connexions of the DPK_bcs node.
The  task  has 2 lineEdits, the first one is for the .json file where all the connexions are saved, and the second one is used to specify the exact name of the BCS node, so if the facial rig has few meshes that are using BCS, the user can drag and drop multiple BCS  tasks, and save all the data from the different BCS nodes.
On build, it just recreates the connexions from the inputs to the BCS nodes based on the given .json file in the lineEdit.
Note : It does not create a BCS node, the BCS node needs to be imported beforehand.

Script


The script task is maybe one of the most important tasks, the task has 2 lineEdits, the first one is there to give the path to a .py file, in order to run a specific definition from it. The second one is used to run the specific def.
On build, it runs the given def from the given python script.



Setup

This task is also very imporant, as the facial module is relying on “setup” groups, that are used to change different values on the rig (I will explain it later).
The task has only one lineEdit, that saves all the attributes and its values from all the groups that ends with *_SETUP in a .json file.
On build, it just bring back the saved values in the correct attributes.





The workflow



Before continuing, I just want to do a little aparté on the workflow, when rigging a character with the autorig.

  • Importing the facial geometry (just the head that has been detached from the body) Import task
  • Importing the facial module Import task
  • Creating the rig groups + the different head duplications for the BlendShapes workflow + parenting everything in the right place in script with the script task (we need to keep ourselves organized ! ) Script task
  • Placing the different guides (joints, controllers) 
  • Resizing the shapes of the controllers
  • Saving the data of guides position and controllers shapes Controllers task / Guides task
  • Bind skinning the correct meshes to the correct joints, and executing the skinning for the different head layers
  • Saving the skinning data Skinning task
  • Applying the different deformers from the facial module, and saving the weights Deformers task
  • Creating the shapes for the facial expressions
  • Exporting the data points and the BCS nodes
  • Importing the data points + BCS nodes Import task
  • Saving the bcs node inputs BCS task
  • Tweaking the SETUP groups, and saving the attributes SETUP task
  • Executing the cleanup script in order to publish the rig when its done Script task
  • Build the rig

That was the workflow used for the graduation movie, by experimeting it, I found some limitations and rooms for improvement ! In order to simplify everything and work faster.







The Facial Module




Now we can talk about the rig itself. For the movie, I decided to do all my modules by hand, in maya. It gave me more freedom, and I didn’t want to spend all my time in vsCode writing all my module by hand. So I decided to strenghten my skills in maya, rather than in scripting this time.
If I had to redo it, I’ll probably chose the script path, in order to save somewhere the steps used to build the module, or do a sort of hybrid way of working, where I will have the module written in script, and then the module scene saved.
The other objective I had, was to do the entire rig in matrices, because it gives more elegant and optimized rigs, and it widens my rigging knowledge. So no maya constraints, and the most important thing, no rivets.

As our movie has only humanoid characters, that share practically the same head shape, I decided to do one module, that every character will share. So the animators can easilly transfer their animations, and it gives a coherence from one character to another.

The facial rig workflow I am using is the one used at Stim Studio, and in most of the feature animation studios. Based on BlendShapes, where the animator create a neat expression with very few controllers, and if needed tweaks the expression with more specific controllers (usually driving joints). The goal as a rigger is to simplify the usage of the rig to the animator, otherwise, the animator will go in the details too early, or break the rig.

What I needed :

- Have all the controllers flattened (no groups above, no parenting)
- Have the BlendShape controllers normalized (all the values going from -1 to 1, in order to preserve coherence for the animators, and give them ease when copy/pasting keys for example)
- Make the controllers follow virtually, imitating somehow the rivetting workflow
- Have a setup that works with my autorig (guides, joints, etc...)
- Make it work with BCS


Here is what I came with, the module with a guides setup, where the user places the joints guides, and the controllers guides, according to the character’s geometry.


As you can see, the guides are mirrored, and they are moving the controllers/joints in real time with the controllers and joint values staying at 0
 


The maths behind the guides system is not that hard, because we do not need parenting, or specific direction on the controllers, in order to avoid double transformations when merging the facial rig to the body. So basically you take the .worldMatrix[0] of the guide, and plug it directly in the .offsetParentMatrix in the controller/joint.



Here is the setup for the guides mirroring




And here is the outliner, where as you can see the controllers are flattened, it makes the outliner cleaner, and the rig less heavy.





“Matrix rivetting”



As I said before, my goal was to not use rivets on the facial rig, in order to already have the module ready when arriving in the scene, and to reduce performance loss for animators so I could add more advanced setups.

The controllers follow-up relies on matrices, where we will have a controller that will drive the matrix transformations of some other controllers, depending the movement it will do.
I did a linkedIn post a few months ago, where I briefly explained a tool, in order to sort of automatize the matrix rivetting.

You can find the post here.

The good thing about this setup, is that it allows you to move whatever controller you want, on a given pivot position. So it could handle deformations similar to lattices with scale etc.. And it’s a very simple setup that you can do with only few nodes.

How it works :

For the example, this is what it looks like, for the corner controller, driven by the middle lattice controller.

This is the multMatrix setup, where you first calculate the offset from the position of the corner to the position of the pivot, and then multiply it by the matrix of the driver.



Then, the intensity of the transformations, is tweaked by the user on the SETUP groups so you can very precisely make the controllers follow along the deformation, and save the values in the UI, as I explained before.




It was the first time that I was doing this, so I was doing it mainly by hand. In the future I would like to implement it directly in the autorig with a custom UI, where the rigger can setup the specific controllers, the drivers, and save it, so it enters in the rebuild logic. I also need to add the possibility to cleanly remove the matrix follow-up nodes if something changes, because the setup here is a bit destructive. Finally, I need to find a new and simpler way to handle the SETUP groups, in order to have less groups, and keep it more organized.

To finish on the facial module, it’s something I can drastically improve in the future. I was lucky I had only humanoid character on the movie, but if you have for example, a rabbit, an eagle, and a bear, the modules will vary a lot, with for example more controllers, or literally different setups. It’s also great as a rigger, to have multiple separated modules, in order to apply the setup fast, and do some early retakes if needed.
The idea for the future would be having separated modules like I did for the body autorig. Where I could reuse them and custom them directly in the ui between characters, and still create different facial rigs at the end, while keeping the matrix follow up logic for the controllers.






During this project I learned so much, on the technical side, as well as the artistic side, the rig can not be good if the deformations are poor, so it’s really important to find a good balance between a really technical rig, and a well deformable rig useful for the animators. 
It also taught me to anticipate and planify everything at start, in order to save some time later. When working procedurally like that, you learn to anticipate every step of the process, and that’s a really cool exercise that you can transfer in every departement of the pipeline.
I also faced a lot of other challenges, and I already want to improve everything I learned.

I hope that you found something useful here, and wish you a good day !  ☀️