Data Expansion in Houdini using Python & Renderman Interface Filters
This page demonstrates the use of a procedural primitive, or helper app as they are often called, to generate an arbitrary number of points in order to enhance the appearance of a particle simulation.
For this project i want to create a procedural Tornado/Dust Devil in Houdini and do data expansion in render-time I am going to concentrate only on the tornado/dust devil network for now.
Reference Footage
Houdini playblast of the initial Tornado Network
Following is the procedural network i created in Houdini which can be used to create a basic tornado/dust devil simulation.
My next step was to figure out a way to use Data Expansion in houdini since i want to avoid big simulation time.
Script implementation for the Tornado network :
Original Houdini Particles Count : 5600 After applying the script : 1680000
Python Script
Following is the code. It basically goes through all the points in the scene and creates a rib file for each point. The built-in procedural RiProcRunProgram will run an external “helper program,” capturing its output and interpreting it as RIB input. This helper program will add the extra particles during the render time.
The following code entered in "Python Source Editor".
def main():
ri = prman.Ri()
ri.Option("rib", {"string asciistyle": "indented"})
ap_script = '/usr/bin/python/home/sragha20/mount/stuhome/vsfx705/python/addPoints.py'
ap_num = str(hou.node("/obj/proxy").parm("num").eval())
ap_dist = str(hou.node("/obj/proxy").parm("dist").eval())
ap_dia = str(hou.node("/obj/proxy").parm("dia").eval())
ap_freq = str(hou.node("/obj/proxy").parm("freq").eval())
inputs = ap_num + ' ' + ap_dia + ' ' + ap_freq + ' ' + ap_dist + ' ' + '3'
items = [ap_num, ap_dia, ap_freq, ap_dist]
pointnode = hou.node('/obj/pop/point1')
pointgeo = pointnode.geometry()
pos = pointgeo.iterPoints()
hou.setFrame(hou.frame())
path = '/home/sragha20/mount/project4/ribs/particle_%04d.rib' % int(hou.frame())
ri.Begin(path) # set rendertarget to ri.RENDER to render pixels
for i in range(len(pos)):
tmp = pointgeo.iterPoints()[i]
tmp1 = tmp.floatListAttribValue("P")
ri.TransformBegin()
ri.Translate(tmp1[0], tmp1[1], tmp1[2])
angle = random.uniform(-180.0, 180.0)
ri.Rotate(angle, random.uniform(-1.0, 1.0), random.uniform(-1.0, 1.0), random.uniform(-1.0, 1.0))
ri.Procedural( (ap_script, inputs), (-1,1, -1,1, -1,1), "ProcRunProgram")
ri.TransformEnd()
ri.End()
if __name__ == "__main__":
main()
Noise Function (Addpoints.py)
import sys, random, math
from pnoise import pnoise
inputs = sys.stdin.readline()
while inputs:
items = inputs.split()
pixels = float(items[0])
num = int(items[1])
dia = float(items[2])
freq = float(items[3])
size = float(items[4])
sed = int(items[5])
random.seed(sed)
print 'Points "P" ['
for n in range(num):
x = random.random() * freq * random.uniform(0.8, 1.3)
y = random.random() * freq * random.uniform(0.8, 1.3)
z = random.random() * freq * random.uniform(0.8, 1.3)
x = pnoise(x,y,z) * size
y = pnoise(y,x,z) * size
z = pnoise(z,x,y) * size
print '%1.3f %1.3f %1.3f' % (x,y,z)
print '] "constantwidth" [%1.3f]' % dia
sys.stdout.write('\377')
sys.stdout.flush()
inputs = sys.stdin.readline()
Once the script was entered in source editor, I made a Renderman Rop and referenced the function in "Pre-Frame Script" field.
hou.session.main()
"hou" is a built-in python procedure which gives you interactive access to all the contexts in houdini. "main" is the function.
No comments:
Post a Comment