Thursday, May 10, 2012

Autoswim-fish-expressions follow up . . .

A couple of months ago I had someone (Patrice Berube) e-mail me a question about some of the behavior in the autoswim fish rig. Been pretty busy with work and all so never got around to posting about the issue . . .
Basically, the problem was when one animated the frequency of the swimming fish (whole or part), over the frames where the animation occurs the sine wave function would freak out, go super fast, super slow, backwards, etc.
Since the rig was made remotely for a studio, I never really got a chance to play with it too much once I made it and no one ever brought up the issue (I actually knew more or less what the animation would be, and animating the frequency never really entered into it. I also suspect that a lot of the animation was done on the FK controls). But once Patrice pointed out what the issue he was having, the problem became more clear.
Essentially, through all of the expressions and such, time was constant (or moving constantly), but changing the frequency as time progressed would give kind of random values as you passed through the progression of frames (essentially, the sin values no longer had any sensible relationship to the values from the previous frame). My first reaction was, "uh oh! This will take some of that crazy math stuff to solve". But as we batted around a couple of emails about, we both kind of arrived at a similar solutions that were a bit more palatable (though I'd still like to know a math-y solution, I can't be bothered at this point).
Here's the problem illustrated:

As you can see, the values that are coming out of the sine function (which is the basis for the joint rotation) are fine if you don't animate the freq. Predictable values, each frame (in this case) changing by a value of 1 in oscillating directions.
But when you animate the freq it looks like it should make sense, but the values kind of suck. Starts out fine (delta of 1. Look I'm using mathy terms!), but then the changes become really unpredictable, sometimes almost 2, sometimes about zero. So the animation would look crazy.
 As it turns out the solution Patrice and I both realized independently (with Patrice actually implementing it, rather than just thinking about it :) is that rather than getting hard-core on the math, you could simply take the constant time out of the equation and not worry so much about animating the frequency. Instead, if you create an attribute to take the place of time (I thought to call it "time", he thought to call it "swimspeed". His is better) and simply animate that to make your fish swim, it would solve the problem. So in your expressions you'd simply replace "frame" with $swimspeed (which pulls the value of that attr), you could speed up or slow down the sine wave without fussing with the global frequency. A linear curve for "swimspeed" equals some version of normal time and messing with that curve will give you faster or slower time (as far as the fish rig is concerned).
Note that you'd still have problems if you tried to animate the frequency of the individual controls (because those frequencies would be animated relative to the new "swimspeed" attr). But that's less of an issue. You can just set those frequencies to be whatever you'd like, per control and control the rest of the animation globally.
Hope that helps anyone having this issue and big thanks to Patrice for pointing it out and working through the problem!