Export camera to .chan file for Nuke

I was wondering if there’s any interest for getting Blender camera data into Nuke. I just abandoned Shake’s Multiplane node because I’m just not psychologically wreaked enough to trudge through that mess of a node. Shake is pretty nice but having full 3d capabilities like Nuke is nicer still.

I’m not a programmer but when this project is done in two weeks I’ll have a little time to finally play with python. Just want to make sure I’m not reinventing the wheel.

Oh, and I am using blender for the bulk of the 3d work, and in the interim, for the “multi-plane stuff.”

Here’s a brief example of .chan: http://www.vfxtalk.com/forum/camera-motion-max-nuke-t9962.html

Don’t know if it’s exactly what you’re looking for, but there’s currently an import/export script written for Terragen 2 which uses the .chan format for importing camera data. See here:

http://blenderartists.org/forum/showthread.php?t=113590&page=4

Thanks! It works well. I used latest svn (2.46) and changed the variables in the python script. Before export I needed to get my IPO on my camera as I was controlling the translation with an empty. It’s just a simple move along the z-axis. Probably not the best test.

In Nuke 4.7 I had to clear the x rotation as it was set to -90.

Hola!

Contrary secundar, I didn’t think the exporter worked that well, so since I couldn’t find any other blender2nuke scripts, needed to learn some Python and could use this for work and ignorantly thought it wouldn’t be so hard, I started to “port” this script to Blender 2.5.

This is only the 2. “thing” I ever done in Python, and this one is 96% from the Ter2Blend script so I can’t take too much credit :stuck_out_tongue: I did however learn a lot, and crossed alot of personal dungeons (I haven’t touched math in ~12 years and completely forgotten about radians among many things!). The best resource is without a doubt the BLenses page. Thank you so much, chipmasque! In fact, the .chan-script is practically useless without BLenses or atleast a “basic” focal2fov formula (BLenses includes the distance to object in the formula). This is also why this script needs to be edited manually, since essential information isn’t available from Blender yet (like aperture/sensor dimensions).

The workflow is therefor not as smooth right now. First copy/paste this code to a file and open it in the Blender text-editor:

Edit 23/2/10:
Of course there was something wrong! I was apparently so focused (no pun intended) on just matching the focal-length and image, I didn’t think about testing animation! I automatically assumed it would work, because it work with the 2.49b script, but no. So the following is the updated script. It still misses a whole lot, and I hope to evolve it into a real exporter, so if you find some errors during testing/use, please tell. Thanks!
Edit 20/4/10:
Needed this script today but there’s some minor changes to the 2.5 Python API. Fixed below.

import math
import bpy

DATA = {
    'EXPORT_CAM': True,
    'EXPORT': "/home/san/Desktop/",
    'ERROR': [],
    'HAP': 22.3,
    'VAP': 14.9,
    }

   
def export_cam():
    context = bpy.context.scene
    cams = [ob for ob in context.objects if ob.type == 'CAMERA']
    if len(cams)>0:
        start = context.frame_start
        end = context.frame_end
        for cam in cams:            
            name = cam.name
            lines = ""
            for f in range(start,end+1):
                context.frame_set(f)                
                loc = cam.location
                if cam.data.type == 'PERSP':
                    hfov = cam.data.angle ### radians
                    vfov = math.degrees(2 * math.atan(math.tan(hfov/2) * (DATA['VAP']/DATA['HAP'])))
                else:
                    vfov = False
                lines += str(f)+" "
                lines += str(loc[0])+" "+str(loc[2])+" "+str(-loc[1])+" "
                ### XZY
                lines += str(math.degrees(cam.rotation_euler[0])-90)+" "
                lines += str(math.degrees(cam.rotation_euler[2]))+" "
                lines += str(math.degrees(-cam.rotation_euler[1]))+" "
                if vfov:
                    lines += str(vfov)+" "
                #lines = lines[:] 
                lines += "
"
            chan = open(DATA['EXPORT']+name+".chan",'w')
            chan.write(lines[:-1])
            chan.close()
        
def ExportAll():
    if DATA['EXPORT_CAM']:
        export_cam()

ExportAll()

Change the values in the DATA variable to fit your setup. The HAP and VAP values are the Horizontal- and Vertical-Aperture size in mm. Here aperture is the sensor size on my Canon-50D (22.3mm x 14.9mm). This is a great database of camera-specs where you can most likely find your cameras sensor-size. The default values in Nuke Camera are HAP: 24.575 & VAP: 18.672 (Cineon 2K/4K).

The idea is to match the focal-length between Blender and Nuke, since the focal-length is usually known rather than the field-of-view in degrees/radians! Many cameras also writes this info to exif, so you can look it up later like here in Rawstudio:
http://img6.imageshack.us/img6/3725/focalinfo.png
Note: Aperture here is the shutter aperture (f/stop), nothing to do with sensor-size/film-back! :eek:

Blender Camera doesn’t have either focal-length or aperture dimensions, hence the need for BLenses or if calculating with infinite focus, this function:

def focal2fov(focal, aperture):
    return math.degrees(2 * math.atan(aperture/(focal*2)))

Here ‘aperture’ is either the horizontal or vertical size, returning either the horizontal fov (hfov) or the vertical fov (vfov). In Blender Camera the value in “Angle/Degrees” is the hfov
http://img704.imageshack.us/img704/8251/blenderinfo.png
But Nuke reads and uses the vfov. Looking in the import_chan_file.tcl Nuke script, the math formula (in Python)

def fov2focal( fov, aperture ):
    return (aperture/2) / ( math.tan(math.radians(fov/2)) )

