Nuke: Normalizing animation curves

I have written a little tool to help turn animation curves into more useable numbers. I’ve called it CurveConverter and it’s just a node that takes an input curve and generates an output curve. Copy any animation into the input, then control other animations in your comp by linking them to the output.

Image

Why is this useful?

Any time you have an animated value in your script that you wish to use to drive other animations, you will most likely have to multiply it by another value to get it into a useable range or scale it by hand in the curve editor. You might have to fiddle a while to get the peak and trough values to be where you want them. With this tool you don’t need to do any maths or manual scaling, just copy the curve across and enter your minimum and maximum values. It will scale the curve so that the highest peak is your maximum value and the lowest trough is your minimum value.

Image

Practical example:

You have a plate with flickering fire light and you need to create a patch or CG character with flickering lighting to match. You might use a CurveTool node to analyze the average intensity of the plate (giving values perhaps between 0.028 and 1.124). Normally you might then link a grade node to that animation curve and work out what value you need to multiply by to get a good result.

Instead, go to a dark frame and adjust your grade node so your patch matches (perhaps using the multiply or gain), copy that value into the ‘New min value’ of a CurveConverter node. Then go to a bright frame, adjust to match then copy the value into the ‘New max value’. The patch should now animate between those two settings.

Alternatively, use a CurveConverter tool to convert that curve into values between 0 and 1. Then connect the result to a Dissolve node to switch between a dark grade setup and a bright grade setup. This way would allow you to do more complex grade adjustments in the two lighting states.

Another application would be matching animation to an audio curve.

Nuke: blip expressions to copy and paste

Using waves to drive animation in Nuke – part 2

In my previous article on this subject I gave some examples of expressions that you can just copy and paste into any value in Nuke to quickly create an infinitely repeating animating pattern. I was asked in the comments how to do a ‘blink expression every x frames’. I answered with ‘just use the square wave example’, but I realised that’s not what he was after. In this article I’ll give you some expressions that can be used for such a blink or ‘blip’ animation curve.

I have also made a new version of my gizmo WaveMaker that incorporates all of this, so you can download that if you’d prefer. It’s now in .nk format rather than .gizmo so it’s easier to share.

Square on/off blip every n frames

(((((sin(((frame*(pi*2/(freq/2))/2)+offset))+1)/2)) > cutoff ? 1 : 0) * (maxVal-minVal) ) + minVal

(Where ‘freq’ is the number of frames between blips, ‘offset’ is the time offset, ‘cutoff’ is a value between 0 and 1 which controls the width of each blip, ‘minVal’ is the lower value, ‘maxVal’ is the upper value. As in the previous article, either replace these variable names with your values, or better still, create a NoOp node, add some user knobs with those names and you’ll be able to adjust it on the fly)

Simpler version: ((( sin( ( ( frame * ( pi * 2 / ( 5 / 2 ) ) / 2 ) + 0.5 ) ) + 1 ) / 2 ) ) > 0.95 ? 1 : 0

(Blip pattern between 0 and 1, replace the ‘5’ to adjust amount of frames between blips, adjust the ‘0.5’ to move the whole thing back and forth in time, and adjust the ‘0.95’ to adjust the width of the blips)

So what’s it doing?

It’s really just a simple sine wave with another expression applied to see when that sine wave goes above the cutoff point. If so, set the value to 1, if not, set it to zero. If a high enough cutoff point is given (like 0.95) most of the time the sine wave will be below that value and only at the very tip of the peak go above it. The lower the cutoff, the longer the peak rises above the cutoff point and so the blip gets wider.

But if you need something a bit smoother than a simple on/off, I’ve also made this version:

Smooth pulse-like blip every n frames

(min((max((((((sin(((frame*(pi*2/(freq/2))/2)+offset))+1)/2)) > cutoff ? (((sin(((frame*(pi*2/(freq/2))/2)+offset))+1)/2)) : 0)) – cutoff,0) * (1/(1-cutoff)) * 1.001),1) * (maxVal-minVal) ) + minVal

Slightly simpler version: (min( (max( ((((( sin( (( frame*( pi * 2 / ( 10 / 2 ) ) / 2 ) + 1.55 )) + 1 ) / 2 )) > 0.7 ? (((sin( ( (frame * ( pi * 2 / ( 10 / 2 ) ) / 2 ) + 1.55 ) ) + 1 ) / 2 )) : 0 )) – 0.7 , 0 ) * ( 1 / ( 1 – 0.7 )) * 1.001) , 1 ))

(Smooth blip pattern between 0 and 1, replace the ’10’s to adjust amount of frames between blips, adjust the ‘1.55’s to move the whole thing back and forth in time, and adjust the ‘0.7’s to adjust the width of the blips)

Multiple blips

To make a complex repeating pattern of blips, create several user knobs using the above expressions, set to different values, then in another user knob max them all together:

max( max( blip1, blip2 ) , blip3 )

Manual looping

Remember, if you just need a quick repeating pattern for one thing in one shot, then building all these expressions is probably overkill because you can just draw a pattern in the curve editor, then tell Nuke to loop that pattern. This is more for the cases where you may have several things blinking on and off at different rates (perhaps a HUD, graphics display or warning lights on buildings), and you may need to go and adjust them all later. I personally wouldn’t go to the trouble of building all the knobs each time, that’s why I built BlipMaker into my WaveMaker gizmo so it’s available whenever I need it. My article where I took all my expressions from WaveMaker and made them available for quick copying and pasting has proved rather popular though so I thought I’d do the same for BlipMaker.

WaveMaker v4

WaveMaker v4 available

 

Edit on 12/10/2013: This tool has been superceded by my new tool Animation Maker.

If you are familiar with my gizmo WaveMaker, I have made another version with two differences:

