Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!BPY
- # """
- # Name: 'Camera Tracking (.ma)'
- # Blender: 273
- # Group: 'Export'
- # Tip: 'Export camera tracking to Maya Ascii (for Shake, After Effects etc)'
- # """
- import bpy
- import time
- import math
- #
- # This operator exports the data from the active camera to a Maya ASCII .ma file.
- # The resulting file can be used in a variety of software programs, including
- # Autodesk Maya, Nothing Real/Apple Shake, Adobe After Effects and others.
- #
- # For Maya, you would think you could use FBX, but the camera is rotated the
- # wrong way in Maya 2010. In Modo, it is also upside down. So until Blender's FBX
- # export gets fixed, this is probably the only way to get correct matchmove
- # data out of Blender.
- #
- # This is based on a script found on videocopilot.net, updated for Blender's new
- # Python API, including support for menu integration.
- #
- # Author of the updated version: Peter Werner ([email protected]).
- # This is provided as-is to the community, with no support given.
- #
- # The following bugs from the original script have been fixed:
- #
- # - The number of keyframes is now written correctly (used to be hard-coded at 3),
- # which caused Maya to complain on import
- # - Now accounting for different coordinate axes and rotation behavior
- # between Blender and Maya
- #
- # Current limitations:
- #
- # - Currently, there is no UI to select which camera to export
- # (or to export all of them)
- # - Apparently the resolution settings don't end up
- # - Playback range/FPS is not set (I thinks there is a playbackOptions MEl command)
- # - Maya gives an error that the .dar attribute does not exist.
- # This code is from the original script, so one would have to investigate this more
- # - When opening the file in Maya, the camera does not appear to be in the correct
- # position. You need to change the current frame for it to update.
- # - If you did matchmoving (camera tracking), you may have to bake/apply the constraint,
- # not sure since my computer is too slow for extensive testing with matchmoving.
- #
- class ExportCameraToMayaOperator( bpy.types.Operator ):
- bl_idname = "export.camera_to_maya"
- bl_label = "Export Camera to Maya"
- filepath = bpy.props.StringProperty( subtype="FILE_PATH" )
- @classmethod
- def poll( cls, context ):
- # We need a camera in the active scene
- return context.scene.camera != None
- def execute( self, context ):
- self.exportTracking( context, self.filepath )
- return { 'FINISHED' }
- def invoke( self, context, event ):
- context.window_manager.fileselect_add( self )
- return { 'RUNNING_MODAL' }
- def exportTracking( self, context, mafilename ):
- t = {}
- t[ 'header' ] = []
- t[ 'header' ].append( '//Maya ASCII scene\n//Name: camera.ma\n//Last modified: %s\n' % time.strftime( '%X %d/%m/%y' ) )
- t[ 'header' ].append( 'currentUnit -l centimeter -a degree -t film;\n' )
- # Save current frame so we can restore it later
- frameOriginal = context.scene.frame_current
- camObj = context.scene.camera
- camera = bpy.data.cameras[ bpy.context.scene.camera.name ]
- matrix = camObj.matrix_world
- t[ 'header' ].append( 'createNode transform -n "%s";\n' % camera.name )
- t[ 'header' ].append( '\tsetAttr ".t" -type "double3" 0 0 0 ;\n' )
- t[ 'header' ].append( '\tsetAttr -av ".tx";\n' )
- t[ 'header' ].append( '\tsetAttr -av ".ty";\n' )
- t[ 'header' ].append( '\tsetAttr -av ".tz";\n' )
- t[ 'header' ].append( '\tsetAttr ".r" -type "double3" 0 0 0 ;\n' )
- t[ 'header' ].append( '\tsetAttr -av ".rx";\n' )
- t[ 'header' ].append( '\tsetAttr -av ".ry";\n' )
- t[ 'header' ].append( 'createNode camera -n "camera" -p "%s";\n' % camera.name )
- t[ 'header' ].append( '\tsetAttr -k off ".v";\n' )
- t[ 'header' ].append( '\tsetAttr ".rnd" no;\n' )
- yRes = context.scene.render.resolution_y
- xRes = context.scene.render.resolution_x
- aspX = context.scene.render.pixel_aspect_x
- aspY = context.scene.render.pixel_aspect_y
- aspect = xRes * aspX / float( yRes * aspY )
- # if aspect > 1: x is constant, otherwise y constant
- # constant comes from fov equations: fov = 2 * atan(aspect * 16.0 / camera.lens), aperturey = tan(fov/2)*camera.lens*2/25.4
- # tracking seems to work better using 1.25, change as needed
- #c = 16.0*2/25.4
- c = 1.25
- aperturex = min( c, c * aspect )
- aperturey = min( c, c / aspect )
- t[ 'header' ].append( '\tsetAttr ".cap" -type "double2" %s %s ;\n' % (aperturex,aperturey) )
- t[ 'header' ].append( '\tsetAttr ".dar" %s;\n' % aspect )
- t[ 'header' ].append( '\tsetAttr ".lsr" 1;\n' ) # lens squeeze ratio
- t[ 'header' ].append( '\tsetAttr ".ff" 0;\n' )
- t[ 'header' ].append( '\tsetAttr ".fl" %s;\n' % camera.lens ) # focal length
- t[ 'header' ].append( '\tsetAttr ".ncp" 0.01;\n' )
- t[ 'header' ].append( '\tsetAttr ".ow" 30;\n' )
- t[ 'header' ].append( '\tsetAttr ".imn" -type "string" "camera1";\n' )
- t[ 'header' ].append( '\tsetAttr ".den" -type "string" "camera1_depth";\n ')
- t[ 'header' ].append( '\tsetAttr ".man" -type "string" "camera1_mask";\n' )
- startFrame = context.scene.frame_start
- endFrame = context.scene.frame_end
- numFrames = endFrame + 1 - startFrame
- for p in [ 'translateX', 'translateY', 'translateZ', 'rotateX', 'rotateY', 'rotateZ' ]:
- t[ p ] = []
- t[ p ].append( 'createNode animCurveTL -n "%s_%s";\n' % ( camObj.name, p ) )
- t[ p ].append( '\tsetAttr ".tan" 10;\n' )
- t[ p ].append( '\tsetAttr ".wgt" no;\n' )
- # Fixed bug in the original script here -- this would always write out [0:3] instead of
- # the actual number of frames, causing Maya to report a file read error to the user
- t[ p ].append( '\tsetAttr -s 4 ".ktv[0:%s]" ' % ( numFrames - 1 ) )
- context.window_manager.progress_begin( startFrame, endFrame + 1 )
- for frame in range( startFrame, endFrame + 1 ):
- # Don't use "context.scene.frame_current = frame" here.
- # It works in the interactive python shell, but the animation
- # is not exported properly.
- context.scene.frame_set( frame )
- context.window_manager.progress_update( frame )
- translation = matrix.translation
- rotation = matrix.to_euler()
- # Append transformations, taking Maya's different coordinate axis
- # orientation into account.
- # In Maya the positive y-axis is vertical up, in Blender positive y
- # moves into the screen. In Maya, negative z goes into the screen.
- t[ 'translateX' ].append( '%s %s ' % ( frame, translation.x ) )
- t[ 'translateY' ].append( '%s %s ' % ( frame, translation.z ) )
- t[ 'translateZ' ].append( '%s %s ' % ( frame, - translation.y ) )
- # A 0 rotation camera in Blender looks down, one in Maya looks
- # into the screen. In Blender, this means the camera points towards
- # negative Z, in Maya towards negative Y.
- # This means we need to rotate the Maya camera by -90 degrees in X
- # (pi/2 in radians) so that an untransformed camera will end up
- # oriented correctly.
- t[ 'rotateX' ].append( '%s %s ' % ( frame, rotation.x - math.pi / 2 ) )
- t[ 'rotateY' ].append( '%s %s ' % ( frame, rotation.z ) )
- t[ 'rotateZ' ].append( '%s %s ' % ( frame, - rotation.y ) )
- # Restore the current frame to the original value
- context.scene.frame_current = frameOriginal
- context.window_manager.progress_end()
- t[ 'footer' ] = []
- t[ 'footer' ].append( 'connectAttr "%s_translateX.o" "%s.tx";\n' % ( camObj.name, camObj.name ) )
- t[ 'footer' ].append( 'connectAttr "%s_translateY.o" "%s.ty";\n' % ( camObj.name, camObj.name ) )
- t[ 'footer' ].append( 'connectAttr "%s_translateZ.o" "%s.tz";\n' % ( camObj.name, camObj.name ) )
- t[ 'footer' ].append( 'connectAttr "%s_rotateX.o" "%s.rx";\n' % ( camObj.name, camObj.name ) )
- t[ 'footer' ].append( 'connectAttr "%s_rotateY.o" "%s.ry";\n' % ( camObj.name, camObj.name ) )
- t[ 'footer' ].append( 'connectAttr "%s_rotateZ.o" "%s.rz";\n' % ( camObj.name, camObj.name ) )
- t[ 'footer' ].append( 'connectAttr "%s_scaleX.o" "%s.sx";\n' % ( camObj.name, camObj.name ) )
- t[ 'footer' ].append( 'connectAttr "%s_scaleY.o" "%s.sy";\n' % ( camObj.name, camObj.name ) )
- t[ 'footer' ].append( 'connectAttr "%s_scaleZ.o" "%s.sz";\n' % ( camObj.name, camObj.name ) )
- t[ 'footer' ].append( '\n// End of camera.ma\n' )
- if not mafilename.endswith( '.ma' ):
- mafilename += '.ma'
- mafile = open( mafilename, 'w' )
- for line in t[ 'header' ]:
- mafile.write(line)
- for p in [ 'translateX', 'translateY', 'translateZ', 'rotateX', 'rotateY', 'rotateZ' ]:
- for line in t[ p ]:
- mafile.write( line )
- mafile.write( ';\n' )
- for line in t[ 'footer' ]:
- mafile.write( line )
- def menu_func( self, context ):
- self.layout.operator_context = 'INVOKE_DEFAULT'
- self.layout.operator( ExportCameraToMayaOperator.bl_idname, text="Camera to Maya (.ma)" )
- def register():
- bpy.utils.register_class( ExportCameraToMayaOperator )
- # Append a menu item for our operator item to the file menu
- bpy.types.INFO_MT_file_export.append( menu_func )
- def unregister():
- bpy.utils.unregister_class( ExportCameraToMayaOperator )
- # Register the operator if the script is running directly (i.e. not
- # being imported as a module)
- if __name__ == "__main__":
- register()
- # Call our new operator when executing the script (use while debugging)
- #bpy.ops.export.camera_to_maya( 'INVOKE_DEFAULT' )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement