# June 2017

## Maya matrix nodes – Part 1: Node based matrix constraint

This post is a part of a three post series, where I will try to implement popular rigging functionalities by only using maya’s native matrix nodes.

Following the Cult of rig lately, I realized I have been very wasteful in my rigs in terms of constraints. I have always known that they are slower than direct connections and parenting, but then I thought that is the only way to do broken hierarchy rigs. Even though I did matrix math at university, I never used it in maya as I weirdly thought the matrix nodes are broken or limited. There was always the option of writing my own nodes, but since I would like to make it as easy for people to use my rigs, I would rather keep everything in vanilla maya.

Therefore, when Raffaele used the `matrixMult` and `decomposeMatrix` nodes to reparent a transform, I was very pleasantly inspired. Since then, I have tried applying the concept to a couple of other rigging functionalities, such as the twist calculation and rivets and it has been giving me steadily good results. So, in this post we will have a look at how we can use the technique he showed in the stream, to simulate a parent + scale constraint, without the performance overhead of constraints, effectively creating a node based matrix constraint.

### Limitations

There are some limitations with using this approach, though. Some of them are not complex to go around, but the issue is that this adds extra nodes to the graph, which in turn leads to performance overhead and clutter. That being said, constraints add up to the outliner clutter, so I suppose it might be a matter of a preference.

#### Joints

Constraining a joint with `jointOrient` values, will not work, as the `jointOrient` matrix is applied before the rotation. There is a way to get around this, but it involves creating a number of other nodes, which add some overhead and for me are making it unreasonable to use the setup instead of an orient constraint.

If you want to see how we go around the `jointOrient` issue just out of curiosity, have a look at the joint orient section.

#### Weights and multiple targets

Weights and multiple targets are also not entirely suitable for this approach. Again, it is definitely not impossible, since we can always blend the output values of the matrix decomposition, but that will also involve an additional `blendColors` node for each of the transform attributes we need – `translate`, `rotate` and `scale`. And similarly to the previous one, that means extra overhead and more node graph clutter. If there was an easy way to blend matrices with maya’s native nodes, that would be great.

#### Rotate order

Weirdly, even though the decompose matrix has a `rotateOrder` attribute, it does not seem to do anything, so this method will work with only the `xyz` rotate order. Last week I received an email from the maya_he3d mailing list, about that issue and it seems like it has been flagged to Autodesk for fixing, which is great.

### Construction

The construction of such a node based matrix constraint is fairly simple both in terms of nodes and the math. We will be constructing the graph as shown in the Cult of Rig stream, so feel free to have a look at it for a more visual approach. The only addition I will make to it is supporting a maintainOffset functionality. Also, Raffaele talks a lot about math in his other videos as well, so have a look at them, too.

All the math is happening inside the `matrixMult` node. Essentially, we are taking the `worldMatrix` of a target object and we are converting it to relative space by multiplying by the `parentInverseMatrix` of the constrained object. The `decomposeMatrix` after that is there to break the matrix into attributes which we could actually connect to a transform – `translate`, `rotate`, `scale` and `shear`. It would be great if we could directly connect to an input matrix attribute, but that would probably create it’s own set of problems.

That’s the basic node based matrix constraint. How about maintaining the offset, though?

### Maintain offset

In order to be able to maintain the offset, we need to just calculate it first and then put it in the `multMatrix` node before the other two matrices.

#### Calculating offset

The way we calculate the local matrix offset is by multiplying the `worldMatrix` of the object by the `worldInverseMatrix` of the parent (object relative to). The result is the local matrix offset.

##### Using the multMatrix node

It is entirely possible to do this using another `matrixMult` node, and then doing a `getAttr` of the output and set it in the main `matrixMult` by doing a `setAttr` with the `type` flag set to `"matrix"`. The local `matrixMult` is then free to be deleted. The reason we get and set the attribute, instead of connecting it, is that otherwise we create a cycle.

##### Using the Maya API

What I prefer doing, though, is getting the local offset via the API, as it does not involve creating nodes and then deleting them, which is much nicer when you need to code it. Let’s have a look.

``````import maya.OpenMaya as om

def getDagPath(node=None):
sel = om.MSelectionList()
d = om.MDagPath()
sel.getDagPath(0, d)
return d

def getLocalOffset(parent, child):
parentWorldMatrix = getDagPath(parent).inclusiveMatrix()
childWorldMatrix = getDagPath(child).inclusiveMatrix()

