#!BPY """ Released under the Blender Artistic Licence (BAL) Name: 'Stereorender 1.3' Blender: 235 Group: 'Render' Tooltip: 'Render stills or animations in red-cyan stereo' """ __author__ = "pat" __version__ = "1.3 - 19/01/05 -" __email__ = ('Author, pat:psycho3d*de') __url__ = ("Author's website, www.psycho3d.de") __bpydoc__ ="""\ This script renders your scene as red-cyan anaglyph. The script renders your scene twice with different camera locations (controlled by the "deltaX" value), generates the final image and displays it in the render window. This also works for animations, the final animation will be played after rendering all frames. Buttons:
Left, Right, Join: deactivate to skip a part of the rendering process
BW: tells Blender to save grey images, faster to generate final image
RGB: Blender saves colored pics, final image will be colored
deltaX: controls the distance between the two camera locations
Correct Cam: Creates an empty to apply location/rotation/animation to the cam. This avoids errors when the camera is rotated. Hotkeys:
Q: [Q]uit """ import Blender from Blender import Scene, Object, Get, Window, Text as txt from Blender.BGL import * from Blender.Draw import * from string import zfill from Blender.sys import sep, time rc = Scene.getCurrent().getRenderingContext() ### gui defines ### f_deltaX = Create(.06) t_anim = Create(0) i_startFrame = Create(rc.startFrame()) i_endFrame = Create(rc.endFrame()) t_gray = Create(1) t_rgb = Create(0) t_left = Create(1) t_right = Create(1) t_join = Create(1) m_settings = Create(1) sett_name = Create("untitled") settings = "" ### gui defines ### finalSize = [] del rc def renderFrame(rc, framenr): rc.startFrame(framenr) rc.endFrame(framenr) rc.renderAnim() ### renderFrame def read24bit(path): f = open(path, 'rb') header = f.read(18) data = f.read() f.close() sizeX = ord(header[12]) + ord(header[13]) * 256 sizeY = ord(header[14]) + ord(header[15]) * 256 tga = [] t = 0 size = sizeX * sizeY * 3 while t < size: tga.append(ord(data[t + 2])) t += 3 return tga, sizeX, sizeY ### read24bit def read24bitCyan(path): f = open(path, 'rb') header = f.read(18) data = f.read() f.close() sizeX = ord(header[12]) + ord(header[13]) * 256 sizeY = ord(header[14]) + ord(header[15]) * 256 tga = [] tga2 = [] t = 0 size = sizeX * sizeY * 3 while t < size: tga.append(ord(data[t])) tga2.append(ord(data[t + 1])) t += 3 return tga2, tga ### read24bitCyan def read8bit(path): f = open(path, 'rb') header = f.read(18) data = f.read() f.close() sizeX = ord(header[12]) + ord(header[13]) * 256 sizeY = ord(header[14]) + ord(header[15]) * 256 tga = [] t = 0 size = sizeX * sizeY while t < size: tga.append(ord(data[t])) t += 1 return tga, sizeX, sizeY ### read8bit def write24bit(path, data, sizeX, sizeY): header = [0,0,2,0,0,0,0,0,0,0,0,0, \ sizeX % 256, sizeX / 256, sizeY % 256, sizeY / 256, 24, 0] f = open(path, 'wb') t = 0 while t < 18: f.write(chr(header[t])) t += 1 t = 0 d = len(data) while t < d: f.write(chr(data[t][2])) f.write(chr(data[t][1])) f.write(chr(data[t][0])) t += 1 f.close() ### write24bit def repCam(): sce = Scene.GetCurrent() cam = sce.getCurrentCamera() eul = cam.getEuler() camipo = cam.getIpo() if eul[1] != 0 or eul[2] != 0 or camipo != None: emp = Object.New("Empty")#, "camcontroller") sce.link(emp) cam.clearIpo() camloc = cam.getLocation() cam.setLocation(0,0,0) cam.setEuler(0,0,0) cam.clrParent() emp.makeParent([cam]) emp.setLocation(camloc) emp.setEuler(eul) if camipo: emp.setIpo(camipo) PupMenu("Note:%t|The empty '"+emp.getName()+"' now controlls the cam, use it to apply rotation or animation") else: PupMenu("No need to correct the cam:%t|The camera is not rotated and has no Ipo") ### repCam def loadSettings(name): global t_left, t_join, t_right, t_rgb, i_startFrame, i_endFrame, f_deltaX name = "[%s]" % name t = txt.Get("stereorenderini") lines = t.asLines() line = 0 while line < t.nlines: if lines[line] == name: data = lines[line+1] line += 1 data = data.split() print data t_left.val = int(data[0]) t_join.val = int(data[1]) t_right.val = int(data[2]) t_rgb.val = int(data[3]) i_startFrame.val = int(data[4]) i_endFrame.val = int(data[5]) f_deltaX.val = float(data[6]) bevent(9) #set BW button Redraw() ### loadSettings def saveSettings(name): name = "[%s]" % name data = [t_left.val] data.append(t_join.val) data.append(t_right.val) data.append(t_rgb.val) data.append(i_startFrame.val) data.append(i_endFrame.val) data.append(f_deltaX.val) datastr = "" for st in data: datastr += str(st) + " " t = txt.Get("stereorenderini") lines = t.asLines() line = 0 overwrite = 0 while line < t.nlines: if lines[line] == name: overwrite = line + 1 line += 1 if not overwrite == 0: lines[overwrite] = datastr t.clear() for lin in lines: if not lin=="": t.write(lin + "\n") else: t.write(name + "\n") t.write(datastr + "\n") ### saveSettings def checkSettings(): global settings settings = "Select Settings%t|** Add New **" try: t = txt.Get("stereorenderini") except NameError: t = txt.New("stereorenderini") else: lines = t.asLines() nline = 0 while nline < t.nlines: name = lines[nline] settings += "|" + name[1 : len(name)-1] nline += 2 Redraw() return nline/2 ### checkSettings def joinImages(rc, framenr, oldPath): leftImage = oldPath + "_left_" + zfill(str(framenr), 4) + ".tga" rightImage = oldPath + "_right_" + zfill(str(framenr), 4) + ".tga" if t_gray.val: redChannel, sizeX, sizeY = read8bit(leftImage) cyanChannel, sizeX, sizeY = read8bit(rightImage) combined = map(None, redChannel, cyanChannel, cyanChannel) else: redChannel, sizeX, sizeY = read24bit(leftImage) greenChannel, blueChannel = read24bitCyan(rightImage) combined = map(None, redChannel, greenChannel, blueChannel) write24bit(oldPath + zfill(str(framenr), 4) + ".tga", combined, sizeX, sizeY) global finalSize finalSize = [sizeX, sizeY] print "Joined Images to: %s" % (oldPath + zfill(str(framenr), 4) + ".tga") ### joinImages def renderScene(start, end): global t_join ### start ### sce = Scene.getCurrent() rc = sce.getRenderingContext() rc.enableExtensions(1) rc.setImageType(14) if t_gray.val: rc.enableGrayscale() else: rc.enableRGBColor() oldStart = rc.startFrame() oldEnd = rc.endFrame() origPath = rc.getRenderPath() oldPath = rc.getRenderPath() oldPath = oldPath.replace("/",sep) oldPath = oldPath.replace("\\",sep) oldPath = oldPath.replace(sep*2,sep) #render to file's directory if nothing is set if oldPath == "": oldPath = Get("filename")[:Get("filename").rindex(sep)+1] cam = sce.getCurrentCamera() #render the current scene joinFailed = 0 frnr = start while frnr <= end: t = time() loc = cam.getLocation() if t_left.val: rc.setRenderPath(oldPath + "_left_") cam.setLocation(loc[0] - f_deltaX.val/2, loc[1], loc[2]) renderFrame(rc, frnr) if t_right.val: rc.setRenderPath(oldPath + "_right_") cam.setLocation(loc[0] + f_deltaX.val/2, loc[1], loc[2]) renderFrame(rc, frnr) cam.setLocation(loc[0], loc[1], loc[2]) if t_join.val: try: joinImages(rc, frnr, oldPath) except: PupMenu("Error%t|Trying to join: pictures missing") t_join.val = 0 Redraw() print "----- Stereo Render Time: %fs -----" % (time() - t) #next frame frnr += 1 Scene.Render.CloseRenderWindow() rc.enableRGBColor() rc.startFrame(oldStart) rc.endFrame(oldEnd) rc.setRenderPath(oldPath) #show result if t_join.val: if start != end: rc.play() #play final animation else: tempscene = Scene.New("stereorendertempscene") tempscene.makeCurrent() tempscene.link(Blender.Object.New("Camera")) rc2 = tempscene.getRenderingContext() rc2.enableBackbuf(1) rc2.setBackbufPath(oldPath + zfill(str(frnr-1), 4) + ".tga") rc2.setRenderPath(oldPath) rc2.enableExtensions(1) rc2.setImageType(14) rc2.enableRGBColor() rc2.setRenderWinSize(100) rc2.imageSizeX(finalSize[0]) rc2.imageSizeY(finalSize[1]) rc2.render() #show final image sce.makeCurrent() Scene.Unlink(tempscene) ### end ### rc.setRenderPath(origPath) ### renderScene def gui(): global t_gray, t_rgb, f_deltaX, i_startFrame, i_endFrame, t_left, t_right, t_join, m_settings, sett_name col = Window.Theme.Get()[0].get("buts").back glClearColor(col[0], col[1], col[2], col[3]) glClear(GL_COLOR_BUFFER_BIT) col = Window.Theme.Get()[0].get("buts").text_hi glColor3f(col[0], col[1], col[2]) PushButton("Exit", 1, 10, 10, 100, 20, "This one should explain itself :)") PushButton("Correct Cam", 5, 120, 40, 100, 20, "Create an empty to carry the camera, for correct images in animation or with rotated cam") f_deltaX = Number("deltaX: ", 2, 10, 40, 100, 20, f_deltaX.val, 0.001, 1.0, "The distance between the \"eyes\", the best value depends on the distance to the foreground objects") i_startFrame = Number("Sta: ", 2, 10, 70, 105, 20, i_startFrame.val, 1, 18000, "the start frame of the animation") i_endFrame = Number("End: ", 2, 115, 70, 105, 20, i_endFrame.val, 1, 18000, "the end frame of the animation") t_gray = Toggle("BW", 8, 10, 95, 105, 20, t_gray.val, "save as grayscale, faster (result will be RGB)") t_rgb = Toggle("RGB", 9, 115, 95, 105, 20, t_rgb.val, "save as RGB, colored pictures but slower") t_left = Toggle("Left", 2, 10, 120, 70, 20, t_left.val, "render left eye picture") t_join = Toggle("Join", 2, 80, 120, 70, 20, t_join.val, "join images to red-cyan stereo image") t_right = Toggle("Right", 2, 150, 120, 70, 20, t_right.val, "render right eye picture") PushButton("RENDER", 6, 10, 150, 100, 30, "render frame \"Sta:\"") PushButton("ANIM", 7, 120, 150, 100, 30, "render animation - WARNING: save your file, you can't stop animation rendering") PushButton("Load", 10, 10, 215, 100, 20, "Load settings") PushButton("Save", 11, 120, 215, 100, 20, "Save settings") sett_name = String("", 2, 145, 190, 75, 20, sett_name.val, 20, "Name of setting for ** Add New **") m_settings = Menu(settings, 3, 10, 190, 130, 20, m_settings.val, "The settings to load or save") glRasterPos2d(180, 10) Text("by pat") def event(evt, val): if (evt == QKEY and not val): Exit() def bevent(evt): if (evt == 1): Exit() elif evt == 5: repCam() elif (evt == 6): saveSettings("** last render **") checkSettings() renderScene(i_startFrame.val, i_startFrame.val) elif (evt == 7): saveSettings("** last render **") checkSettings() renderScene(i_startFrame.val, i_endFrame.val) elif (evt == 8): t_rgb.val = not t_gray.val Redraw() elif (evt == 9): t_gray.val = not t_rgb.val Redraw() elif (evt == 10): #load if m_settings.val != 1: name = settings.split("|")[m_settings.val] loadSettings(name) elif (evt == 11): #save if m_settings.val == 1: if sett_name.val != "": saveSettings(sett_name.val) #select new setting in menu m_settings.val = checkSettings() else: name = settings.split("|")[m_settings.val] saveSettings(name) checkSettings() Register(gui, event, bevent) checkSettings()