Sunday
Jul152012

This is cool

Monday
May282012

Python Scripting a Projection Camera

I’m in the process of trying to learn Python, so I can do things faster in Nuke.  It’s tough.  I have no experience with computer programming at all, and it’s not really coming naturally to me.  I do have some resources to learn from though.  I thought the best way would be to just dive in and start trying things.  Something that I do all the time is make a projection camera from a tracked camera.  There are similar scripts on Nukepedia, but I thought I’d take a crack at it myself.

The first thing I did was make a list of what I would need my script to do.  So, assuming that I had selected a tracked 3D camera in Nuke, I would want my script to do the following:

-First thing, check and make sure it’s a Camera node.  If it’s not a Camera node, then put up a message saying “This isn’t a Camera’.

-Copy and Paste the Camera, so that the original camera doesn’t get messed up.

-Add in a control panel that allows me to select the frame I want the projection camera set to.  Ideally, this would be in the frame range of my project.  Even better would be a button to allow me to select the current frame.

-Connect the animation to the control panel, so that the control panel actually does something.

-Change the color of the pasted Camera node in the DAG.  I always change my projection cameras to a bright purple color.

-Change the name of the pasted Camera to ‘Projection Camera’, and give it an autolabel so that whatever frame I select, it’ll show up in the DAG.

