January 31st, 2014

Yes, I have in fact been doing work this past year! Lots of it, actually. A 45 hour standard work week doesn’t leave much time for anything else. Which is why this blog and Guppy Tools have sadly been neglected. Don’t get me wrong, Guppy Tools isn’t broken. I just haven’t been able to give it the love it needs to reflect my current skill level. I hope to change that soon though.

What’s my current skill level you ask? Well, it just so happens that I recently asked my supervisor at Luma Pictures if I could show off a little of what I’ve been doing. And luckily for both of us, I got the go ahead! May I proudly present: Close Contact, a C++ deformer I made solve to approximate collisions a few months ago.

Okay, I lied a little. This isn’t quite an accurate picture of what I do with most of my time at work. I spend the large majority of my time writing python code heavily tied to Luma’s existing architecture. It’s not something I could show off.

Close Contact has the benefit of being a very visual tool with little tied to Luma’s existing architecture. It’s something I can wow the audience with a bit. And I had an amazing time writing it. I was telling friends for weeks that I finally had an excuse to use the quadratic formula at work. Yes. You heard me right. I got paid to use the quadratic formula. While I was learning the quadratic formula in high school I was dead certain I would never use it in any practical setting. Boy was I wrong.

Posted January 29th, 2014Updated January 31st, 2014 at 12:22 am

You know how embarrassing and awkward it is getting back in touch with someone you haven’t talked to in a really long time? It usually goes something like this:

So. Umm, hi.
It’s me.
Remember me?
We used to hang out. And then we stopped talking a few years back.
I don’t remember why.
You know that one time when you were like “Oh, man, I totally owe you for that.”
Well, I have this favor that I need to ask…

And then you get a reply which goes something like:

We stopped talking because you ran over my cat.
Please don’t contact me again.

Yeah. We’re having one of those talks. It’s a bit awkward isn’t it?

It’s been more than a year since my last post. Lots has happened since then. Shortly after my last post I landed a job at Luma Pictures as a Junior Pipeline TD. I’ve since become a full-fledged Pipeline TD and I’ve had loads of fun doing it.

Check this out. Last year Luma Pictures did the Harlem shake:

