Animation Maker

Ease curves in Nuke, with just a right-click.

menu

I have made a little extension to Nuke that when right-clicking any animatable value on any node you can choose ‘Animation Maker…‘ from the pop up menu and a whole suite of customisable animation curves can be chosen. When you’re happy, it generates the expression to form that curve and puts it into the knob in question. It also adds a user tab to the node with sliders so you can refine it on the fly. No extra nodes or expression lines in your script and it’s available everywhere.

It does all the maths for you.

Contains ease curves such as Quad, Exponential, Bounce and Elastic. Wave curves such as Sine, Random, Noise, Triangle and Sawtooth. Options to combine a wave with an ease curve, turn a wave into a ‘square’ version or create a sequence of blips at certain intervals.

All contained in one .py file. No gizmos required. Just put the file in your .nuke directory (or wherever your plugins directory is located), then add two lines to your menu.py.

Download here

This supersedes my previous WaveMaker tool, so no need to have both installed.

AnimMaker

Pop up dialogue in Ease mode, showing the motion with a growing circle, a moving circle and a circle fading from black to white.

AnimMaker2

Pop up dialogue in Wave mode showing an example noise wave.

tab

When CREATE is pressed, a new tab like this will appear on the node.

expression

An expression will be put into the chosen knob which is linked to the new tab’s controls.

easeout

An example Expo Ease Out curve

ease

An example Expo Ease In curve

easeinandout

An example Expo Ease In & Out curve

bounce

An example Bounce curve

elastic

An example Elastic curve

noise

An example Noise wave

waveEase

An example Sine wave combined with a Linear ease in.

blip

An example Blip animation made from a Sine wave.

Advertisements

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.

Nuke wave expressions to copy and paste

Using waves to drive animation in Nuke

Creating repeating or random patterns in the curve editor can often be made easier by using expressions that describe a curve. Sine, noise and random functions are very useful, but forcing them into the exact shape you want can be a little time-consuming. So, following my previous post talking about my gizmo WaveMaker, I thought I’d share some handy expressions it uses which you can copy and paste straight from this blog when you need them, rather than installing the gizmo itself.

Edit on 12/10/2013: I have just released Animation Maker, a handy Nuke extension that contains all the waves talked about here, plus lots of Ease curves too. See the article here.

Click on any value in any node, press ‘=’ and type an expression. Right click and choose ‘Curve Editor…’ to view the curve.

These expressions give you full control over the width, height and position of the wave. Either replace the following variables with your actual values, or add your own sliders to the node so you can adjust them on the fly (see below for how to do that).

waveLength (how many frames between peaks of the wave)
minVal (the wave will never go below this value)
maxVal (the wave will never go above this value)
offset (shift the wave back and forth in time)

Edit on 15/01/12: I have also provided simple versions that will work immediately once you paste them in. They will just produce a wave between 0 and 1 but that may be all you need.

Some useful wave expressions:

Sine

(((sin(((frame*(pi*2/(waveLength/2))/2)+offset))+1)/2) * (maxVal-minVal) ) + minVal

Simple version:  (sin(frame/5)/2)+0.5  (Wave between 0 and 1, replace the ‘5’ to adjust speed) 

Square

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

Simple version:  (sin(frame/5)/2)+0.5 > 0.5 ? 1 : 0  (Wave between 0 and 1, replace the ‘5’ to adjust speed)

Triangle

(((((2*asin(sin(2*pi*(frame/waveLength)+offset)))/pi) / 2)+0.5) * (maxVal-minVal) ) + minVal

Simple version:  (((2*asin(sin(2*pi*(frame/30))))/pi) / 2)+0.5  (Wave between 0 and 1, replace the ’30’ to adjust speed)

Sawtooth

((1/waveLength)*(((frame-1)+offset) % waveLength) * (maxVal-minVal) ) + minVal

Simple version:  ( 1 / 30 )*( (frame-1) % 30)  (Wave between 0 and 1, replace the two ’30’s to adjust speed)

Random

((random((frame/waveLength)+offset)) * (maxVal-minVal) ) + minVal

Simple version:  random(frame/5)  (Wave between 0 and 1, replace the ‘5’ to adjust speed)

Noise

(((1*(noise((frame/waveLength)+offset))+1 ) /2 ) * (maxVal-minVal) ) + minVal

Simple version:  (noise(frame/5)/2)+0.5  (Wave between 0 and 1, replace the ‘5’ to adjust speed)

Bounce

((sin(((frame/waveLength)*pi)+offset)>0?sin(((frame/waveLength)*pi)+offset):cos((((frame/waveLength)*pi)+offset)+(pi/2))) * (maxVal-minVal) ) + minVal

Simple version:  sin(((frame/10)*pi)) > 0 ? sin(((frame/10)*pi)) : cos(((frame/10)*pi)+(pi/2))  (Wave between 0 and 1, replace the ’10’s to adjust speed)

Sawtooth (parabolic)

((sin((1/(pi/2))*(((frame-1)+offset)/(waveLength/2.46666666)) % (pi/2)))>0.99999? 1 : (sin((1/(pi/2))*(((frame-1)+offset)/(waveLength/2.46666666)) % (pi/2))) * (maxVal-minVal) ) + minVal