return childWorldMatrix * parentWorldMatrix.inverse()
``````

The `getDagPath` function is just there to give us a reference to an `MDagPath` instance of the passed object. Then, inside the `getLocalOffset` we get the `inclusiveMatrix` of the object, which is the full world matrix equivalent to the `worldMatrix` attribute. And in the end we return the local offset as an `MMatrix` instance.

Then, all we need to do is to set the `multMatrix.matrixIn[0]` attribute to our local offset matrix. The way we do that is by using the `MMatrix`‘s `()` operator which returns the element of the matrix specified by the row and column index. So, we can write it like this.

``````localOffset = getLocalOffset(parent, child)
mc.setAttr("multMatrix1.matrixIn[0]", [localOffset(i, j) for i in range(4) for j in range(4)], type="matrix")
``````

Essentially, we are calculating the difference between the `parent` and `child` objects and we are applying it before the other two matrices in the `multMatrix` node in order to implement the `maintainOffset` functionality in our own node based matrix constraint.

### Joint orient

Lastly, let us have a look at how we can go around the joint orientation issue I mentioned in the Limitations section.

What we need to do is account for the `jointOrient` attribute on joints. The difficulty comes from the fact that the `jointOrient` is a separate matrix that is applied after the `rotation` matrix. That means, that all we need to do is, in the end of our matrix chain rotate by the inverse of the `jointOrient`. I tried doing it a couple of times via matrices, but I could not get it to work. Then I resolved to write a node and test how I would do it from within. It is really simple, to do it via the API as all we need to do is use the `rotateBy` function of the `MTransformationMatrix` class, with the inverse of the `jointOrient` attribute taken as a `MQuaternion`.

Then, I thought that this should not be too hard to implement in vanilla maya too, since there are the quaternion nodes as well. And yeah there is, but honestly, I do not think that graph looks nice at all. Have a look.

As you can see, what we do is, we create a quaternion from the joint orientation, then we invert it and apply it to the calculated output matrix of the `multMatrix`. The way we apply it is by doing a quaternion product. All we do after that is just convert it to euler and connect it to the rotation of the joint. Bear in mind, the `quatToEuler` node supports rotate orders, so it is quite useful.

Of course, you can still use the `maintainOffset` functionality with this method. As I said though, comparing this to just an orient constraint it seems like the orient constraint was performing faster every time, so I see no reason of doing this other than keeping the outliner cleaner.

Additionally, I am assuming that there is probably an easier way of doing this, but I could not find it. If you have something in mind, give me a shout.

### Conclusion

Using this node based constrain I was able to remove parent, point and orient constraints from my body rig, making it perform much faster than before, and also the outliner is much nicer to look at. Stay tuned for parts 2 and 3 from this matrix series, where I will look at creating a twist calculator and a rivet by using just matrix nodes.

## Maya performance test – Follicle vs Classic rivet

The classical rivet was a really popular rigging thing a few years ago (and long before that it seems). I am by no means a seasoned rigger, but whenever I would look for facial rigging techniques the rivet would keep coming up. What is more, barely if ever people suggested using `follicle` to achieve the result, generally because the classical rivet evaluates faster. So, I thought I’d do a maya performance test to compare them.

#### Prerequisites

I will be looking into the performance of a `follicle` and a classical rivet, both on a NURBS sphere and on a poly sphere. NURBS because I tend to use a lot of ribbons and poly, because it’s a popular feature for attaching objects to meshes.

I will be using Maya 2017’s Evaluation Toolkit to run the performance test, as it gives nice output for each evaluation method, even though I cannot imagine using anything but parallel.

The way the tests are going to work is, I will create two files, each containing the same geometry with 10 rivets. In one file I will use follicles and in the other the classical setup. The deformation on the geometry will just be keyed vertices and it will be identical for each setup, so we can be sure that the only difference between the two files is the riveting setup.

Then, the test will be done in a new scene where I will reference the file to test a 100 times. For each setup I will run the evaluation manager’s performance test and take the results and compare them.

Okay, let us have a look then.

#### NURBS

##### Classical rivet setup

So, the way this one works is I just loop from 1 to 10 and I create a `pointOnSurfaceInfo` node with `parameterU` set to `iterator * .1` and `parameterV` set to .5. Then, I plug the output position directly to a locator’s `translate` attr. Additionally, the output position, normal vector and a tangent vector go into an `aimConstraint` which constraints the rotation of the locator.

