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 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