I was actually able to make this, but I needed a lot of help.  I went to Nukepedia and downloaded a similar Python script.  On Nukepedia there’s a script called copyCamForProj (v3.1) (http://www.nukepedia.com/python-scripts/3d/copycamforproj/) by Marco Leone.  This is a great script, and by downloading it and checking it out, I learned a lot about python scripting.  Basically, I would try to build the tool on my own.  When I would run into problems, I’d refer to Marco’s script to try to help me through it.  If you compare the two scripts, you can see I needed a lot of help, and I’d say that most of this is Marco’s work.  But by the end I had learnt a lot about Python, so it was fairly successful.

So, the first thing is to copy and paste the Camera node.  Nuke does have a python command that allows us to copy a node to the operating system’s clipboard, then paste it back into the DAG.

 

nuke.nodeCopy('%clipboard%')

nuke.nodePaste('%clipboard%')

 

We want to change it’s name to Projection Camera, so there’s a command for that:

 

nuke.selectedNode().setName(‘Projection Camera’)

 

We’re going to be using the command ‘nuke.selectedNode()’ pretty often.  The good thing is that when you copy and paste a node in Nuke, then the pasted node automatically is selected.  We’ll be making a variable for that expression and put it at the top of the script editor:

 

n = nuke.selected Node()

 

Then we’re going to change the set name command to accommodate the expression.

 

So,

nuke.selectedNode().setName(‘Projection Camera’) becomes:

n.setName(‘Projection Camera’)

 

Our program now looks like:

 

#Assign variable to the selected node

n = nuke.selectedNode()

 

#Copy and Paste the Camera

nuke.nodeCopy('%clipboard%')

nuke.nodePaste('%clipboard%')

 

#Give it the name 'Projection Camera'

n.setName('Projection Camera')

 

The next thing to do is to change the node’s colors in the DAG and the Open GL view.

 

#Change it’s color

n[‘tile_color’].setValue(4278255615)

n['gl_color'].setValue(4278255615)

 

The color value there is a pretty crazy number, but that’s a hexadecimal number for the RGB values.  If you want to add your own color, the easy way to find the hexadecimal value is to color a node, then run this command in the script editor:

 

nuke.selectedNode()['tile_color'].value()

 

It will print out a number that you’ll be able to use in your script.

Once we have that, we want to add the control panel to have our slider on.

 

n.addKnob(nuke.WH_Knob('projFrame', 'Projection Frame’))

 

This is a long command, which can be confusing to read.  We’re going to break it up into two lines, one line assigning it to a variable called ‘control’.

 

#Assign a variable to the new projection frame control 

control=nuke.WH_Knob('projFrame', 'Projection Frame')

 

#Add the knob for the projection frame control

n.addKnob(control)

 

Then we want to link the new control panel to the translate, rotate and focal length sliders

 

#Add in the Projection Frame control to the expressions

n.knob('translate').setExpression("curve(projFrame)")

n.knob('rotate').setExpression("curve(projFrame)")

n.knob('focal').setExpression("curve(projFrame)")

 

Our tool now works, but it just barely.  We need to add a few things.  The main thing is that we need to make sure that this only works on Camera nodes.  We can do this by adding in a ‘if’ statement.  We can say that if the selected node is a Camera node, then run the commands.  If it’s not, then put up a message to the user.  We can do this by typing:

 

#Check to make sure that a Camera Node is selected

if (n.Class() == 'Camera2') or (n.Class() == 'Camera'):

 

  #Copy and Paste the Camera

        nuke.nodeCopy('%clipboard%')

        nuke.nodePaste('%clipboard%')

 

        #Give it the name 'Projection Camera'

        n.setName('Projection Camera')

 

        #Change it's color

        n['tile_color'].setValue(4278255615)

        n['gl_color'].setValue(4278255615)

 

        #Assign a variable to the new projection frame control 

        control=nuke.WH_Knob('projFrame', 'Projection Frame')

 

        #Add the knob for the projection frame control

        n.addKnob(control)

 

        #Add in the Projection Frame control to the expressions

        n.knob('translate').setExpression("curve(projFrame)")

        n.knob('rotate').setExpression("curve(projFrame)")

        n.knob('focal').setExpression("curve(projFrame)")

 

    else:

        nuke.message("This is not a camera node")

 

Now we can add in a few things that will make it a bit more convenient.  We’re going to get the values of the first frame and last frame of our comp and put those in a list.  We can do that by typing:

 

    #Assign variable to the shot's first and last frame

    Min_Max = []

 

    #Get the first and last frame numbers, append these values to the variable

    Min_Max.append(nuke.Root()['first_frame'].value())

    Min_Max.append(nuke.Root()['last_frame'].value())

 

    print Min_Max

 

Then in the body of the script, we add in a command to get those values:

 

#Set the first and last name of the control panel

control.setRange(Min_Max[0], Min_Max[1])

 

#Assign the first frame of the shot

n['projFrame'].setValue(Min_Max[0])

 

Then we’re going to add a button on our control panel that will set the value of our Projection Frame slider to the current frame:

 

#Make the 'Set Current Frame Button

n.addKnob(nuke.PyScript_Knob('curFrameBut', 'Set To Current Frame', 'nuke.thisNode()["projFrame"].setValue(nuke.frame())'))

 

Last thing is adding in a command to put down a command to write the frame number we’re using in the Camera node:

 

n['label'].setValue('Frame:[value projFrame]')

 

So our script will now look like this:

 

    #Assign variable to the selected node

    n = nuke.selectedNode()

 

    #Assign variable to the shot's first and last frame

    Min_Max = []

 

    #Get the first and last frame numbers, append these values to the variable

    Min_Max.append(nuke.Root()['first_frame'].value())

    Min_Max.append(nuke.Root()['last_frame'].value())

 

    print Min_Max

 

    #Check to make sure that a Camera Node is selected

    if (n.Class() == 'Camera2') or (n.Class() == 'Camera'):

 

        #Copy and Paste the Camera

        nuke.nodeCopy('%clipboard%')

        nuke.nodePaste('%clipboard%')

 

        #Give it the name 'Projection Camera'

        n.setName('Projection Camera')

 

        #Change it's color

        n['tile_color'].setValue(4278255615)

        n['gl_color'].setValue(4278255615)

        n['label'].setValue('Frame:[value projFrame]')

 

        #Assign a variable to the new projection frame control 

        control=nuke.WH_Knob('projFrame', 'Projection Frame')

 

        #Add the knob for the projection frame control

        n.addKnob(control)

 

        #Set the first and last name of the control panel

        control.setRange(Min_Max[0], Min_Max[1])

 

        #Assign the first frame of the shot

        n['projFrame'].setValue(Min_Max[0])

 

        #Make the 'Set Current Frame Button

        n.addKnob(nuke.PyScript_Knob('curFrameBut', 'Set To Current Frame', 'nuke.thisNode()["projFrame"].setValue(nuke.frame())'))

 

        #Add in the Projection Frame control to the expressions

        n.knob('translate').setExpression("curve(projFrame)")

        n.knob('rotate').setExpression("curve(projFrame)")

        n.knob('focal').setExpression("curve(projFrame)")

 

 

 

 

    else:

        nuke.message("This is not a camera node")

 

The last thing is to save this script out as a Python file.  In order for Nuke to import this command for it to use, we need to add in two lines at the top:

 

import nuke

 

def makeProjectionCam():

 

Now we want to add this so that every time Nuke runs, we can use this script.  So we need to add the following to our menu.py file:

 

import makeProjectionCam

nuke.toolbar('Nodes').addMenu('Downloaded Gizmos’).addCommand('3D/Projection Camera', 'makeProjectionCam.makeProjectionCam()', 'shift+V')

 

This will create a new menu item in Nuke that’s linked to the Python script.

Hopefully you found this helpful.  If you have any tips on making it better, please leave a comment, I need all the help I can get.

 

Below is a video, showing the tool in action:

 

Sunday
May272012

Update

Maintaining a blog is much harder than it sounds.  It's been almost a year since my last post, which is horrible.

A few updates:

Things at the school have been better than ever.  The latest class graduated about a month ago and produced awesome work.  I've started working on the You Tube video of their work, which should come out in late August.

I finished up a contract at Arc Productions, working on a movie called 'Little Boy'.  I'll be going back there for another project in July.

A few months ago I became one of the first certified Nuke trainers in Canada.  In fact, I was the first one in Canada when I took my final test, but I'm sure that there's probably many of them now.  If you know of anyone who needs a Nuke trainer, contact me.

Wednesday
Jun292011

Toronto's first Nuke User Group Meeting

Last night was the first Toronto Nuke User Group meeting, sponsored by The Foundry and their new local reseller, Oceana Digital.  It was a bit different than previous Foundry events in the city.  There was no real demonstration of software, and no sales pitch about new products.  This was different.

This was more of a social get together, and it was great seeing old friends from other studios in the city.  

It was first of many community events that will be held.  I think the idea for this meeting was to get feedback and find out what people would want from future user group meetings.  The next meeting, which should be in the early fall, will have some software demonstrations and hopefully some examples of work done in the city.  There's a real need for continuing visual effects education for artists in the middle of their careers, and I'm hoping that these user group meetings will help fill that need.

Monday
May232011

Colour Correction

When I started compositing, colour correction seemed like a black art.  I would push and pull different controls until I would eventually get something that looked somewhat like what I wanted.  When I had spare time, I would open other artists’ scripts and I’d marvel at how they would colour correct a shot.  Every artists' technique was different - some would exclusively use curves.  Others would use levels/histograms, while others would use numeric inputs.  Looking at other artists' scripts would allow me to undertand their technique, but I was still clueless about their thought process - about why they did what they did. 

I fumbled around with colour correction over my first few years of compositing.  The first step towards understanding was reading Steve Wright and later, Ron Brinkmann’s compositing books.  They explained basic things like matching black and white levels and checking different colour channels. These details now seem obvious. However, at the time, gaining this understanding was like lifting a heavy vale from my eyes.

Understanding the different tools took time.  I had to learn that ‘gain’ really meant ‘multiply’, and ‘offset’ meant ‘add‘. I had to learn that there was a difference between these controls and between their impact on images. It took me some time to grasp that when you multiply images highlights are affected more than shadows.  Colour correction was one of those things that just took practice.  It was here that the ‘compositing is really visual math’ really started to click for me. 

Even now, whenever I submit a shot for review, I receive feedback about a necessary colour correction. There is definitely a certain level of subjectivity to colour correction: supervisors often have a different idea than I on how a shot should look.  However, I’m now usually much closer to the target than I used to be, and it only takes one or two iterations before everyone is satisfied.


These books contain great advice about how to approach colour correction.  Wright and Brinkmanns’ books are software independent, while Christiansen’s book is specific to After Effects.

Colour correction resources:

Steve Wright

After Effects Studio Techniques