##### Follicle setup

This one is fairly straightforward, I just created 10 follicles, with `parameterU` set to `iterator * .1` and `V` to .5.

##### Results

Bear in mind, `EMS` refers to serial evaluation and `EMP` is parallel.

``````NURBS surface
Classical Rivet
Playback Speeds
===============
DG  = 13.1694 fps
EMS = 11.1359 fps
EMP = 20.7469 fps
-----------------------------
Follicle
Playback Speeds
===============
DG  = 11.3208 fps
EMS = 12.6263 fps
EMP = 27.8293 fps
``````

Even though I expected the follicle to be faster I was surprised by how much. It is important to note that we have `10 * 100 = 1000` rivets in the scene, which is obviously a big number. Therefore, in a more realistic example the difference is going to be more negligible, but still `7.8fps` is quite a bit.

What is also quite interesting is that in `DG` the follicle is slower than the classic rivet. So, the stigma of the old days that the classical rivet is faster, seem to be deserved, but parallel changes everything.

#### Polygons

##### Classical rivet setup

So, when it comes to polys the classical rivet gets a bit more complicated, which I would imagine results in a larger slowdown as well. The way this setup works is, we grab 10 couples of edges, which in turn produce 10 surfaces through a `loft` node. Maintaining history, the nurbs surfaces will follow the poly geometry. So, we can perform the same rivet setup as before on the nurbs.

###### Follicle setup

On a mesh with proper UVs the follicles are again trivial to set up. We just loop 10 times and create a follicle with the appropriate `U` and `V` parameters.

##### Results
``````Polygon geometry
Follicle
Playback Speeds
===============
DG  = 1.7313 fps
EMS = 3.32005 fps
EMP = 9.79112 fps
-------------------------
Classical rivet
Playback Speeds
===============
DG  = 1.05775 fps
EMS = 1.52022 fps
EMP = 3.31053 fps
``````

As expected, follicles are again quite a bit faster. I am saying as expected, as not only do we have a riveting setup as in the NURBS case, but also there is the edges and the `loft` which add to the slowdown. I am assuming, that is why even in DG the classical rivet is still slower.

#### Conclusion

So, the conclusion is pretty clear – `follicle` rivets are much faster than classical rivets in the latest maya versions which include the parallel evaluation method.

## Custom marking menus in Maya editors

So, it seems like I have been going crazy with marking menus lately. I am really trying to get the most of them, and that would not be much if we could only use them in the viewports, so today we are going to look at how we can construct custom marking menus in maya editors.

tl;dr: We can query the current panel popup menu parent in maya with the `findPanelPopupParent` MEL function, and we can use it as a parent to our `popupMenu`.

So, there are a couple of scenarios that we need to have a look at, as they should be approached differently. Although, not completely necessary I would suggest you have a look at my previous marking menu posts – Custom marking menu with Python and Custom hotkey marking menu – as I will try to not repeat myself.

Okay, let us crack on. Here are the two different situations for custom marking menus in maya editors we are going to look at.

### Modifiers + click trigger

In the viewport these are definitely the easier ones to set up as all we need to do is just create a `popupMenu` with the specified modifiers – `sh`, `ctl` and `alt`, the chosen button and viewPanes as the `parent`. When it comes to the different editors, though, it gets a bit trickier.

Let us take the node editor as an example.

If we are to create a marking menu in the node editor, it is a fairly simple process. We do exactly the same as before, but we pass `"nodeEditorPanel1"` as the `parent` argument. If you have a node editor opened when you run the `popupMenu` command, you will be able to use your marking menu in there. The catch is though, that once you close the node editor the marking menu is deleted, so it is not available the next time you open the node editor.

Unfortunately, I do not have a great solution to this problem. In fact, it is a terrible solution, but I wanted to get it out there, so someone can see it, be appalled and correct me.

The second method – Custom hotkey trigger – is much nicer to work with. So, you might want to skip to that one.

What I do is, I create a hotkey for a command that invokes the specific editor (I only have marking menus in the node editor and the viewport) and runs the marking menu code after that. So, for example, here is my node editor hotkey (Alt+Q) `runTimeCommand`.

``````mc.NodeEditorWindow()

else:

``````