I’m all the way in the back wearing a squirrel mask, so you can’t see me. It was amazing to see everyone go crazy on top of their desks. A bit later we had an awesome Halloween party (http://lumapictures NULL.com/culture/album/10151753513997183) (apparently anybody who’s anybody was there). Here’s me in another mask!

Luma's Halloween Party!

(I’m the one cool one.)

Oh yeah, I also got some work done in between all this fun. But I’ll leave that for another post. Suffice it to say that I’ve had a blast this past year coding in Python, squashing bugs, kicking ass and working on films like Iron Man 3, Thor: The Dark World, and Captain America: The Winter Soldier.

September 18th, 2012

I’ve finally updated my demo reel! It has my new smooth stretch algorithm front and center. If you didn’t quite understand some of the concepts of my previous posts, you should definitely look at the video. I think it makes the concept if not the math a lot easier to understand.

I also wanted to share this short method I made for accessing OpenMaya array attributes. It’s very quick and simple. I’d rather encapsulate things like this into smaller functions since the API has so many non-standard elements. Remembering them all can be a hassle.

If it isn’t immediately clear how you would use this, for a matrix array attribute that was created in the initialize method like this:

I would call my sparse method in the compute method like so:

I just wrote this a few hours ago, and I can’t tell you how happy it made me. Now I don’t need to think nearly as hard when accessing sparse array attributes from the datablock. Of course, this still doesn’t help for all the other ways you might need to access array attributes. Getting the output value, or using the physical index, or getting it from a plug, or getting it from the other type of array attributes. Good God, this stuff needs to be simplified! In any case, good luck and god speed if you’re trying to use the Maya API to do anything.

September 13th, 2012

Excellent. Smooth stretch was solved. Another day, another math problem solved. I felt like a crime fighter who just beat this giant math monster back. Or was the math monster really solved? Wait, wait wait. Hold on a minute here! The whole reason of redoing this thing was that smooth stretch 2.0 didn’t work well in an IK/FK switch! If this new formula can’t help me solve that, then it’s no better than the old one. Oh crap!

So I continued to stare at my math chalkboard.

Okay. I needed to lay out the basics. Going from IK to FK would be simple. Just grab the current scale of the joints, and apply that to my FK chain. Going from FK to IK is all that I needed to concentrate on. So, what did I need to solve for? The IK Scale variable is what I put into the smooth stretch equation to find my final scale. So presumably all I needed to do was put in the final scale I had from the FK chain and get out the IK Scale.

Wait. That won’t work. The IK Scale is the current scale of the IK chain. It’s based on the distance to the IK handle, and that’s not going to change in either FK or IK. I needed another variable.

Luckily, I knew what I wanted that variable to be. The length variable. The variable that the animators would use to change the total length of the arm. After a little trial and error I came up with this equation to add length to the smooth stretch equation:
\textup{Final\_Scale} = \textup{smooth\_stretch}\left(\frac{\textup{IK\_Scale}}{\textup{Length}}\right)\textup{Length}

This is where I started to really hit the limits of my math knowledge. Length is being multiplied inside the smooth stretch function as well as outside. Even if I did know the inverse of my smooth stretch function, how would I use that to solve for length?

Well, there was nothing else to do but just try and see if something worked. I busted out wolphram alpha. Then I learned how to use wolphram alpha to solve the inverse of an equation. I solved for the inverse of the regular smooth stretch curve (https://www NULL.desmos NULL.com/calculator/8oz8mkbb0d). I still didn’t know how to use it. I tried solving for the inverse of the entire smooth stretch function (https://www NULL.desmos NULL.com/calculator/w2wws1fypu) including the pythagorean theorem. I still didn’t know how to use it.

I went back to staring at my math chalkboard.

I like to think that staring at my math chalkboard makes it sound like I’m some sort of math genius. Unfortunately I’m not. And staring at my math chalkboard usually means putting my head into my hands and letting the feeling of despair sink in. Then it’s a matter of waiting to see which will win. Inspiration or despair.

I tried adding the IK Scale variable to my original smooth stretch curve and graphing it (https://www NULL.desmos NULL.com/calculator/yyptflsx1h). Maybe seeing what was going on visually would help. That was much better. I immediately saw that the length variable just projected my unit curve out from the origin. It merely scaled the smooth stretch curve.

Inspiration struck. The smooth stretch curve could pass through any point in the first quadrant of the graph by changing the length variable. I wanted the smooth stretch curve to pass through the point that was the representation of the “elbow” in our IK chain. A vector starting at the origin with an infinite length pointing at the elbow on the graph will always pass through the unit smooth stretch curve. Therefore the length variable is literally the ratio of the distance to the elbow along that vector divided by the distance to the unit circle along that vector. All I needed to do was solve those two lengths.

Skipping past some wolphram alpha wizardry and a bit of trial and error I ended up with the following graph (https://www NULL.desmos NULL.com/calculator/fdk9yux17c) which solves smooth stretch for the length variable given the IK Scale variable and an arbitrary point in the first quadrant (a,b). Keep in mind that the graph only works in the falloff section of the smooth stretch equation due to the limitations of the graphing software. However, solving for any point which is not in the falloff section is much easier since the distance to the unit circle will always be 1, so the length variable will just be the distance to the elbow point.

Into the python code!

And that’s a wrap. The math monster was defeated for real.

Posted September 12th, 2012Updated September 14th, 2012 at 1:18 pm

As I was trying to say in my last post, two weeks ago I began my mathematical journey into smooth stretch. This time around I knew what I wanted to accomplish. I wanted a way to represent smooth stretch using just math. My Maya API chops had increased since my last attempt, so I could now wrap this math into a nice python/c++ node.

Now I hear what you’re saying, “But Jordan, that XSI blog you pointed to already has the math in it!” Yes, I know. That blog post shows the math for one way to solve smooth stretch. I just didn’t like that way. Using that equation the IK chain never actually becomes straight because there’s an asymptote at y = 0. When I made my first attempt at smooth stretch I tried using that equation in an expression. In the rigs I tested it on, I remember it was painfully obvious that the arms were never straight. My last iteration of smooth stretch didn’t have this problem, and I didn’t want to solve one part of the problem just to introduce another.

So, with my stubbornness in tow and a goal in mind I went back to the math drawing board.

First things first. I needed a way to model what a normal stretchy IK system was doing with just math. In a normal stretchy IK system, you are usually solving the scale of the shoulder and elbow joint as a function of the distance to the IK Handle. This is calculated by the current distance to the IK handle divided by the total distance the IK handle can go. Lets call this number the IK Scale.

\textup{IK Scale} = \frac{\textup{Current Distance}}{\textup{Total Distance}}

When the IK Scale is 1, the chain is fully extended. When the IK Scale is at 0, the chain is completely bent. IK scale is therefore the variable used to solve a normal stretchy IK system. So whatever graph I came up with would have to be a function of this variable. That is to say, IK scale would be the variable x in my equation f(x).

Scrutinizing a normal IK system, I noticed the obvious. In an IK system consisting of a shoulder, elbow and a wrist, the elbow will always rotate around the shoulder. The elbow draws a circle around the shoulder in the plane defined by the pole-vector. It’s a 2D circle. A quarter-circle to be precise. And if you make this circle a function of our IK scale, then you would have a visual representation of an IK system. A quick google search later for how to graph a quarter circle and I had this graph representing an Ik system (https://www NULL.desmos NULL.com/calculator/lp2lsb90jh).

This was when I had a really great epiphany (even if it’s pretty darn obvious). The scale of the shoulder joint in this graph was literally the distance from the origin to the point on the circle. So to find the scale of the shoulder (and therefore the scale of any other joint in the IK system), all I needed was the Pythagorean theorem! What’s even more cool, is that this wasn’t just true about the circle function I just drew, it was true for any function. All I needed to make was the graph of an equation of the path I wanted my elbow to take while stretching, and that’s what my IK chain would do. So to write it all out:

\textup{Final Joint Scale} = \sqrt{\textup{any\ equation}(\textup{IK\ Scale})^2 + \textup{IK\ Scale}^2}

Wow. So I can use any function I want to describe the motion of the elbow joint. I just need an equation that smoothly eases from y = 1 to y = 0. Well, hey! I know a function that does that. I could just use the gaussian function. At this point I did a little jig, hooked up a guassian function and looked at the graph (https://www NULL.desmos NULL.com/calculator/y2dfrnmtk1). Well. The elbow did follow the gaussian function. There was only a wee little problem with this. The IK chain was shrinking for most of the graph.

So, while I can plug any function I want into this equation to find the scale, the function has to always stay above the unit circle on the y-axis or the IK chain will start to shrink.

Now I started thinking about how I could keep things about that y limit. I tried adding an equation to the x part of the unit circle function. That just made a distorted half circle. Then I thought about attaching bezier curves to the right point on the circle and getting the starting tangent at that point to match the circle. I thought about this for a pretty long time before I decided two things. One, this was very similar to my last technique of solving smooth stretch, which I decided was too complex. And two, I only had a vague idea of how to do this, so it was going to take too long to figure out.

I went back to staring at my math chalkboard.

I had another epiphany. I had one unit circle. If you draw a second circle that touches the first at a single point, that point will have the same slope on both circles. I already had the equation for a circle. I just needed to constrain it so that it touched the first. Then I could constrain it so that its bottom edge would touch y=0. That would give me a nice smooth falloff. What’s more, if I changed the radius of the second circle, I could control exactly how long the IK chain would be when it became straight. This was an important point. Though I haven’t mentioned it before, this was very high on my list of priorities when I was considering how to approach this problem. The final equation needed to provide flexible and intuitive control for animators. Any solution that couldn’t achieve both would not be a real solution.

Easy to say, but it wasn’t necessarily easy to implement. This took me awhile to figure out how to do. In the end, I ended up with a graph that used two functions to draw a single smooth curve (https://www NULL.desmos NULL.com/calculator/y758xj2rw6) which never falls below the unit circle on the y-axis.

The math for that graph is as follows.
\textup{Radius} = 0.5(\textup{Falloff\_Length}^2 - 1)
\textup{Unit\_Circle} = \sqrt{1-\textup{IK\_Scale}^2}
\textup{Falloff\_Circle} = \textup{Radius}-\textup{Radius}\sqrt{1-\left(\frac{\textup{Falloff\_Length}-\textup{IK\_Scale}}{\textup{Radius}}\right)^2}
\textup{Tangent\_Point} = \frac{\textup{Falloff\_Length}}{\sqrt{\textup{Radius}^2+\textup{Falloff\_Length}^2}}

  • Falloff_Length is the point where the falloff reaches y = 0 (the y intercept). That is, the scale of the arm when it becomes completely straight.
  • Radius is the radius of the second circle (the Falloff circle). It is a function of Falloff_Length.
  • Tangent_Point is the point at which the two circles meet. When IK_Scale is less than or equal to this, the unit circle equation is used. When IK_Scale is greater, the second falloff circle equation is used.

All that was left was to plug the result of that equation into the pythagorean theorem to find the stretch scale.

Math functions usually hurt my brain. So if you’re like me, here’s the python code of what’s going on above. This is the python code I’m currently using inside my final smooth stretch node. Note that this python code has some minor optimizations – primarily it skips calculating the unit circle function since any pythagorean operation on the unit circle will always result in 1.