More Matrix Math for IK and Cross-Module Setups
Continuing with my goal to remove native Maya constraints from my rigs, in this post I will be covering rotate plane solver IK, and how I integrate a multi-module feature into my matrix multiplication chains. Although we technically have full body control with the FK setup, these features are the bare minimum to pull off animation as fundamental as walk cycles.
Solving the IK Triangle
Making a custom IK setup is a little more complex that altering the parent matrix multiplication as described in my last post. Maya’s IK solver is a black box for anyone adding an IK system, essentially removing any semblance of the trigonometry working under the hood.
Think of a leg as a triangle, with corners positioned at the hip, knee, and ankle. With the transform information at each of these three points, we can calculate the length of the upper leg, the lower leg, and the distance between the hip and ankle. In trigonometry, this is known as an SSS triangle, and it is enough information to find all of the corresponding angles with the law of cosines. This website has a straightforward and abstract breakdown:
https://www.mathsisfun.com/algebra/trig-solving-sss-triangles.html
When I started using Maya in 2019, trigonometry nodes like sin, cos, arctan were famously omitted. Creating these trigonometry nodes was my first project with C++ Maya node development, along with many other technical artists. As of Maya 2024 (the version I am using), these nodes are added to vanilla Maya.
Essentially, our goal is to drive the Z rotation (assuming X down the bone) of each IK joint based on the lengths of the leg sides. Because the length from hip to ankle is variable, this will change our angle outputs and create the IK style system.
Although this looks like node spaghetti, at a basic level this graph is taking a locator at each joint position of the leg, applying the law of cosines, and finding the correct angle to apply to the joint’s Z rotation to satisfy the triangle.
We can repeat this process for the knee, refactoring the law of cosines to solve the second angle. Because the ankle rotation does not factor into the upper leg position, we can simply connect our IK end control to its offset parent matrix.
Although we are able to have a no flip setup with the PV control as an attribute on the end control, animators that I have worked with will often prefer the visual flexibility of the separate control. To add this, we multiply in an aimMatrix to the hip joints OPM so that the joint’s Y axis is aimed in the direction of our pole vector control.
IK movement range test
Reverse Foot
This is the first of what I am referring to as a “multi-module” feature in my pipeline. While an RP IK setup can fully exist within the data of the leg, a reverse foot needs to know joint and control transforms of the leg AND the foot. In order to respect private data access between modules, only the essential matrices are passed through buffer input and output nodes. Here’s how I integrate something like reverse foot into my matrix multiplication chain:
For each influence I want on a control or module, the module receives an input driver transform matrix. In a reverse foot setup, the FK control is influenced by a combination of the leg driver chain, the IK end control, and in my case a global world control shown at the far left end. By appropriately multiplying, blending, and aiming each of these transforms, you can have a chain of influences on one node. I’m ordering the multiplication from large scope to small scope. That way the foot will still roll correctly with any ankle transformation, and the foot roll is still transformable in global world space.
Foot roll driven by IK end control attribute.
Creating buffer input groups makes ripping out modules or features much easier in my pipeline. If I need to find the root of an influence, I always know its coming from a node in my input or output groups in the outliner.
My next post will be a little different, focusing heavily on my process for designing a Python tool at the software level. The complexities of this module rig has allowed me to dive deep into proper Python module management and set myself up for future tools.