That means that everytime I open the node editor with my hotkey I also create the marking menu in there, ready for me to use. As, I said, it is not a solution, but more of a workaround at this point. In my case, though, I never open the node editor through anything else than a hotkey, so it kind of works for me.

Then the `vsRigging.markingMenus.vsNodeMarkingMenu` file is as simple as listing the `menuItem`s.

``````import maya.cmds as mc

mc.menuItem(l="multiplyDivide", c="mc.createNode('multiplyDivide')", rp="N", i="multiplyDivide.svg")
mc.menuItem(l="multDoubleLinear", c="mc.createNode('multDoubleLinear')", rp="NE", i="multDoubleLinear.svg")
mc.menuItem(l="plusMinusAverage", c="mc.createNode('plusMinusAverage')", rp="S", i="plusMinusAverage.svg")
mc.menuItem(l="condition", c="mc.createNode('condition')", rp="W", i="condition.svg")
mc.menuItem(l="blendColors", c="mc.createNode('blendColors')", rp="NW", i="blendColors.svg")
mc.menuItem(l="remapValue", c="mc.createNode('remapValue')", rp="SW", i="remapValue.svg")
...
``````

A proper way of doing this would be to have a callback, so everytime the node editor gets built we can run our code. I have not found a way to do that though, other than ofcourse breaking apart maya’s internal code and overwriting it, which I wouldn’t go for.

Luckily, creating a custom marking menu bound to a custom hotkey actually works properly and is fairly easy. In fact, it is very similar to the Custom hotkey marking menu post. Let us have a look.

### Custom hotkey trigger

Now, when we are working with custom hotkeys we actually run the initialization of the `popupMenu` everytime we press the hotkey. This means we have the ability to run code before we create the marking menu. Therefore, we can query the current panel and build our `popupMenu` according to it. Here is an example `runTimeCommand`, which is bound to a hotkey.

``````import maya.mel as mel

mc.deleteUI(name)

parent = mel.eval("findPanelPopupParent")

if "nodeEditor" in parent:
popup = mc.popupMenu(name, b=1, sh=1, alt=0, ctl=0, aob=1, p=parent, mm=1)

else:
popup = mc.popupMenu(name, b=1, sh=1, alt=0, ctl=0, aob=1, p=parent, mm=1)

``````

So, what we do here is, we start by cleaning up any existing versions of the marking menu. Then, we use the very handy `findPanelPopupParent` MEL function to give us the parent to which we should bind our `popupMenu`s. Having that we check if the editor we want exists in the name of the parent. I could also compare it directly to a string, but the actual panel has a number at the end and I prefer just checking the base name. Then, depending on which panel I am working in at the moment, I build the appropriate custom marking menu.

Don’t forget that you need to create a release command as well, to delete the marking menu so it does not get in the way if you are not pressing the hotkey. It is a really simple command, that I went over in my previous marking menu post.

The obvious limitation here is that we have a hotkey defined and we cant just do ctrl+alt+MMB for example.

### Conclusion

So, yeah, these tend to be a bit trickier than just creating ones in the viewport, but also I think there is more to be desired from some of maya’s editors *cough* node editor *cough*, and custom marking menus help a lot.

## Custom hotkey marking menu in Maya

So, recently I stumbled upon a djx blog blost about custom hotkeys and marking menus in different editors in maya. I had been thinking about having a custom hotkey marking menu, but was never really sure how to approach this, so after reading that post I thought I’d give it a go and share my process.

tl;dr: We can create a runtime command which builds our marking menu and have a hotkey to call that command. Thus, giving us the option to invoke custom marking menus with our own custom hotkeys, such as Shift+W or T for example, and a mouse click.

Disclaimer: I have been having a super annoying issue with this setup, where the “release” command does not always get called, so the marking menu is not always deleted. What this means is that if you are using a modifier like Shift, Control or Alt sometimes your marking menu will still be bound to it after it has been closed. Therefore, if you are using something like Shift+H+LMB, just pressing Shift+LMB will open it up, so you lose the usual add to selection functionality. Sure, to fix it you just have to press and release your hotkey again, but it definitely gets on your nerve after a while.

If anyone has a solution, please let me know.

I have written about building custom marking menus in Maya previously, so feel free to have a look as I will try to not repeat myself here. There I also talked about why I prefer to script my marking menus, instead of using the Marking menu editor, and that’s valid here as well.

So, let us have a look then.

### RunTimeCommands

