Polygon Surface to Blobby Conversion in Render Time
using Python and Renderman Interface Filters
RenderMan Pro Server 14 introduces prman_for_python, a Python plugin module that allows us to build Pixar's RenderMan into our Python applications. With the plugin module "prman_for_python.so" comes a simple Python wrapper module, "prman.py". Together they make accessing the power of prman as easy as python.
Prman_for_python can be used to write/append RIB files and to render pixels directly from Python. We can even express RenderMan procedural primitive plugins and Ri filters (rifs) directly in Python.
prman.py
prman.py represents the highest level layer of the bridge to prman. prman.py is a Python module that exports a combination of procedures, constants, and class definitions. You must first import the module to gain access to prman. Python offers a number of methods to ensure a module import succeeds.
The Ri layer is at the heart of prman and embodies the RenderMan Interface. Ri Filter plugins can be expressed with Python. This makes it trivial to manipulate the Ri stream at the mouth of the renderer or simply to filter RIB files.
For this project i am using python rifs to convert a polygon surface into volumetric blobbys.
Polygon Surface to Volumetric Blobbies
Breakdown
First i created a particle simulation in houdini and used "Particle Fluid Surfacer" node to create the polygon surface for the simulation. Once i got the simulation i rendered it as a rib sequence.
The code first reads all the rib files in the folder and converts it blobby geometry. Then it goes through all the files for the second time and renders the blobby surface as volume primitives.
Polygon Surface To Blobby ( rif_polymeshToBlobby.py)
Using the "PointGeneralPolygon" module, this script goes through the rib files and converts it into blobby surface.
import prman
scale = .25
class Rif(prman.Rif):
def PointsGeneralPolygons(self, numpolys, numloops, indices, params):
opcodes = []
numblobs = len(params['P'])/3
for n in range(numblobs):
opcodes.append(1001)
opcodes.append(n * 16)
opcodes.append(0) # blending code
opcodes.append(numblobs)# blend all blobs
for n in range(numblobs):
opcodes.append(n)
common = (scale,0,0,0,0,scale,0,0,0,0,scale,0)
transforms = (scale,0,0,0,0,scale,0,0,0,0,scale,0)
xyz = params['P']
numxyz = len(xyz)
for n in range(0, numxyz, 3):
pos = (xyz[n], xyz[n+1], xyz[n+2])
if n == 0:
transforms = common + pos + (1,)
else:
transforms = transforms + common + pos + (1,)
params = {}
strs = ('',)
self.m_ri.Blobby(numblobs,opcodes,transforms, strs, params)
Blobby To Volume Primitives (rif_blobby.py)
Using the "Blobby" module, this script goes through the rib files and converts it into volume primitives. It basically appends the file and adds the number '8' as the first entry in the opcode, which renderman interprets as a blobby surface.
import prman
class Rif(prman.Rif):
def Blobby(self, numblobs, opcodes, xyz, strs, params):
opcodes = (8,) + opcodes
self.m_ri.Blobby(numblobs, opcodes, xyz, strs, params)
First i created a particle simulation in houdini and used "Particle Fluid Surfacer" node to create the polygon surface for the simulation. Once i got the simulation i rendered it as a rib sequence.
The code first reads all the rib files in the folder and converts it blobby geometry. Then it goes through all the files for the second time and renders the blobby surface as volume primitives.
Polygon Surface To Blobby ( rif_polymeshToBlobby.py)
Using the "PointGeneralPolygon" module, this script goes through the rib files and converts it into blobby surface.
import prman
scale = .25
class Rif(prman.Rif):
def PointsGeneralPolygons(self, numpolys, numloops, indices, params):
opcodes = []
numblobs = len(params['P'])/3
for n in range(numblobs):
opcodes.append(1001)
opcodes.append(n * 16)
opcodes.append(0) # blending code
opcodes.append(numblobs)# blend all blobs
for n in range(numblobs):
opcodes.append(n)
common = (scale,0,0,0,0,scale,0,0,0,0,scale,0)
transforms = (scale,0,0,0,0,scale,0,0,0,0,scale,0)
xyz = params['P']
numxyz = len(xyz)
for n in range(0, numxyz, 3):
pos = (xyz[n], xyz[n+1], xyz[n+2])
if n == 0:
transforms = common + pos + (1,)
else:
transforms = transforms + common + pos + (1,)
params = {}
strs = ('',)
self.m_ri.Blobby(numblobs,opcodes,transforms, strs, params)
Blobby To Volume Primitives (rif_blobby.py)
Using the "Blobby" module, this script goes through the rib files and converts it into volume primitives. It basically appends the file and adds the number '8' as the first entry in the opcode, which renderman interprets as a blobby surface.
import prman
class Rif(prman.Rif):
def Blobby(self, numblobs, opcodes, xyz, strs, params):
opcodes = (8,) + opcodes
self.m_ri.Blobby(numblobs, opcodes, xyz, strs, params)
BatchRiHoudini.py
The following piece of code reads the directory where all the rib files are saved and makes use of the modules listed above for the conversion process. It also creates the batch render script, which renders the images to the location specified in the rib file.
import ribops, os, sys, subprocess, prman, rif_polymeshToBlobby, rif_blobby
def testSingleRib(ribpath):
ri = prman.Ri()
ri.Option("rib", {"string asciistyle": "indented"})
rif = rif_polymeshToBlobby.Rif(ri)
prman.RifInit( [rif] )
temprib = os.path.join('/home/sragha20/mount/Chops/blobbyTest/test', 'temp.rib')
ri.Begin('-')
prman.ParseFile(ribpath)
ri.End()
def main():
hostdir = '/home/sragha20/mount/Chops/blobbyTest/test'
files = os.listdir(hostdir)
ribs = []
for f in files:
if os.path.isdir(f):
continue
if f.endswith('.rib'):
ribs.append(f)
# Specify the batch render script - it could be saved anywhere
batchPath = os.path.join(hostdir, 'batchRender')
job = ribops.Job('/home/sragha20/mount/Chops/blobbyTest/test')
ri = prman.Ri()
ri.Option("rib", {"string asciistyle": "indented"})
rif = rif_polymeshToBlobby.Rif(ri)
rif1 = rif_blobby.Rif(ri)
prman.RifInit( [rif])
for rib in ribs:
rib = os.path.join(hostdir, rib)
print rib
parent = os.path.dirname(rib)
name = os.path.basename(rib)
tmpRib = os.path.join(parent, 'tmp_' + name)
ri.Begin(tmpRib)
prman.ParseFile(rib)
ri.End()
os.remove(rib)
os.rename(tmpRib,rib)
prman.RifInit([rif1])
for rib in ribs:
rib = os.path.join(hostdir, rib)
print rib
parent = os.path.dirname(rib)
name = os.path.basename(rib)
tmpRib = os.path.join(parent, 'tmp_' + name)
ri.Begin(tmpRib)
prman.ParseFile(rib)
ri.End()
os.remove(rib)
os.rename(tmpRib,rib)
print 'done'
# Create the script
job.makeBatchRenderScript(hostdir, batchPath, ribs)
# Make is executible
os.chmod(batchPath, 0777)
# Spawn a child process that will run the script
args = ['sh', batchPath]
subprocess.Popen(args, stdout=subprocess.PIPE)
if __name__ == "__main__":
main()