This allows playblast of certain frames in blender while filling in the gaps automatically
The goal is to allow animator to work in spline yet make a playblast on two's (Tip from Joan Marc Fuentes)
TODO: put this in blender addon form.
TODO: allow it to use a keyed object to find frames to playblast ...
#Use and Modify at your own risk
#example usage it assumes first frame in list is starting frame: #naPlayblast( frames = [1,3,5], imageDir = "/Users/Nathaniel/Desktop/SINGLE_BLENDER_FACE_RIG/intro_blender_pipe/output/tmpPlayblast", fill = True)
#this example playblasts on twos #frames = range( bpy.context.scene.frame_start, bpy.context.scene.frame_end, 2) #naPlayblast( frames = frames, imageDir = "/Users/Nathaniel/Desktop/SINGLE_BLENDER_FACE_RIG/intro_blender_pipe/output/tmpPlayblast", fill = True) ##
import shutil import os import bpy def naPlayblast( frames = [1,3,5], imageDir = "/Users/Nathaniel/Desktop/SINGLE_BLENDER_FACE_RIG/intro_blender_pipe/output/tmpPlayblast", fill = True): if not os.path.exists( imageDir ): print('cannot find output directory') return if frames[0] != bpy.context.scene.frame_start: print('only works with starting frame given matches with timeline') return setImageExt() #playblast chosen frames for frame in frames: bpy.context.scene.frame_set(frame) imageName = getImageNameFromNumber(frame) imagePath = os.path.join( imageDir, imageName ) bpy.data.scenes["Scene"].render.filepath = imagePath bpy.ops.render.opengl(write_still=True) #fill in missing frames if fill: missingInfoDict = getFillMissingFramesDictionary( frames ) fillMissingFrames( missingInfoDict, imageDir ) def setImageExt(): """can change this for different image extension """ bpy.context.scene.render.image_settings.file_format = 'TIFF' def getImageExt(): return 'tif' def getImageNameFromNumber( frame = 1 ): """can change this to any image name formatting """ return 'img_%d.%s' %(frame, getImageExt() ) def getFillMissingFramesDictionary( sourceFrames = [1,3,5] ): """keys are source image name values list of destination image names needed to fill #this gives info for filling in images #ex result given [1,3,5] it assumes always beginning with start frame: #{ 'img_1':['img_2'], 'img_3':[img_4] } """ startFrame = bpy.context.scene.frame_start endFrame = bpy.context.scene.frame_end if sourceFrames[0] != startFrame: print( 'cannot handle source frames not starting at %d.' %startFrame) return result = {} for i in range(0,len(sourceFrames)-1): #print sourceFrames[i], range( sourceFrames[i]+1, sourceFrames[i+1] ) sImage = getImageNameFromNumber( sourceFrames[i] ) dImages = [ getImageNameFromNumber(x) for x in range( sourceFrames[i]+1, sourceFrames[i+1] ) ] result[ sImage ] = dImages #fill in up to total frames if needed if sourceFrames[ len(sourceFrames) - 1 ] != endFrame: sImage = getImageNameFromNumber( sourceFrames[len(sourceFrames)-1] ) dImages = [ getImageNameFromNumber(x) for x in range( sourceFrames[ len(sourceFrames)-1 ]+1, endFrame+1 ) ] result[ sImage ] = dImages return result def fillMissingFrames( imgDict = { 'img_1':['img_2'], 'img_3':['img_4'] }, imgDir = '/Users/Nathaniel/Desktop/SINGLE_BLENDER_FACE_RIG/intro_blender_pipe/output/tmpPlayblast' ): """ this does actual copy of images #given ex: { 'img_1':['img_2'], 'img_3':[img_4] }, imgDir = '/Users/Nathaniel/Desktop/SINGLE_BLENDER_FACE_RIG/intro_blender_pipe/output/tmpPlayblast' """ for sourceImage in imgDict.keys(): destinationImages = imgDict[sourceImage] for dImage in destinationImages: dImageFull = os.path.join( imgDir, dImage ) sImageFull = os.path.join( imgDir, sourceImage ) if not os.path.exists( sImageFull ): print('could not find source image %s, skipping' %sImageFull) continue shutil.copy( sImageFull, dImageFull )
Happy Sketching!
Nate
#inspired by:
#Joan Marc Fuentes https://vimeo.com/88955189
#https://stackoverflow.com/questions/14982836/rendering-and-saving-images-through-blender-python
#https://blender.stackexchange.com/questions/1101/blender-rendering-automation-build-script
#https://blender.stackexchange.com/questions/27579/render-specific-frames-with-opengl-via-python/27640
#https://stackoverflow.com/questions/27515913/create-a-copy-of-an-image-python
#https://stackoverflow.com/questions/27678156/how-to-count-by-twos-with-pythons-range