The first thing we need to do is define a runTimeCommand, so we can run it with a hotkey. That is what happens if you do it through the Marking menu editor and set Use marking menu in to Hotkey Editor, as well.

There a couple of ways we can do that.

#### Hotkey Editor

On the right hand side of the hotkey editor there is a tab called Runtime Command Editor. If you go on that one you can create and edit runTime commands.

#### Scripting it in Python

If you have multiple marking menus that you want to crate, the hotkey editor might seem as a bit of a slow solution. Additionally, if changes need to be made I always find it more intuitive to look at code in my favourite text editor (which is sublime by the way).

To create a runTime command we run the `runTimeCommand` function which for some reason does not appear in the Python docs, but I’ have been using `maya.cmds.runTimeCommand` successfully.

All we need to provide is a `name` for the command, some annotation – `ann`, a string with some code – `c` and a language – `cl`.

Here is an example

``````mc.runTimeCommand("exampleRunTimeCommand", ann="Example runTime command", c=commandString, cl="python")
``````

Something we need to keep in mind when working with runTime commands is that we cannot pass external functions to them. We can import modules and use them once inside, but I cannot pass a reference to an actual function to the `c` flag, as I would do to `menuItem`s for example. That means that we need to pass our code as a string.

### Press and release

Now, that we know how to create the `runTimeCommand`s let us see what we need these commands for.

As I mentioned, they are needed so we can access them by a hotkey. What that hotkey should do is initialize our marking menu, but once we release the key it should get rid of it, so it does not interfere with other functions. Therefore we need two of them – Press and Release.

Let us say we are building a custom hotkey marking menu for weight painting. In that case we will have something similar to the following.

• `mmWeightPainting_Press` runTimeCommand – to initialize our marking menu
• `mmWeightPainting_Release` runTimeCommand – to delete our marking menu

The way we bind the release command to the release of a hotkey is by pressing the small arrow to the side of the hotkey field.

### The Press command

``````import maya.cmds as mc # Optional if it is already imported

name = "mmWeightPainting"
mc.deleteUI(name)

popup = mc.popupMenu(name, b=1, sh=1, alt=0, ctl=0, aob=1, p="viewPanes", mm=1)

import mmWeightPainting
``````

So, essentially what we do is every time we press our hotkey, we delete our old marking menu and rebuild it. We do this, because we want to make sure that our latest changes are applied.

Now, the lower part of the command is where it gets cool, I think. We can store our whole marking menu build – all `menuItems` – inside a file somewhere in our `MAYA_SCRIPT_PATH` and then just import it from the `runTimeCommand` as in this piece of code. What this gives us, is again, the ability to really easily update stuff (not that it is a big deal with marking menus once you set them up). Additionally, I quite like the modularity, as it means we can have very simple `runTimeCommand`s not cluttered with the actual marking menu build. This is the way that creating through the Marking menu editor works as well, but obviously it loads a `MEL` file instead.

So, literally that `mmWeightPainting` file is as simple as creating all our marking menu items.

``````import maya.cmds as mc

...
``````

And that takes care of building our marking menu when we press our hotkey + the specified modifiers and mouse button. What, we do not yet have is deleting it on release, so it does not interfere with the other functionality tied to modifier + click combo. That is where the `mmWeightPainting_Release` `runTimeCommand` comes in.

### The Release command

``````## mmWeightPainting_Release runTimeCommand
name = "mmWeightPainting"

mc.deleteUI(name)
``````

Yep, it is a really simple one. We just delete the marking menu, so it does not interfere with anything else. Essentially, the idea is we have it available only while the hotkey is pressed.

### Hotkey

All that is left to be done is to assign a hotkey to the commands. There are a couple of things to have in mind.

If you are using modifiers for the `popupMenu` command – `sh`, `ctl` or `alt` – then the same modifiers need to be present in your hotkey as otherwise, even though the `runTimeCommand` will run successfully, the `popupMenu` will not be triggered.

In the above example

``````mc.popupMenu(name, b=1, sh=1, alt=0, ctl=0, aob=1, p="viewPanes", mm=1)
``````

we have specified the `sh` modifier. Therefore, the Shift key needs to be present in our hotkey.

Also, obviously be careful which hotkeys you overwrite, so you do not end up causing yourself more harm than good.

### Conclusion

That’s it, it really is quite simple, but it helps a lot once you get used to your menus. Honestly, trying to do stuff without them feels so tedious afterwards.