#!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()