Page MenuHome

io_import_chan.py

File Metadata

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

io_import_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": "Import animation from chan file (.chan)",
"author": "Michael Krupa",
"version": (1, 0),
"blender": (2, 6, 0),
"api": 36079,
"location": "File > Import > Nuke (.chan)",
"description": "Import object's animation from nuke",
"warning": "",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
"Scripts/Import-Export/Nuke",
"tracker_url": "http://projects.blender.org/tracker/index.php?"\
"func=detail&atid=467&aid=28368&group_id=153",
"category": "Import-Export"}
""" This script is an importer for the nuke's .chan files"""
import bpy
from mathutils import Matrix
from mathutils import Euler
from mathutils import Vector
from math import radians
from math import degrees
from math import atan
from math import tan
def read_chan(context, filepath, Zup, 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 resolution (needed to calculate the camera lens)
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()
#read the file
f = open(filepath, 'r')
#iterate throug the files lines
for line in f.readlines():
#reset the target objects matrix
#(the one from whitch one we'll extract the final transforms)
mTransMat = Matrix()
mTransMat.to_4x4()
#strip the line
data = line.split()
#test if the line is not commented out
if data[0] != "#":
#set the frame number basing on the chan file
bpy.context.scene.frame_set(int(data[0]))
#read the translation values basing on the
vTransl = Vector([float(data[1]), float(data[2]), float(data[3])])
mTranslMat = Matrix.Translation(vTransl)
mTranslMat.to_4x4()
#read the rotations, and set the rotation order basing on the order
#set during the export
eRot = Euler([radians(float(data[4])),
radians(float(data[5])),
radians(float(data[6]))])
eRot.order = rotOrd
mRotMat = eRot.to_matrix()
mRotMat.resize_4x4()
#merge the rotation and translation
mTransMat = mTranslMat * mRotMat
#correct the world space
#(nuke's and blenders scene spaces are different)
if Zup:
mTransMat = rotMat * mTransMat
#break the matrix into a set of the coordinates
trns = mTransMat.decompose()
#set the location and the location's keyframe
obj.location = trns[0]
obj.keyframe_insert('location')
#convert the rotation to euler angles (or not)
#basing on the objects rotation mode
if obj.rotation_mode != "QUATERNION":
obj.rotation_euler = trns[1].to_euler(obj.rotation_mode)
obj.keyframe_insert('rotation_euler')
else:
obj.rotation_euler = trns[1]
obj.keyframe_insert('rotation_quaternion')
#if the target object is camera test for the vfov data. If present,
#calculate the horizontal angle and set the keyframe on camera lens
if obj.data.type == "PERSP":
if len(data) > 7:
print(data[7])
vFov = float(data[7])
hFov = atan(1 / (resRatio / tan(radians(vFov))))
obj.data.angle = hFov
obj.data.keyframe_insert('lens')
f.close()
return {'FINISHED'}
from bpy_extras.io_utils import ImportHelper
from bpy.props import StringProperty, BoolProperty, EnumProperty
class ImportChan(bpy.types.Operator, ImportHelper):
'''Import animation from .chan file, exported from nuke or houdini.
The importer uses frame numbers from the file.'''
bl_idname = "import_scene.import_chan"
bl_label = "Import chan file"
filename_ext = ".chan"
filter_glob = StringProperty(default="*.chan", options={'HIDDEN'})
Zup = BoolProperty(name="Make Z 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 rotation order with whitch \
the chan has been made",
default='XYZ')
@classmethod
def poll(cls, context):
return context.active_object != None
def execute(self, context):
return read_chan(context, self.filepath, self.Zup, self.rotOrd)
def menu_func_import(self, context):
self.layout.operator(ImportChan.bl_idname, text="Nuke (.chan)")
def register():
bpy.utils.register_class(ImportChan)
bpy.types.INFO_MT_file_import.append(menu_func_import)
def unregister():
bpy.utils.unregister_class(ImportChan)
bpy.types.INFO_MT_file_import.remove(menu_func_import)
if __name__ == "__main__":
register()
bpy.ops.import_scene.import_chan('INVOKE_DEFAULT')

Event Timeline