Sawtooth (parabolic, reversed)

((cos((1/(pi/2))*(((frame-1)+offset)/(waveLength/2.46666666)) % (pi/2)))>0.99999? 1 : (cos((1/(pi/2))*(((frame-1)+offset)/(waveLength/2.46666666)) % (pi/2))) * (maxVal-minVal) ) + minVal

Sawtooth (exponential)

((((((exp((1/(pi/2))*(((frame-1)+offset)/(waveLength/4.934802)) % pi*2)))/534.5)) – 0.00186741)>0.999987? 1 : (((((exp((1/(pi/2))*(((frame-1)+offset)/(waveLength/4.934802)) % pi*2)))/534.5)) – 0.00186741) * (maxVal-minVal) ) + minVal

*Note: the waveLength value doesn’t really correspond to the peaks in Random or Noise waves, so you will probably need a smaller wavelength value for those.

To add your own sliders:

  1. Right click your node, choose ‘Manage User Knobs…’
  2. Click ‘Add…’ and choose ‘Floating Point Slider…’
  3. Type ‘waveLength’ into its name and label boxes. Give it a max and min value of 0 and 100.
  4. Repeat with each of the four variable names (above).

These  four sliders will appear in the ‘User’ tab of the node. You may find it better to create a ‘NoOp’ node, add the above sliders, but also add several extra floating-point sliders called ‘Wave1’, ‘Wave2’, ‘Wave3’ etc. This way you can use the same sliders to control several different expressions, then you can use any one of them to drive animations in your script.

It’s worth noting many of these wave shapes can be created using a few keyframes and telling nuke to ‘loop’ that section. But using expressions with a few sliders you can mess around with them a lot easier. Besides, maths is fun.

One more thing:

To describe a CIRCLE, put this in the X: 

(((sin(((frame*(pi*2/(waveLength/2))/2)+offset))+1)/2) * (maxVal-minVal) ) + minVal

and this in Y:

(((cos(((frame*(pi*2/(waveLength/2))/2)+offset))+1)/2) * (maxVal-minVal) ) + minVal

Simple version (X): sin(frame/5)*300

Simple version (Y): cos(frame/5)*300

(replace the ‘5’ to adjust speed, replace the ‘300’ to change the circle size)

Tip: put it in the X and Z in a TransformGeo after a Card to make a carousel type animation.

Nuke: Stabilizing a plate with CameraTracker

Discovered today that you can easily use  a 3D camera track in Nuke to stabilize a plate – and what’s more, you can easily choose which plane of the image you want to lock down (something in the foreground, mid-ground or background).

CameraTracker Stabilize screengrab

  1. Get a good 3D camera track, masking out anything that moves first.
  2. Solve the camera and go to a frame you’d like to use for reference, probably somewhere in the middle of the sequence.
  3. Copy and paste the camera, renaming them to something like ‘CameraMain’ and ‘CameraProject’.
  4. Open the properties of CameraMain and remove any animation (right click the parameter and choose ‘No Animation’)
  5. Create a Project3D node and connect it to CameraProject. Also plug the plate into the Project3D.
  6. While viewing the plate, bring up the CameraTracker properties pane so that you can see the solved camera tracks over the plate. Choose one that sits on the plane you want to stabilize, eg on the back wall. Then right-click the point and choose ‘create – card ‘ to create a card in 3D space at that coordinate.
  7. Plug the Project3D into the card.
  8. Switch to 3D view and you should see the image projected from CameraProject onto the card. Remove all rotation from the card in the properties pane so that it’s flat on to CameraMain, then use the Uniform Scale on the card to scale it up nice and large so that none of the picture gets cut off.
  9. Now, create a ScanlineRender, plug in the card and CameraMain (your stationary camera), then view the result. If you are still on the same reference frame, the output should be identical to the plate.
  10. Play it back and you should see a stabilized image. You will then need to crop the image to remove black edges appearing. To choose a different plane to lock to, just repeat steps 6-8 using a different point from the track (eg, something from the foreground). You can do this several times and keep the cards in your script, swapping them out to find which one gives the best result. Alternatively you can just play with the Z translation of the first card until you get what you want, but choosing an actual point on a plane will probably be quicker.

So, to summarize, the viewing camera and the card do not move at all, but the image being projected moves around on the card, which matches the camera move in the shot, cancelling out the movement.

EDIT: After using this technique quite a lot for various tasks, I realise that for best results you should create a card at the angle of the plane you want to stabilise (by selecting multiple points on that plane and creating a card), rather than pick one point and remove rotation. That’s what you’d do for a frame hold patch projection, so you’d do the same here. Only difference is you swap the cameras.

This means after you stabilise, you can copy the card and project it onto the new card with the cameras swapped to match move it back to the original. Useful for creating mattes, but not advised for patches because of the slight softness produced as it breaks concatenation between the two stages. I’ve been using it recently to create rain mattes; remove the camera movement using the 3D track, Min 3 adjacent frames together to remove the bright rain drops, use a Difference node between the stablised plate and the Min, then match move using the same camera setup. Gives a nice alpha of the rain as that’s the only thing moving in the plate.