# Render Online Ortho Tiles # by Ari Häyrinen 2014 # www.opendimension.org import bpy import math import os import errno import signal from mathutils import Vector, Matrix # USER SETTINGS defaultLevel = 2 # default level in browser maxLevel = 3 # starting from zero tilesDir = 'tiles' # the name of the tiles directory # - in the same directory where your .blend is # USER SETTINGS ENDS abort = None reso = 256 # better not to change this! minLevel = 0 cam = bpy.data.objects['Camera'] #save some camera settings camLoc = Vector((cam.location)) camOrtho = cam.data.ortho_scale origX = bpy.context.scene.render.resolution_x origY = bpy.context.scene.render.resolution_y bpy.context.scene.render.resolution_x = reso bpy.context.scene.render.resolution_y = reso # find out the output directory (location of the .blend) filepath = bpy.data.filepath directory = os.path.dirname(filepath) # handler for keyboard interrupt, so that we can reset camera when user terminates script # http://blender.stackexchange.com/questions/6781/abort-script-that-renders-frames def hndl(signum, frame): global abort abort = True print("\nCancel request!!! Wait a moment...\n") # reset handler def reset(): signal.signal( signal.SIGINT, signal.default_int_handler ) def makeDir(path): try: os.makedirs(path) except OSError as exception: if exception.errno != errno.EEXIST: raise def createDirs(minLevel, maxLevel): global abort # global signal.signal(signal.SIGINT, hndl) abort = False currentLevel = minLevel makeDir(os.path.join(directory, 'tiles')) tilesDir = os.path.join(directory, 'tiles') while currentLevel <= maxLevel and not abort: path = os.path.join(tilesDir, str(currentLevel)) makeDir(path) createSubDirs(currentLevel, tilesDir) currentLevel += 1 cam.data.ortho_scale = cam.data.ortho_scale/2 def createSubDirs(currentLevel, tilesDir): global abort x = 0 while x < math.pow(2,currentLevel) and not abort: path = os.path.join(tilesDir, str(currentLevel), str(x)) makeDir(path) renderTiles(x, path, currentLevel) x += 1 #bpy.context.scene.update() def renderTiles(x, path, zoomLevel): global abort y = 0 print('rendering: ' + path) #reset camera location cam.location = camLoc camMatrix = cam.matrix_world.copy() xAngle = cam.rotation_euler[0] zAngle = cam.rotation_euler[2] sinXAngle = math.cos(xAngle) if sinXAngle == 0.0: sinXAngle = 1.0 sinXAngle = 1/sinXAngle # how much we must move camera along X axis transl_x = -1*camOrtho/2 + cam.data.ortho_scale/2 + x*cam.data.ortho_scale while y < math.pow(2,zoomLevel) and not abort: # how much we must move camera along Y axis transl_y = -1*camOrtho/2*sinXAngle + (cam.data.ortho_scale/2*sinXAngle) + y*(cam.data.ortho_scale*sinXAngle) print('filename: ' + str(y)) moveCamera(transl_x,transl_y) bpy.data.scenes['Scene'].render.filepath = path + '/' + str(y) bpy.ops.render.render(write_still=True ) #reset cam.matrix_world = camMatrix y += 1 def moveCamera(x,y): #we need to move camera along Y and X axis after it is rotated in Z ignoring X loc, rot, sca = cam.matrix_world.decompose() locMat = Matrix.Translation(loc) #original location xAngle = cam.rotation_euler[0] zAngle = cam.rotation_euler[2] xRotMat = Matrix.Rotation(xAngle,4,'X') zRotMat = Matrix.Rotation(zAngle,4,'Z') moveMat = Matrix.Translation((x,y,0.0)) # starting point * Z rotation * Move after Z rot * and then finally rotate x m = locMat * zRotMat * moveMat * xRotMat cam.matrix_world = m def writeIndexHTML(html): inFile = 'index.html' outFile = 'index.html' html = html.format(pixel=math.pow(2,maxLevel)*reso, maxZ=maxLevel, defLevel=defaultLevel) templateOut = os.path.join(directory, tilesDir, outFile) try: print('Writing Leaflet index file: ' + templateOut) ff = open(templateOut, "wb") for lin in html: ff.write((lin).encode('utf-8')) ff.close() print('\nDONE!') except: print('TILES export ERROR: Could not write ' + outFile +'!') def resetCamera(cam,camLoc,camOrtho,origX,origY): cam.location = camLoc cam.data.ortho_scale = camOrtho bpy.context.scene.render.resolution_x = origX bpy.context.scene.render.resolution_y = origY # index.html html = """

Blender Online Tiles Script

Made with Blender

""" if __name__== "__main__": createDirs(minLevel, maxLevel) reset() # reset camera to the original state print("Resetting camera") resetCamera(cam,camLoc,camOrtho,origX,origY) writeIndexHTML(html) # open the result in a browser urli = os.path.join(directory, tilesDir, 'index.html') bpy.ops.wm.url_open(url=urli)