Page MenuHome

io_export_chan.py

File Metadata

Author
Michael Krupa (kroopson)
Created
Nov 13 2013, 3:07 PM

io_export_chan.py

# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
"name": "Export animation to nuke (.chan)",
"author": "Michael Krupa",
"version": (0, 9),
"blender": (2, 5, 9),
"api": 36079,
"location": "File > Export > Nuke (.chan)",
"description": "Export object's animation to nuke",
"warning": "Might be buggy",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
"Scripts/Import-Export/PC2_Pointcache_export",
"tracker_url": "https://projects.blender.org/tracker/index.php?"\
"func=detail&aid=24703",
"category": "Import-Export"}
""" This script is an exporter to the nuke's .chan files. It takes the currently active object and writes it's transformation data
into a text file with .chan extension."""
import bpy
from mathutils import Matrix
from mathutils import Euler
from math import radians
from math import degrees
from math import atan
from math import tan
def saveChan(context, filepath, Yup, rotOrd):
#check if we have anything selected, if not, finish without doing anything.
if not bpy.context.active_object:
return {'FINISHED'}
#get the active object
obj = bpy.context.active_object
#get the range of an animation
fStart = bpy.context.scene.frame_start
fEnd = bpy.context.scene.frame_end
#get the resolution (needed by nuke)
resX = bpy.context.scene.render.resolution_x
resY = bpy.context.scene.render.resolution_y
resRatio = float(resY) / float(resX)
#prepare the correcting matrix
rotMat = Matrix.Rotation(radians(-90), 4, "X").to_4x4()
f = open(filepath, 'w')
for a in range(fStart, fEnd, 1):
#reset the new line of a chan file
export_string = ""
#set the current frame
bpy.context.scene.frame_set(a)
#get the objects world matrix
mat = Matrix(obj.matrix_world)
#if the setting is proper use the rotation matrix to flip the Z and Y axis
if Yup:
mat = rotMat * mat
#create the first component of a new line, the frame number
export_string += "%i\t" % a
#create transform component
t = mat.to_translation()
export_string += "%f\t%f\t%f\t" % (t[0], t[1], t[2])
#create rotation component
r = mat.to_euler(rotOrd)
#export_string += "%f\t%f\t%f\t" % (r[0], r[1], r[2])
export_string += "%f\t%f\t%f\t" % (degrees(r[0]), degrees(r[1]), degrees(r[2]))
#if we have a camera, add the focal length
if obj.type == 'CAMERA':
export_string += "%f\n" % degrees(2 * atan(tan((obj.data.angle / 2.0) * resRatio)))
#print(degrees( tan(radians( obj.data.angle / 2.0 ))))
#math.degrees(2 * math.atan( math.tan(math.radians(45.0)) * .5 ))
#when all is set and done write the new line
f.write(export_string)
#after the whole loop close the file
f.close()
return {'FINISHED'}
from bpy_extras.io_utils import ExportHelper
from bpy.props import StringProperty, BoolProperty, EnumProperty
class ExportChan(bpy.types.Operator, ExportHelper):
'''Export the animation to .chan file, readable by nuke and houdini. The exporter uses frames from the frames range.'''
bl_idname = "export.export_chan"
bl_label = "Export chan file"
filename_ext = ".chan"
filter_glob = StringProperty(default="*.chan", options={'HIDDEN'})
Yup = BoolProperty(name="Make Y up", description="Switch the Y and Z axis.", default=True)
rotOrd = EnumProperty(items=(('XYZ', "XYZ", "XYZ"),
('XZY', "XZY", "XZY"),
('YXZ', "YXZ", "YXZ"),
('YZX', "YZX", "YZX"),
('ZXY', "ZXY", "ZXY"),
('ZYX', "ZYX", "ZYX"),
),
name="Rotation order",
description="Choose the export rotation order",
default='XYZ')
settings = {"Yup":Yup, "rotOrd":rotOrd}
@classmethod
def poll(cls, context):
return context.active_object != None
def execute(self, context):
return saveChan(context, self.filepath, self.Yup, self.rotOrd)
# Only needed if you want to add into a dynamic menu
def menu_func_export(self, context):
self.layout.operator(ExportChan.bl_idname, text="Nuke (.chan)")
def register():
bpy.utils.register_class(ExportChan)
bpy.types.INFO_MT_file_export.append(menu_func_export)
def unregister():
bpy.utils.unregister_class(ExportChan)
bpy.types.INFO_MT_file_export.remove(menu_func_export)
if __name__ == "__main__":
register()

Event Timeline