During the week, I got a comment on the first post in my Maya matrix nodes series – the matrix constraint one – about using the
wtAddMatrix node to achieve the multiple targets with blending weights functionality similar to constraints. I have stumbled upon the
wtAddMatrix node, but I think it is the fact that Autodesk have made it very fiddly to work with it – we need to show all attributes in the node editor and we have 0 access to setting the weight plug – that put me off ever using it. That being said, when RigVader commented on that post I decided I will give it a go. Since it actually works quite nicely, today I am looking at blending matrices in Maya.
Disclaimer: I will be using the matrix constraint setup outlined in the post I mentioned, so it might be worth having a look at that one if you have missed it.
Another disclaimer: In the comments, Harry Houghton flagged up the fact that the resulting orientation of the setup, when using weights other than half and half, is not comparable to the
parentConstraint result, as the
wtAddMatrix node does not have a way of controlling the interpolation type.
That being said, you might find that difference beneficial in certain cases, as the resulting rotation doesn’t flip when going beyond 180.
tl;dr: Using the
wtAddMatrix we can blend between matrices before we plug the output into a matrix constraint setup to achieve having multiple targets with different weights.
Turns out, the
wtAddMatrix is a really handy node. It gives us the chance to plug a number of matrices in the
.matrixIn plugs of the
.wtMatrix array attribute, and give them weight in the
.weightIn plug. That, effectively lets us blend between them.
Blending matrices for a matrix constraint setup
So, now that we know we can blend matrices, we just need to figure out exactly what do we need to blend.
Let us first have a look at the simpler case – not maintaining the offset.
group1 on the graph is the parent of
pCube1 and is used just so we convert the world matrix into a relative to the parent matrix, without using the
parentInverseMatrix. The reason for that is we do not want to create benign cycles, which Raff sometimes talks about on the Cult of Rig streams. Other than that, everything seems to be pretty straightforward.
Bear in mind, the
wtAddMatrix node does not normalize the weights, which means that we could have all of the targets fully influence our object. What is more, you could also push them beyond 1 or negate them, which would result in seemingly odd results, but that might just be what you need in some cases.
Maintaining the offset
Often we need to maintain the offset in order to achieve the desired behaviour, so the way we do that is we resort to the
multMatrix node once more. I am not going in detail, as there are already a couple of ways you can do that outlined in the previous post, but let us see how it fits in our graph.
The two additional
multMatrix nodes let us multiply the local offset for the current target by the world matrix of the current target, effectively constraining the object but also maintaining the initial offset.
Now, however clean and simple it may be, the graph gets to be a bit long. What this means is, it is probably getting a bit slower to evaluate as well. That is why, I thought I would do a bit of a performance test to see if there still is any benefit to using this setup over a
The way I usually do my tests is either loop a few hundred times in the scene and build the setup or build it once, save it in a file and then import the file a few hundred times and let it run with some dummy animation. Then I use Maya 2017’s Evaluation toolkit to Run a performance test, which gives us info about the performance in the different evaluation methods – DG, Serial and Parallel. Since, the results vary quite a bit, what I usually do is, run it three times and take the best ones.
In this case, I built the two setups in separate files, both with 2 target objects and maintain offset. Then I ran the tests on 200 hundred imported setups.
So here are the results.
Playback Speeds =============== DG = 89.8204 fps EMS = 20.1613 fps EMP = 59.2885 fps
Playback Speeds =============== DG = 91.4634 fps EMS = 24.6305 fps EMP = 67.2646 fps
Bear in mind these tests are done on my 5 years old laptop, so the results you are going to get if you are to repeat this test are going to be significantly better.
As you can see even with the extended graph we are still getting about 7.5 fps increase by using the matrix constraint setup with blending matrices. Considering, we have 200 hundred instances in the scene (which is by no means a large number), that means we have about .0375 fps increase per setup, which in turn means that on every 26 setups we win a frame.
So, there we have it, an even larger part of the
parentConstraint functionality, can be implemented by just using matrix nodes. What this means is we can keep our outliner cleaner and get a better performance out of our rigs at the same time, which is a total win win.
Thanks to RigVader for pointing the
wtAddMatrix node as a potential solution, it really works quite nicely!