is looking for/using the vertical aperture size in the Nuke Camera properties, since this data is not included in the chan-file. This means you have to enter this data before importing the chan-file. Another important thing to do in Nuke, is setting the rotation-order to XZY:

http://img37.imageshack.us/img37/4248/nukeinfo.png

Only then will the numbers, and ultimately image, match. Not totally smooth, but I’m working on it :wink:
The required actions in Nuke is hard to do something about, and as it is right know Blender Camera is lacking crucial information. Hopefully Blender Camera will work just like BLenses.

I would like to make this script a real Blender 2.5 exporter, but I’m not totally comfortable with creating custom properties (yet), and I still believe that this information should be part of Blenders camera. Until then I still have a lot of Python to learn! And hopefully I can make the chan-importer too :slight_smile:

Edit: Completely forgot to mention that it is important to set the render output size in Blender with the right aspect ratio, taken from hap/vap. For example with a “Full frame 35mm” (36x24mm), if the render output is set to 800x600 it has to be changed to 800x533 to match, since 800/533 = 1.5. BLenses can calculate this for you.

I will also post the modified script for Blender 2.49b when I find it!

I must get a better system for “organizing” text-files… found the modified script, but then realized I had “hacked” the BLenses script to output the vfov instead of hfov which then get entered directly in the .chan-file. Pretty ugly, since first you got to run BLenses to setup your scene correctly with focal-length -> hfov, render what needed to be rendered, then run the hacked BLenses to set the vfov (which of course completely ruins the perspective in Blender), just so Nuke correctly can set the correct focal-length…

So here is the modified Blender2Nuke chan-exporter for 2.4x with the hfov -> vfov formula:

"""
Terragen 2 importer/exporter
Snapshot of work in progress: April 23 2008
© Bartius Crouch 2008

- Exporting cameras
    * Position, rotation
    * Lens angle
"""

import bpy
import Blender
from Blender import *
from math import pi, cos, sin, tan, atan, degrees, radians

DATA = {
    'EXPORT_CAM': True,    #export cameras
    'EXPORT': "/home/san/Desktop/",
    'ERROR': [], #You can ignore this one
    'HAP': 22.3,
    'VAP': 14.9,
    }

def ExportCam():
    cams = [ob for ob in bpy.data.scenes.active.objects if ob.type=="Camera"]
    if len(cams)>0:
        context = bpy.data.scenes.active.getRenderingContext()
        start = context.sFrame
        end = context.eFrame
        cur = context.cFrame
        for cam in cams:
            name = cam.name
            try:
                chan = open(DATA['EXPORT']+name+".chan",'r')
                chan.close()
                overwrite = Draw.PupMenu("Overwrite "+name+".chan?%t|Yes|No")
                if overwrite == 1:
                    file = True
                else:
                    file = False
            except:
                file = True
            if file:
                lines = ""
                for f in range(start,end+1):
                        Blender.Set("curframe",f)
                    loc = cam.loc
                    if cam.data.type=="persp":
                        #aspectRatio = (context.sizeX*float(context.aspectX))/(context.sizeY*float(context.aspectY))
                        hfov = radians(cam.data.angle)
                        vfov = degrees(2 * atan(tan(hfov/2) * (DATA['VAP']/DATA['HAP'])))

                    else:
                        vfov = False
                    lines += str(f)+" "
                    lines += str(loc[0])+" "+str(loc[2])+" "+str(-loc[1])+" "
                    lines += str(((cam.RotX/pi)*180.0)-90.0)+" "
                    lines += str((cam.RotZ/pi)*180.0)+" "
                    lines += str((cam.RotY/pi)*-180.0)+" "
                    if vfov:
                        lines += str(vfov)+" "
                    lines = lines[:-1]
                    lines += "
"
                chan = open(DATA['EXPORT']+name+".chan",'w')
                chan.write(lines[:-1])
                chan.close()
        Blender.Set("curframe",cur)

def ExportAll():
    if DATA['EXPORT_CAM']:
        ExportCam()

ExportAll()

is this the same script?

http://www.virtualmatter.org/stardrive/2009/12/blender-nuke/

Hi jason7,

I didn’t find any script other than from this thread, before I started learning about field-of-view/angle-of-view, focal-length, aperture-size, virtual-cameras, etc. I justed looked at the script you link to, and I recognize it as the Ter2Blend script by Bartius Crouch. It is for Blender 2.4x and not 2.5x, and if you look at the vfov-formula, it will not match between Blender and Nuke (don’t know why/how he thinks it works perfectly). This is why I posted these modified scripts here, because for a 99% match, the vfov-formula had to be changed. It is also essential to use a correct focal2fov calculation (with BLenses for example), or else it will not match since the values in Blenders default camera are useless, and the vfov calculation in the original Ter2Blend script uses some hardcoded values.

For this script (my adaption) to work better, the camera in Blender need to change. I’m working on a sort of proposal and will post it for debate, because Blender should really have a first class Camera, not what it is now.

I completely agree with you on blender cameras. They are the most basic i have seen in any 3d program. It has worked until now because it was used for plain 3d but for live action it is incomplete.

I would like to see your proposal and test any other things you come up with. This is very important.

Thanks.

Just to clarify things, the Terragen2 script did indeed not work correctly. I came across slight errors exporting from terragen to blender and the other way round as well. It was never even tested with Nuke. Not to mention that I was way in over my head, and didn’t know what I was doing ;). The code is amateuristic at best.

Hola Crouch!

If it was not for your script, I would have nothing to start from and I would be at a complete loss. You call it amateuristic but me being an absolute Python newbie have learned a lot from it! I did have to work on the math, but otherwise the script is almost untouched. So thank you! :slight_smile:

Hi!
I know that it’s while ago last reply, but is there any chance to update the script?