Last active
January 19, 2024 09:37
-
-
Save p2or/5560c142fcb14716c6ac490a1d9bfb6e to your computer and use it in GitHub Desktop.
Export Camera to BMD Fusion [Blender 2.8x] from https://blenderartists.org/t/addon-export-camera-to-bmd-fusion #BlenderArtists
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ##### 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 Fusion Composition", | |
| "author": "Michael Vorberg, Christian Brinkmann", | |
| "version": (0, 6, 0), | |
| "blender": (2, 80, 0), | |
| "location": "File > Export > Fusion Comp (.comp)", | |
| "description": "Export Cameras and PointClouds of motion tracking into a Fusion Composition(.comp)", | |
| "warning": "", | |
| "category": "Import-Export", | |
| } | |
| import bpy | |
| from bpy_extras.io_utils import ExportHelper, axis_conversion | |
| import math | |
| import mathutils | |
| import os | |
| def write_cameras(context, filepath, frame_start, frame_end, only_selected=False): | |
| data_attrs = ( | |
| 'lens', | |
| 'shift_x', | |
| 'shift_y', | |
| 'dof_distance', | |
| 'clip_start', | |
| 'clip_end', | |
| 'draw_size', | |
| ) | |
| scene = context.scene | |
| bl_display_colorspace = scene.display_settings.display_device | |
| #print (bl_display_colorspace) | |
| fu_display_colorspace = "" | |
| try: | |
| if bl_display_colorspace == "sRGB": | |
| fu_display_colorspace = "sRGB" | |
| elif bl_display_colorspace == "Rec709": | |
| fu_display_colorspace = "Rec709Display" | |
| elif bl_display_colorspace == "XYZ": | |
| fu_display_colorspace = "DCI" | |
| elif bl_display_colorspace == "None": | |
| fu_display_colorspace = "No Change" | |
| elif bl_display_colorspace == "Filmic": | |
| fu_display_colorspace = "" | |
| elif bl_display_colorspace == "sRGB / BT.709": | |
| fu_display_colorspace = "sRGB" | |
| except: | |
| fu_display_colorspace = "" | |
| rot_x_neg90 = mathutils.Matrix.Rotation(-math.pi/2.0, 4, 'X') | |
| obj_attrs = ( | |
| 'hide_render', | |
| ) | |
| with open(filepath, "w") as fw: | |
| cameras = [] | |
| for obj in scene.objects: | |
| if only_selected and not obj.select_get(): | |
| continue | |
| if obj.type != 'CAMERA': | |
| continue | |
| cameras.append((obj, obj.data)) | |
| if len(cameras) == 0: | |
| raise RuntimeError("no camera selected but \"only selected\" activated") | |
| # write some settings for the composition | |
| frame_range = range(frame_start, frame_end + 1) | |
| fw.write("Composition {\n" | |
| " CurrentTime = 0,\n") | |
| fw.write(" RenderRange = { %d, %d, },\n"%(frame_start, frame_end)) | |
| fw.write(" GlobalRange = { %d, %d, },\n"%(frame_start, frame_end)) | |
| fw.write("""Prefs = { | |
| Comp = { | |
| Views = { | |
| Right = { | |
| Viewer = { | |
| EnableLUTs = true, | |
| LUTPlugin = "GamutViewLUT", | |
| LUTSelected = "Gamut View LUT", | |
| }, | |
| ViewLUT = { | |
| { | |
| Tools = ordered() { | |
| GamutViewLUT1 = ViewOperator { | |
| CtrlWZoom = false, | |
| NameSet = true, | |
| Inputs = {""") | |
| fw.write(" OutputSpace = Input { Value = FuID { \"%s\", }, },"%fu_display_colorspace) | |
| fw.write(""" }, | |
| }, | |
| }, | |
| ID = "GamutViewLUT", | |
| }, | |
| SelectedPlugin = "GamutViewLUT", | |
| SelectedName = "Gamut View LUT", | |
| }, | |
| }, | |
| Left = { | |
| Viewer = { | |
| EnableLUTs = true, | |
| LUTPlugin = "GamutViewLUT", | |
| LUTSelected = "Gamut View LUT", | |
| }, | |
| ViewLUT = { | |
| { | |
| Tools = ordered() { | |
| GamutViewLUT = ViewOperator { | |
| CtrlWZoom = false, | |
| NameSet = true, | |
| Inputs = {""") | |
| fw.write(" OutputSpace = Input { Value = FuID { \"%s\", }, },"%fu_display_colorspace) | |
| fw.write(""" }, | |
| }, | |
| }, | |
| ID = "GamutViewLUT", | |
| }, | |
| SelectedPlugin = "GamutViewLUT", | |
| SelectedName = "Gamut View LUT", | |
| }, | |
| }, | |
| View1 = { | |
| }, | |
| }, | |
| FrameFormat = { | |
| Name = "Multimedia", """) | |
| fw.write("Width = %d,\n"%(scene.render.resolution_x)) | |
| fw.write("Height = %d,\n"%(scene.render.resolution_y)) | |
| fw.write("Rate = %d,\n"%(scene.render.fps)) | |
| fw.write("""PerFeet = 1, | |
| GuideRatio = 1.77777777777778, | |
| }, | |
| }, | |
| Views = { | |
| Right = { | |
| SideB = { | |
| PrevCtrlInactiveColor = 65280, | |
| PickW = 1, | |
| PickH = 1, | |
| PrevCtrlActiveColor = 255, | |
| Viewer = { | |
| EnableLUTs = false, | |
| LUTPlugin = "FusionViewLUT", | |
| FitMarginY = 0, | |
| FitMarginX = 0, | |
| FitMarginType = 0, | |
| FarZ = -1000, | |
| NearZ = 0, | |
| }, | |
| }, | |
| Viewer = { | |
| EnableLUTs = true, | |
| LUTPlugin = "GamutViewLUT", | |
| LUTSelected = "Gamut View LUT", | |
| }, | |
| ViewLUT = { | |
| { | |
| Tools = ordered() { | |
| GamutViewLUT1 = ViewOperator { | |
| NameSet = true, | |
| Inputs = {""") | |
| fw.write(" OutputSpace = Input { Value = FuID { \"%s\", }, },"%fu_display_colorspace) | |
| fw.write(""" }, | |
| CtrlWZoom = false, | |
| }, | |
| }, | |
| ID = "GamutViewLUT", | |
| }, | |
| Recent = { | |
| SelectedPlugin = "GamutViewLUT", | |
| FusionViewLUT = { | |
| Tools = ordered() { | |
| FusionViewLUT = ViewLUTOp { | |
| NameSet = true, | |
| Inputs = { | |
| }, | |
| }, | |
| }, | |
| }, | |
| SelectedName = "Gamut View LUT", | |
| }, | |
| SelectedName = "Gamut View LUT", | |
| SelectedPlugin = "GamutViewLUT", | |
| }, | |
| }, | |
| Left = { | |
| SideB = { | |
| PrevCtrlInactiveColor = 65280, | |
| PickW = 1, | |
| PickH = 1, | |
| PrevCtrlActiveColor = 255, | |
| Viewer = { | |
| EnableLUTs = false, | |
| LUTPlugin = "FusionViewLUT", | |
| FitMarginY = 0, | |
| FitMarginX = 0, | |
| FitMarginType = 0, | |
| FarZ = -1000, | |
| NearZ = 0, | |
| }, | |
| }, | |
| Viewer = { | |
| EnableLUTs = true, | |
| LUTPlugin = "GamutViewLUT", | |
| LUTSelected = "Gamut View LUT", | |
| }, | |
| ViewLUT = { | |
| { | |
| Tools = ordered() { | |
| GamutViewLUT = ViewOperator { | |
| NameSet = true, | |
| Inputs = {""") | |
| fw.write(" OutputSpace = Input { Value = FuID { \"%s\", }, },"%fu_display_colorspace) | |
| fw.write(""" }, | |
| CtrlWZoom = false, | |
| }, | |
| }, | |
| ID = "GamutViewLUT", | |
| }, | |
| SelectedPlugin = "GamutViewLUT", | |
| SelectedName = "Gamut View LUT", | |
| }, | |
| }, | |
| View1 = { | |
| PrevCtrlInactiveColor = 0, | |
| PickW = 1, | |
| PickH = 1, | |
| PrevCtrlActiveColor = 0, | |
| SideB = { | |
| PrevCtrlInactiveColor = 65280, | |
| PickW = 1, | |
| PickH = 1, | |
| PrevCtrlActiveColor = 255, | |
| Viewer = { | |
| EnableLUTs = false, | |
| LUTPlugin = "FusionViewLUT", | |
| FitMarginY = 0, | |
| FitMarginX = 0, | |
| FitMarginType = 0, | |
| FarZ = -1000, | |
| NearZ = 0, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| """) | |
| # starting with the actual nodes | |
| fw.write("Tools = {\n") | |
| # look if we have a clip in the scene and create a loader node for it | |
| try: | |
| if bpy.data.movieclips[0]: | |
| fw.write("""Loader1 = Loader { | |
| Clips = { | |
| Clip { | |
| ID = "Clip1",\n""") | |
| clip_filepath = os.path.normpath(bpy.data.movieclips[0].filepath) | |
| clip_filepath_four_slashes = clip_filepath.replace("\\", "\\\\") | |
| fw.write("Filename = \" %s \",\n"%(clip_filepath_four_slashes)) | |
| fw.write("StartFrame = %d,\n"%(frame_start)) | |
| fw.write("Length = %d,\n"%(frame_end)) | |
| fw.write("LengthSetManually = true,\n") | |
| fw.write("TrimIn = %d,\n"%(frame_start-1)) | |
| fw.write("TrimOut = %d,\n"%(frame_end-1)) | |
| fw.write("""ExtendFirst = 0, | |
| ExtendLast = 0, | |
| Loop = 1, | |
| AspectMode = 0, | |
| Depth = 0, | |
| TimeCode = 0,""") | |
| fw.write("GlobalStart = %d,\n"%(frame_start)) | |
| fw.write("GlobalEnd = %d,\n"%(frame_end)) | |
| fw.write("""}, | |
| }, | |
| ViewInfo = OperatorInfo { Pos = { 300, 0, }, }, | |
| CtrlWZoom = false, | |
| }, | |
| Gamut1 = GamutConvert { | |
| Inputs = { | |
| SourceSpace = Input { Value = FuID { "sRGB", }, }, | |
| Input = Input { | |
| SourceOp = "Loader1", | |
| Source = "Output", | |
| }, | |
| }, | |
| ViewInfo = OperatorInfo { Pos = { 300, 100, }, }, | |
| },""") | |
| except: | |
| print("No clip found for Loader") | |
| # create Camera3D nodes | |
| try: | |
| for obj, obj_data in cameras: | |
| fw.write(" Camera3D_%s = Camera3D {\n" %obj_data.name.replace(".", "_").replace(".", "_")) | |
| fw.write(" CtrlWZoom = false,\n" | |
| " Inputs = {\n" | |
| " [\"PerspNearClip\"] = Input {\n" | |
| " SourceOp = \"Camera3D_%s_PerspNearClip\",\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" Source = \"Value\",\n" | |
| " },\n" | |
| " [\"PerspFarClip\"] = Input {\n" | |
| " SourceOp = \"Camera3D_%s_PerspFarClip\",\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" Source = \"Value\",\n" | |
| " },\n" | |
| " [\"FLength\"] = Input {\n" | |
| " SourceOp = \"Camera3D_%s_LensFlength\",\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" Source = \"Value\",\n" | |
| " },\n" | |
| " [\"PlaneOfFocus\"] = Input {\n" | |
| " SourceOp = \"Camera3D_%s_PlaneOfFocus\",\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" Source = \"Value\",\n" | |
| " },\n" | |
| " [\"Transform3DOp.Translate.X\"] = Input {\n" | |
| " SourceOp = \"Camera3D_%s_XOffset\",\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" Source = \"Value\",\n" | |
| " },\n" | |
| " [\"Transform3DOp.Translate.Y\"] = Input {\n" | |
| " SourceOp = \"Camera3D_%s_YOffset\",\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" Source = \"Value\",\n" | |
| " },\n" | |
| " [\"Transform3DOp.Translate.Z\"] = Input {\n" | |
| " SourceOp = \"Camera3D_%s_ZOffset\",\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" Source = \"Value\",\n") | |
| fw.write(" },\n" | |
| " [\"Transform3DOp.Rotate.X\"] = Input {\n" | |
| " SourceOp = \"Camera3D_%s_XRotation\",\n"%obj_data.name.replace(".", "_")) | |
| fw.write(" Source = \"Value\",\n") | |
| fw.write(" },\n" | |
| " [\"Transform3DOp.Rotate.Y\"] = Input {\n" | |
| " SourceOp = \"Camera3D_%s_YRotation\",\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" Source = \"Value\",\n") | |
| fw.write(" },\n" | |
| " [\"Transform3DOp.Rotate.Z\"] = Input {\n" | |
| " SourceOp = \"Camera3D_%s_ZRotation\",\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" Source = \"Value\",\n") | |
| fw.write(" },\n") | |
| fw.write(" [\"Stereo.Mode\"] = Input { Value = FuID { \"Mono\", }, },\n" | |
| " FilmBack = Input { Value = 1, },\n" | |
| " FilmGate = Input { Value = FuID { \"User\", }, },\n") | |
| fw.write(" LensShiftX = Input { Value = %r, },\n" %(-obj_data.shift_x)) | |
| fw.write(" LensShiftY = Input { Value = %r, },\n" %(-obj_data.shift_y*(scene.render.resolution_x/scene.render.resolution_y))) | |
| ap_w = float(obj_data.sensor_width) / 25.4 | |
| fw.write(" ApertureW = Input { Value = %s, },\n" %str(ap_w)) | |
| ap_h = ap_w/(scene.render.resolution_x/scene.render.resolution_y) | |
| fw.write(" ApertureH = Input { Value = %s, },\n" %str(ap_h)) | |
| if obj_data.sensor_fit == "HORIZONTAL": | |
| fw.write(" AovType = Input { Value = 1, },\n") | |
| if obj_data.sensor_fit == "VERTICAL": | |
| fw.write(" AovType = Input { Value = 0, },\n") | |
| fw.write(''' [\"SurfacePlaneInputs.ObjectID.ObjectID\"] = Input { Value = 1, },\n | |
| [\"MtlStdInputs.MaterialID\"] = Input { Value = 1, },\n | |
| },\n | |
| ViewInfo = OperatorInfo { Pos = { 0, 100, }, }, | |
| },\n''' | |
| ) | |
| fw.write(" Camera3D_%s_XOffset = BezierSpline {\n" %obj_data.name.replace(".", "_")) | |
| fw.write(''' NameSet = true,\n | |
| KeyFrames = {\n''') | |
| # X Translation | |
| for f in frame_range: | |
| scene.frame_set(f) | |
| matrix = obj.matrix_world.copy() | |
| fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, matrix.to_translation()[0])) | |
| fw.write(" },\n" | |
| "},\n") | |
| # Y Translation (Fusion Y) | |
| fw.write(" Camera3D_%s_YOffset = BezierSpline {\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" NameSet = true,\n" | |
| " KeyFrames = {\n") | |
| for f in frame_range: | |
| scene.frame_set(f) | |
| matrix = obj.matrix_world.copy() | |
| fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, matrix.to_translation()[2])) | |
| fw.write(" },\n" | |
| "},\n") | |
| # Z Translation (Fusion Z) | |
| fw.write(" Camera3D_%s_ZOffset = BezierSpline {\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" NameSet = true,\n" | |
| " KeyFrames = {\n") | |
| for f in frame_range: | |
| scene.frame_set(f) | |
| matrix = obj.matrix_world.copy() | |
| fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, -matrix.to_translation()[1])) | |
| fw.write(" },\n" | |
| "},\n") | |
| # X Rotation (Fusion X) | |
| fw.write(" Camera3D_%s_XRotation = BezierSpline {\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" NameSet = true,\n" | |
| " KeyFrames = {\n") | |
| for f in frame_range: | |
| scene.frame_set(f) | |
| matrix_org = obj.matrix_world.copy() | |
| matrix = rot_x_neg90 * matrix_org | |
| fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, (math.degrees(matrix.to_euler()[0])))) | |
| fw.write(" },\n" | |
| "},\n") | |
| # Y Rotation (Fusion Y) | |
| fw.write(" Camera3D_%s_YRotation = BezierSpline {\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" NameSet = true,\n" | |
| " KeyFrames = {\n") | |
| for f in frame_range: | |
| scene.frame_set(f) | |
| matrix_org = obj.matrix_world.copy() | |
| matrix = rot_x_neg90 * matrix_org | |
| fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, math.degrees(matrix.to_euler()[1]))) | |
| fw.write(" },\n" | |
| "},\n") | |
| # Z Rotation (Fusion Z) | |
| fw.write(" Camera3D_%s_ZRotation = BezierSpline {\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" NameSet = true,\n" | |
| " KeyFrames = {\n") | |
| for f in frame_range: | |
| scene.frame_set(f) | |
| matrix_org = obj.matrix_world.copy() | |
| matrix = rot_x_neg90 * matrix_org | |
| fw.write(" [%d] = { %r, Flags = { Linear = true, }, },\n" %(f, math.degrees(matrix.to_euler()[2]))) | |
| fw.write(" },\n" | |
| "},\n") | |
| fw.write(" Camera3D_%s_LensFlength = BezierSpline {\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" NameSet = true,\n" | |
| " KeyFrames = {\n") | |
| for f in frame_range: | |
| scene.frame_set(f) | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, obj_data.lens)) | |
| fw.write(" },\n" | |
| "},\n") | |
| fw.write(" Camera3D_%s_PlaneOfFocus = BezierSpline {\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" NameSet = true,\n" | |
| " KeyFrames = {\n") | |
| for f in frame_range: | |
| scene.frame_set(f) | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, obj_data.dof_distance)) | |
| fw.write(" },\n" | |
| "},\n") | |
| fw.write(" Camera3D_%s_PerspNearClip = BezierSpline {\n" %obj_data.name.replace(".", "_")) | |
| fw.write(" NameSet = true,\n" | |
| " KeyFrames = {\n") | |
| for f in frame_range: | |
| scene.frame_set(f) | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, obj_data.clip_start)) | |
| fw.write(" },\n" | |
| "},\n") | |
| fw.write(" Camera3D_%s_PerspFarClip = BezierSpline {\n" %obj_data.name.replace(".", "_")) | |
| fw.write(''' NameSet = true,\n | |
| KeyFrames = {\n''') | |
| for f in frame_range: | |
| scene.frame_set(f) | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, obj_data.clip_end)) | |
| fw.write(''' },\n | |
| },\n''') | |
| obj.select_set(False) | |
| except: | |
| print("No camera found/selected") | |
| # write pointcloud3D node | |
| # look if we have a clip in the scene | |
| try: | |
| if bpy.data.movieclips[0]: | |
| fw.write(''' | |
| PointCloud3D1 = PointCloud3D {\n | |
| CtrlWZoom = false,\n | |
| ViewInfo = OperatorInfo { Pos = { 150, 0, }, },\n | |
| Positions = {\n | |
| Version = 0,\n | |
| ''') | |
| curr_clip = bpy.data.movieclips[0] | |
| zeroPosition = [0, 0, 0] | |
| sceneCamera = bpy.data.objects['Camera'] | |
| track_list = [] | |
| for track in curr_clip.tracking.tracks: | |
| if track.has_bundle is False: | |
| continue | |
| track_list.append(track) | |
| for track in track_list: | |
| track_name = track.name | |
| bpy.ops.object.add(type='EMPTY',location = [0, 0, 0]) | |
| current_obj = context.active_object | |
| bpy.ops.object.constraint_add(type="FOLLOW_TRACK") | |
| context.object.constraints["Follow Track"].use_3d_position = True | |
| context.object.constraints["Follow Track"].object = "Camera" | |
| context.object.constraints["Follow Track"].track = track_name | |
| context.object.constraints["Follow Track"].camera = sceneCamera | |
| current_obj_data = bpy.data.objects[current_obj.name] | |
| current_obj_data.name = track_name | |
| print ("created object: ", current_obj_data.name) | |
| i = 0 | |
| for track in track_list: | |
| track_name = track.name | |
| current_obj = context.active_object | |
| current_obj_data = bpy.data.objects[track_name] | |
| obj_name_matrix = current_obj_data.matrix_world.copy() | |
| fw.write( | |
| "[%d] = { %r, %r, %r, \"%s\", \"\", },\n" % ( | |
| i, obj_name_matrix.to_translation()[0], | |
| obj_name_matrix.to_translation()[2], | |
| -obj_name_matrix.to_translation()[1], | |
| track_name | |
| ) | |
| ) | |
| i += 1 | |
| current_obj_data.select_set(True) | |
| # delete all helper tracks | |
| bpy.ops.object.delete(use_global=False) | |
| # close pointcloud3D and create Merge3D | |
| fw.write(''' },\n | |
| },\n | |
| Merge3D1 = Merge3D { | |
| Inputs = { | |
| SceneInput1 = Input {''') | |
| try: | |
| if not obj_data.name: | |
| fw.write("SourceOp = \"Camera3D_%s\",\n" % obj_data.name.replace(".", "_").replace(".", "_")) | |
| else: | |
| fw.write("SourceOp = \"\",\n") | |
| except: | |
| raise RuntimeError("no camera selected") | |
| fw.write('''Source = \"Output\", | |
| }, | |
| SceneInput2 = Input { | |
| SourceOp = \"PointCloud3D1\", | |
| Source = \"Output\", | |
| }, | |
| }, | |
| ViewInfo = OperatorInfo { Pos = { 151, 100, }, }, | |
| },''') | |
| except: | |
| print("No clip found") | |
| try: | |
| if bpy.data.movieclips[0]: | |
| #create2d trackers | |
| print ("trying 2d tracks") | |
| curr_clip = bpy.data.movieclips[0] | |
| track_list = [] | |
| for track in curr_clip.tracking.tracks: | |
| if track.has_bundle is False: | |
| continue | |
| track_list.append(track) | |
| fw.write(""" | |
| Tracker1 = Tracker { | |
| Trackers = { | |
| """) | |
| for track in track_list: | |
| track_name = track.name.replace(".", "_") | |
| track_name_orig = track.name | |
| fw.write("""{ | |
| PatternTime = 1, | |
| PatternX = 0.392840626111704, | |
| PatternY = 0.699857685009488, | |
| },""") | |
| fw.write("""}, | |
| CtrlWZoom = false, | |
| Inputs = {TrackerList = Input { Value = 1, },""") | |
| i = 0 | |
| for track in track_list: | |
| track_name = track.name.replace(".", "_") | |
| track_name_orig = track.name | |
| i += 1 | |
| fw.write("Name%d = Input { Value = \"%s\", }," %(i, track_name)) | |
| fw.write("PatternCenter%d = Input { Value = { %r, %r, }, },"% ( | |
| i, bpy.data.movieclips[0].tracking.tracks[track_name_orig].markers[0].co.x, | |
| bpy.data.movieclips[0].tracking.tracks[track_name_orig].markers[0].co.y) | |
| ) | |
| fw.write("PatternWidth%d = Input { Value = 0.0154571326929918, },"%i) | |
| fw.write("PatternHeight%d = Input { Value = 0.020841239721695, },"%i) | |
| fw.write("SearchWidth%d = Input { Value = 0.0574350764852365, },"%i) | |
| fw.write("SearchHeight%d = Input { Value = 0.0714421252371915, }," %i) | |
| fw.write("TrackedCenter%d = Input {" %i) | |
| fw.write("SourceOp = \"Tracker1%sXYPath\"," %track_name) | |
| fw.write("""Source = "Value", | |
| }, | |
| """) | |
| fw.write("""},\n ViewInfo = OperatorInfo { Pos = { 500, 0, }, }, | |
| },""") | |
| for track in track_list: | |
| track_name = track.name.replace(".", "_") | |
| track_name_orig = track.name | |
| print ("creating animation for 2d tracker: ", track_name) | |
| fw.write("Tracker1%sXYPath = XYPath {" %track_name) | |
| fw.write("""ShowKeyPoints = false, | |
| DrawMode = "ModifyOnly", | |
| CtrlWZoom = false, | |
| NameSet = true, | |
| Inputs = { | |
| X = Input {""") | |
| fw.write("SourceOp = \"XYPath_%sX\"," %track_name) | |
| fw.write("""Source = "Value", | |
| }, | |
| Y = Input {""") | |
| fw.write("SourceOp = \"XYPath_%sY\"," %track_name) | |
| fw.write("""Source = "Value", | |
| }, | |
| }, | |
| }, | |
| """) | |
| fw.write("XYPath_%sX = BezierSpline {" %track_name) | |
| fw.write("""SplineColor = { Red = 255, Green = 0, Blue = 0, }, | |
| NameSet = true, | |
| KeyFrames = { | |
| """) | |
| for f in frame_range: | |
| marker_at_frame = bpy.data.movieclips[0].tracking.tracks[track_name_orig].markers.find_frame(f) | |
| if not marker_at_frame: | |
| continue | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, marker_at_frame.co.x)) | |
| fw.write(""" },\n | |
| },\n""") | |
| fw.write("XYPath_%sY = BezierSpline {" %track_name) | |
| fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, }, | |
| NameSet = true, | |
| KeyFrames = { | |
| """) | |
| for f in frame_range: | |
| marker_at_frame = bpy.data.movieclips[0].tracking.tracks[track_name_orig].markers.find_frame(f) | |
| if not marker_at_frame: | |
| continue | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(f, marker_at_frame.co.y)) | |
| fw.write(""" },\n | |
| },\n""") | |
| #create lens distortion node | |
| fw.write("""LensDistort1 = LensDistort { | |
| CtrlWZoom = false, | |
| Inputs = { | |
| LensDistortionModel = Input { Value = 1, }, | |
| Model = Input { Value = FuID { "PFTrack", }, },\n""") | |
| fw.write("[\"PFTrack.LowOrderDistortion\"] = Input { Value = %r, },\n" %-bpy.data.movieclips[0].tracking.camera.k1) | |
| fw.write("[\"PFTrack.HighOrderDistortion\"] = Input { Value = %r, },\n" %-bpy.data.movieclips[0].tracking.camera.k2) | |
| fw.write("[\"PFTrack.LensCenterX\"] = Input { Value = %r, },\n" % (bpy.data.movieclips[0].tracking.camera.principal[0]/bpy.data.movieclips[0].size[0])) | |
| fw.write("[\"PFTrack.LensCenterY\"] = Input { Value = %r, },\n" %(bpy.data.movieclips[0].tracking.camera.principal[1]/bpy.data.movieclips[0].size[1])) | |
| fw.write("""}, | |
| ViewInfo = OperatorInfo { Pos = { 700, 0, }, }, | |
| }, | |
| """) | |
| except: | |
| print("No clip found") | |
| try: | |
| if bpy.data.movieclips[0]: | |
| curr_clip = bpy.data.movieclips[0] | |
| plane_track_list = [] | |
| for plane_track in curr_clip.tracking.plane_tracks: | |
| plane_track_list.append(plane_track) | |
| if len(plane_track_list)>0: | |
| for i,track in enumerate(plane_track_list): | |
| track_name = track.name.replace(".", "_") | |
| track_name_orig = track.name | |
| fw.write("CornerPositioner%d = CornerPositioner {" %i) | |
| fw.write('''Inputs = { | |
| TopLeft = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack1XYPath\"," %i) | |
| fw.write('''Source = "Value", | |
| }, | |
| TopRight = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack2XYPath\"," %i) | |
| fw.write('''Source = "Value", | |
| }, | |
| BottomLeft = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack3XYPath\"," %i) | |
| fw.write('''Source = "Value", | |
| }, | |
| BottomRight = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack4XYPath\"," %i) | |
| fw.write('''Source = "Value", | |
| }, | |
| },''') | |
| toolPos = 900+i*100 | |
| fw.write("ViewInfo = OperatorInfo { Pos = { %d, 0, }, }," %toolPos) | |
| fw.write('''},''') | |
| fw.write("PlaneTrack%dTrack1XYPath = XYPath {" %i) | |
| fw.write('''ShowKeyPoints = false, | |
| DrawMode = "InsertAndModify", | |
| NameSet = true, | |
| Inputs = { | |
| X = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack1XYPath%dX\"," %(i,i)) | |
| fw.write('''Source = "Value", | |
| }, | |
| Y = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack1XYPath%dY\"," %(i,i)) | |
| fw.write('''Source = "Value", | |
| }, | |
| }, | |
| },''') | |
| fw.write("PlaneTrack%dTrack2XYPath = XYPath {" %i) | |
| fw.write('''ShowKeyPoints = false, | |
| DrawMode = "InsertAndModify", | |
| NameSet = true, | |
| Inputs = { | |
| X = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack2XYPath%dX\"," %(i,i)) | |
| fw.write('''Source = "Value", | |
| }, | |
| Y = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack2XYPath%dY\"," %(i,i)) | |
| fw.write('''Source = "Value", | |
| }, | |
| }, | |
| },''') | |
| fw.write("PlaneTrack%dTrack3XYPath = XYPath {" %i) | |
| fw.write('''ShowKeyPoints = false, | |
| DrawMode = "InsertAndModify", | |
| NameSet = true, | |
| Inputs = { | |
| X = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack3XYPath%dX\"," %(i,i)) | |
| fw.write('''Source = "Value", | |
| }, | |
| Y = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack3XYPath%dY\"," %(i,i)) | |
| fw.write('''Source = "Value", | |
| }, | |
| }, | |
| },''') | |
| fw.write("PlaneTrack%dTrack4XYPath = XYPath {" %i) | |
| fw.write('''ShowKeyPoints = false, | |
| DrawMode = "InsertAndModify", | |
| NameSet = true, | |
| Inputs = { | |
| X = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack4XYPath%dX\"," %(i,i)) | |
| fw.write('''Source = "Value", | |
| }, | |
| Y = Input {''') | |
| fw.write("SourceOp = \"PlaneTrack%dTrack4XYPath%dY\"," %(i,i)) | |
| fw.write('''Source = "Value", | |
| }, | |
| }, | |
| },''') | |
| fw.write("PlaneTrack%dTrack1XYPath%dX = BezierSpline {" %(i,i)) | |
| fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, }, | |
| NameSet = true, | |
| KeyFrames = { | |
| """) | |
| for j, marker in enumerate(track.markers): | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[3][0])) | |
| fw.write(""" },\n | |
| },\n""") | |
| fw.write("PlaneTrack%dTrack1XYPath%dY = BezierSpline {" %(i,i)) | |
| fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, }, | |
| NameSet = true, | |
| KeyFrames = { | |
| """) | |
| for j, marker in enumerate(track.markers): | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[3][1])) | |
| fw.write(""" },\n | |
| },\n""") | |
| fw.write("PlaneTrack%dTrack2XYPath%dX = BezierSpline {" %(i,i)) | |
| fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, }, | |
| NameSet = true, | |
| KeyFrames = { | |
| """) | |
| for j, marker in enumerate(track.markers): | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[2][0])) | |
| fw.write(""" },\n | |
| },\n""") | |
| fw.write("PlaneTrack%dTrack2XYPath%dY = BezierSpline {" %(i,i)) | |
| fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, }, | |
| NameSet = true, | |
| KeyFrames = { | |
| """) | |
| for j, marker in enumerate(track.markers): | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[2][1])) | |
| fw.write(""" },\n | |
| },\n""") | |
| fw.write("PlaneTrack%dTrack3XYPath%dX = BezierSpline {" %(i,i)) | |
| fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, }, | |
| NameSet = true, | |
| KeyFrames = { | |
| """) | |
| for j, marker in enumerate(track.markers): | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[0][0])) | |
| fw.write(""" },\n | |
| },\n""") | |
| fw.write("PlaneTrack%dTrack3XYPath%dY = BezierSpline {" %(i,i)) | |
| fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, }, | |
| NameSet = true, | |
| KeyFrames = { | |
| """) | |
| for j, marker in enumerate(track.markers): | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[0][1])) | |
| fw.write(""" },\n | |
| },\n""") | |
| fw.write("PlaneTrack%dTrack4XYPath%dX = BezierSpline {" %(i,i)) | |
| fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, }, | |
| NameSet = true, | |
| KeyFrames = { | |
| """) | |
| for j, marker in enumerate(track.markers): | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[1][0])) | |
| fw.write(""" },\n | |
| },\n""") | |
| fw.write("PlaneTrack%dTrack4XYPath%dY = BezierSpline {" %(i,i)) | |
| fw.write("""SplineColor = { Red = 0, Green = 255, Blue = 0, }, | |
| NameSet = true, | |
| KeyFrames = { | |
| """) | |
| for j, marker in enumerate(track.markers): | |
| fw.write(" [%d] = { %s, Flags = { Linear = true, }, },\n" %(j, marker.corners[1][1])) | |
| fw.write(""" },\n | |
| },\n""") | |
| fw.write(""" | |
| Tracker2 = Tracker { | |
| Trackers = { | |
| """) | |
| fw.write("""{ | |
| PatternTime = 1, | |
| PatternX = 0.392840626111704, | |
| PatternY = 0.699857685009488, | |
| },\n | |
| { | |
| PatternTime = 1, | |
| PatternX = 0.392840626111704, | |
| PatternY = 0.699857685009488, | |
| },\n | |
| { | |
| PatternTime = 1, | |
| PatternX = 0.392840626111704, | |
| PatternY = 0.699857685009488, | |
| },\n | |
| { | |
| PatternTime = 1, | |
| PatternX = 0.392840626111704, | |
| PatternY = 0.699857685009488, | |
| },\n | |
| """) | |
| fw.write("""}, | |
| CtrlWZoom = false, | |
| Inputs = {TrackerList = Input { Value = 2, },""") | |
| fw.write("Name1 = Input { Value = \"PlaneTrack1\", }," ) | |
| fw.write("PatternCenter1 = Input { Value = { %r, %r, }, },"%( marker.corners[0][0],marker.corners[0][1])) | |
| fw.write("PatternWidth1 = Input { Value = 0.0154571326929918, },") | |
| fw.write("PatternHeight1 = Input { Value = 0.020841239721695, },") | |
| fw.write("SearchWidth1 = Input { Value = 0.0574350764852365, },") | |
| fw.write("SearchHeight1 = Input { Value = 0.0714421252371915, },") | |
| fw.write("TrackedCenter1 = Input {" ) | |
| fw.write("SourceOp = \"PlaneTrack%dTrack1XYPath\"," %i) | |
| fw.write("""Source = "Value", | |
| }, | |
| """) | |
| fw.write("Name2 = Input { Value = \"PlaneTrack2\", }," ) | |
| fw.write("PatternCenter2 = Input { Value = { %r, %r, }, },"%( marker.corners[1][0],marker.corners[1][1])) | |
| fw.write("PatternWidth2 = Input { Value = 0.0154571326929918, },") | |
| fw.write("PatternHeight2 = Input { Value = 0.020841239721695, },") | |
| fw.write("SearchWidth2 = Input { Value = 0.0574350764852365, },") | |
| fw.write("SearchHeight2 = Input { Value = 0.0714421252371915, },") | |
| fw.write("TrackedCenter2 = Input {" ) | |
| fw.write("SourceOp = \"PlaneTrack%dTrack2XYPath\"," %i) | |
| fw.write("""Source = "Value", | |
| }, | |
| """) | |
| fw.write("Name3 = Input { Value = \"PlaneTrack3\", }," ) | |
| fw.write("PatternCenter3 = Input { Value = { %r, %r, }, },"%( marker.corners[2][0],marker.corners[2][1])) | |
| fw.write("PatternWidth3 = Input { Value = 0.0154571326929918, },") | |
| fw.write("PatternHeight3 = Input { Value = 0.020841239721695, },") | |
| fw.write("SearchWidth3 = Input { Value = 0.0574350764852365, },") | |
| fw.write("SearchHeight3 = Input { Value = 0.0714421252371915, },") | |
| fw.write("TrackedCenter3 = Input {" ) | |
| fw.write("SourceOp = \"PlaneTrack%dTrack3XYPath\"," %i) | |
| fw.write("""Source = "Value", | |
| }, | |
| """) | |
| fw.write("Name4 = Input { Value = \"PlaneTrack4\", }," ) | |
| fw.write("PatternCenter4 = Input { Value = { %r, %r, }, },"%( marker.corners[3][0],marker.corners[3][1])) | |
| fw.write("PatternWidth4 = Input { Value = 0.0154571326929918, },") | |
| fw.write("PatternHeight4 = Input { Value = 0.020841239721695, },") | |
| fw.write("SearchWidth4 = Input { Value = 0.0574350764852365, },") | |
| fw.write("SearchHeight4 = Input { Value = 0.0714421252371915, },") | |
| fw.write("TrackedCenter4 = Input {" ) | |
| fw.write("SourceOp = \"PlaneTrack%dTrack4XYPath\"," %i) | |
| fw.write("""Source = "Value", | |
| }, | |
| """) | |
| ##toolPosTracker = 1200+i*100 | |
| fw.write("ViewInfo = OperatorInfo { Pos = { %d, 100 } }," %toolPos) | |
| fw.write(""" | |
| },},""") | |
| i += 1 | |
| except: | |
| print("No clip found plane_track") | |
| # close composition | |
| fw.write(" },\n}\n") | |
| fw.close() | |
| print("finished export to fusion comp") | |
| # ------------------------------------------------------------------------ | |
| # Export Operator | |
| # ------------------------------------------------------------------------ | |
| class EXPORT_OT_fusionComp(bpy.types.Operator, ExportHelper): | |
| """Save a python script which re-creates cameras and markers elsewhere""" | |
| bl_idname = "export_scene.fusion_comp" | |
| bl_label = "Export Fusion Composition" | |
| filename_ext = ".comp" | |
| filter_glob: bpy.props.StringProperty( | |
| default="*.comp", | |
| options={'HIDDEN'} | |
| ) | |
| frame_start: bpy.props.IntProperty( | |
| name="Start Frame", | |
| description="Start frame for export", | |
| default=1, | |
| min=0, max=300000 | |
| ) | |
| frame_end: bpy.props.IntProperty( | |
| name="End Frame", | |
| description="End frame for export", | |
| default=250, | |
| min=1, max=300000 | |
| ) | |
| only_selected: bpy.props.BoolProperty( | |
| name="Only Selected", | |
| default=False | |
| ) | |
| def execute(self, context): | |
| write_cameras(context, self.filepath, self.frame_start, self.frame_end, self.only_selected) | |
| return {'FINISHED'} | |
| def invoke(self, context, event): | |
| self.frame_start = context.scene.frame_start | |
| self.frame_end = context.scene.frame_end | |
| wm = context.window_manager | |
| wm.fileselect_add(self) | |
| return {'RUNNING_MODAL'} | |
| def draw_fusion_export_menu(self, context): | |
| default_path = os.path.splitext(bpy.data.filepath)[0] + ".comp" | |
| self.layout.operator( | |
| EXPORT_OT_fusionComp.bl_idname, | |
| text="Fusion Composition (.comp)" | |
| ).filepath = default_path | |
| # ------------------------------------------------------------------------ | |
| # Registration | |
| # ------------------------------------------------------------------------ | |
| def register(): | |
| bpy.utils.register_class(EXPORT_OT_fusionComp) | |
| bpy.types.TOPBAR_MT_file_export.append(draw_fusion_export_menu) | |
| def unregister(): | |
| bpy.types.TOPBAR_MT_file_export.remove(draw_fusion_export_menu) | |
| bpy.utils.unregister_class(EXPORT_OT_fusionComp) | |
| if __name__ == "__main__": | |
| register() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment