Lip Intersection + Lip Sticky Nodes

A problem I’ve wanted to tackle for a while, lip meet intersections. This is my first take on a possible solution.

A custom C++ deformer written to dynamically resolve intersections between the upper and lower lips by pushing and flattening the contact area.
This Lip Intersection deformer will first solve the intersection, and then do a post-push on the areas around the meet line for a softer roll into the meet line.
Width and strength of this post-pushing is all controllable independently from the intersection solve. (I’ve pumped it a bit for the demo)

In this demo I’ve also layered on a custom C++ Lip Sticky deformer. As lip sticky is another effect that benefits a lot visually from a clean lip meet line.

All deformers running the on GPU to make them somewhat puppet friendly.

Lip meet intersections can be a subtle problem, and an even more subtle result when fixed, but in my experience, I’ve found that the intersection between closed lips can contribute to unnatural looking lips at render time for close-up shots.
This is especially true when the lips transition from closed to parted and a clear intersection can be seen as the upper lip slides out of the lower.

Ideally, the compression between lips should not be baked into the neutral, as the full roundness of the lips need to be in place whenever the lips are parted.
This means that the only solution is to solve the intersections dynamically, either in CFX, or in this case, the rig.

This setup has its limits, and works when the lips are not overly intersected. Going far beyond the neutral intersection can cause things to look odd. But things are generally stable with 50/60% of the lips intersected.

Cornea Push Node

A custom C++ Maya deformer to handle cornea displacement along the lid line and surrounding mesh.
Running on the GPU to make it puppet friendly.

The deformer does both cornea displacement and automatic snapping of the eyelid to the input eyeball geometry.
The radius, strength and shape of the displacement can be adjusted via attributes and a shape ramp for a decent amount of control over the final look.
The eyelid snapping influence can be adjusted by weights.

I my experience, I’ve found that a setup like this allows artists to simplify their eye look shape workflow by allowing them to focus solely on the eye opening shape in general and the flesh movement around it. 
I find this helps a lot with iteration speed and eye shape network management.

For best results, the eyelids would be modelled without any cornea displacement baked in, allowing for it all to be done 100% dynamically by the deformer.
However, as that is often not possible in production (due to renders and presentations being done before any rig is in place), the deformer will store offsets against the current shape, allowing for that baked displacement to be removed during deformation.

Workflow Tools

A long running set of tools I’ve been building up over the years to aid my personal workflow in Facial Modelling and Modelling in general. Constantly evolving as I add and adjust tools.

The core of the this specific UI and tool set is to be a crude plugin system that allows me to quickly implement new tools, with built-in automatic UI (for when custom UIs are not required).

Recently rewritten to be cleaner, faster and ready for PySide 6/Python 3 etc.

The toolset also comes with a set of custom C++ nodes and deformers.

Weight Builder Node

A custom C++ node to build and populate a weights array based on the input mesh’s shape.
I found the need for something like this for a while, useful when plugged directly into deformer weights attributes.

Current modes:

  • Mesh Convexity
  • Mesh Concavity
  • Mesh Smoothness
  • Mesh Roughness
  • Mesh Tension
  • Mesh Compression
  • Axis X
  • Axis Y
  • Axis Z
  • Noise
    • More noise modes/features to be implemented
    • FastNoiseLite.h used for noise algorithms

Weight range clamping, multiplying and blurring built in.

Shape Splitter

I’ve been working on a Shape Splitting tool on/off over the years.
With a major re-write for a recent project.

That latest iteration has been re-worked to have the following core features:

  • Unlimited Split Directions
    • Allowing users to add as many custom splits as required for the character
    • A Split Direction defines how a shape is divided into two resulting shapes
    • Example:
      • Split Lips Upper and Lower Splits a shape into an Upper Lip and Lower Lip version
      • Split Left/Right Splits a shape down the middle of the face into Left and Right versions
    • Split Directions are controlled through JSON configuration files and per-vertex painted weight data
  • Unlimited Splits Per Shape
    • While most shapes typically require basic Left/Right or Lip Upper/Lower splits, or both, the tool supports any number of additional splits as required
    • Example, taking a full brow shape and producing not only a L/R brow raiser, but also an Inner and Outer browRaisesr that are in-turn split L/R
  • Middle line pulling
    • Automatically pulls shapes across the midline after splitting to reduce the “dead zone” often felt along the centre line.
  • Realtime Split Preview
    • Ability to preview the resulting split names before committing to the split process
  • Config Driven
    • Shapes List, Split Directions, Pull Directions all driven via JSON config files allowing for different configs per show
  • Shape Group
    • Basic group of the input shapes list with import/export
  • Split States
    • Ability to disable/enable shapes for splitting after selection for faster iterations

The core splitting logic is independent of the UI and can be easily implemented as a post-process for use on a farm or at rig build time.

Split times depend on mesh resolution, but the tool has been written to only work on the smallest amount of data required to reduce memory and speed up split times.

Adjusting Shapes in Pose Context

A custom C++ command I wrote to allow users to adjust a series of facial blendshapes from a “pose” context.

The tool allows users to set blendshape target values to achieve their desired pose, from there they are able to adjust the mesh as a whole to achieve the look they want. The tool with then extract and apply those changes to the shapes individually, applying the changes based on how much each shape individually contributes to the full pose.

I found this useful to do broad changes to a base set of facial shapes allowing my to improve likeness and appeal quickly.