1) BlipMaker added. Allows you to generate blip animations for animating flashing beacons, LED lights or anything that needs to blip on for a frame or so every few seconds. WaveMaker itself can’t generate such a curve, it can only create squared versions of existing waves, meaning you could get it to come on for a frame, but it would only be off for another frame before it came on again. BlipMaker lets you choose the ‘on’ length and ‘off’ length separately. Examples below.

2) Instead of sharing the gizmo, I have provided a .nk file with a group node inside. If you want to use it as a gizmo, just load up the file, load the group in the properties tab, and Export as Gizmo… from the Node tab. However if you want to avoid problems when sharing your scripts, you can just import this .nk file into your script whenever you need it. The third, best option is to use the provided example menu.py file to create a custom button in your toolbar that looks and behaves like a regualar gizmo but is in fact just importing that .nk file each time you press it.

Download the zip file here

BlipMaker

Example curve: Blip of one frame, every 24 frames

Example curve: Soft blip over three frames, every 24 frames

Example curve: Three one frame blips, every 24 frames

Example curve: Combination pattern of blips with different settings, every 24 frames

These are just a few examples, you can play around with the sliders to get all sorts of combinations. Feel free to drop me a line or leave a comment if you use WaveMaker in any of your projects, I’m always interested to see how people use it.

If you just need to grab these expressions quickly, have a look this article where I break it down further.

Nuke: Retiming tracking data and cameras

Retiming a curve

There are many retiming options in Nuke but how do you retime tracking data or animation?
The answer is actually very simple and can be used wherever you have an animation curve in your script. If you are using an OFlow node, called ‘OFlow1’, and are using ‘Source Frame’ timing, rather than ‘Speed’ to retime a plate, you can access the retime curve by referring to ‘OFlow1.timingFrame‘.

So if you apply the following expression to any other curve in your script, that animation curve will be retimed to match OFlow1:
curve(OFlow1.timingFrame)

Translated: “For the frame I am currently on, instead of using the current value, jump to the frame the OFlow is currently looking at and use the value from this curve at that frame“.

Offsetting a curve

Any control that has keyframe animation, right click the curve icon and choose ‘Edit Expressions…‘ and you should see it has one expression in there already: ‘curve‘. This is just the curve created from your keyframes. You can treat that curve like a variable, for example ‘curve*2‘ to double the amplitude of the curve. Putting a value in brackets after it allows you to slip the curve back and forth in time. ‘curve(frame-5)‘ would offset the curve by 5 frames. “At this frame, don’t use this value, use the one 5 frames earlier“. ‘frame‘ is a variable that always contains the current frame number. The resulting output would look something like this:

An example script

Let’s say you have a shot of a building and you want to patch in some extra windows. You don’t want to use a still because there are shadows of people moving around inside the building so you want to copy another window, translate it to the new position and then retime the input so the people moving round look less repetitive. If it was a locked off shot, you could just retime it, copy and translate it. But if there is a camera move and camera wobble it will need to be stabilized, translated then match-moved. But where do you put the retime node? It makes sense to put it after the stabilize, but then you will break concatentation with the translate and match-move nodes, potentially introducing softening. Using the above method of retiming the tracking data, you can keep the transform nodes together and keep concatentation.

In this example I’m using a CornerPin node as my stablize/match-move, exported from Mocha Pro.

One of the patches in this example doesn’t use any retiming, and the other does. They use an identical setup but one has expressions linked to the OFlow. I have put a dot node in there so you can see the expression line more clearly. The CornerPin nodes labelled ‘stabilize’ and ‘match’ are identical but the stabilize ones have the ‘invert’ check box ticked. I could have cloned several of them but the tracking data is unlikely to change so a straight copy/paste is better here.

When I right click on any parameter in cornerPinTrack4 and choose ‘Edit Expressions…‘ I enter the above expression into each corner:

No matter how I animate my OFlow1 node, the cornerPinTrack4 node will adjust it’s tracking data to match the newly retimed plate, keeping it stabilized. Of course, if you retime it to extremes, the plate and/or tracking data will run out. In this example I have just slowed it down and sped it up again. The retime curve looks like this:

When I look at the curve for one of the values in my corner pin (the x value of corner 1) it shows the original keyframes with the newly calculated curve on top:

I drew the roto shape on my reference frame around the window I wanted to copy, whilst looking at the result of the cornerPinTrack4. I then cloned the offset transform node and put it beneath the roto shape. I could have just viewed the result of the offset transform node when I drew my rotoshape to achieve the same thing, but this way I can change my mind about the offset later if I want, moving it to a different position and the rotoshape will always be in the correct place.

To avoid grain issues you will probably want to degrain the plate and regrain the patches afterwards. Even if it doesn’t get softened, you don’t want grain running at different speeds.

Using a TimeWarp node instead

If you are retiming with a timewarp node, you can use the ‘lookup’ value instead to achieve the same thing:
curve(TimeWarp1.lookup)

Summary

This trick can be used anywhere in your nuke script; anywhere there’s a keyframed knob, you can adjust the curve by adding an expression to it. In most cases retiming is done to the plate beforehand or at the end of a comp, so your matchmove will have been done on the retimed plate already, or if at the end, then it doesn’t matter. But occasionally a decision will be made later on, after you have your matchmove, to retime something and it means throwing off all your animation. But using this expression you can keep the existing animation, whether that be tracking, a 3D camera, switches, fades or transforms, and avoid precomps and other methods that might introduce softness by breaking concatenation.

And yes, I did say 3D camera… if you have a tracked camera but the plate has to be retimed, you can put this expression on every animated value in that camera (once you untick ‘read from file‘) and the camera will now match the retimed plate. No need to send it back to the matchmove department.