The goal of this assignment was to use Python classes to write scripts to generate a Hilbert curve that can be implemented
# This is the formula that generates the CVs for the Hilbert pattern.
# Code from Malcolm Kesson - www.fundza.com
import sys, math
def hilbert(x0, y0, xi, xj, yi, yj, n):
if n <= 0:
X = x0 + (xi + yi)/2
Y = y0 + (xj + yj)/2
# Output the coordinates the cv
print '%s %s 0' % (X, Y)
hilbert(x0, y0, yi/2, yj/2, xi/2, xj/2, n - 1)
hilbert(x0 + xi/2, y0 + xj/2, xi/2, xj/2, yi/2, yj/2, n - 1)
hilbert(x0 + xi/2 + yi/2, y0 + xj/2 + yj/2, xi/2, xj/2, yi/2, yj/2, n - 1)
hilbert(x0 + xi/2 + yi, y0 + xj/2 + yj, -yi/2,-yj/2,-xi/2,-xj/2, n - 1)
Next, we created a Python class for the Hilbert function, to which we could then add sub-classes for more functionality.
The first sub-class simply took the X and Y outputs and held them, so they could be used by the next sub-class to pass the information to a RIB file.
def data(self, x, y):
With the class implementation, we can now create "instances" of the hilbert function, passing different arguments to each, generating multiple files.
if __name__ == '__main__':
hilbert1 = Hilbert(0.0, 0.0, 5.0, 0.0, 0.0, 5.0, 5)
We then made a new file, HilbertRib, that served as another sub-class of Hilbert. This file calls to the base class to generate the data, then processes it into a RIB file.
from HilbertClass import Hilbert
# This is a class (global) variable
rootpath = '/home/cfetze20/mount/stuhome/tech312/Hilbert/renderman/ribarchives/hilbert_'
def __init__(self, x0, y0, xi, xj, yi, yj, n, degree, width):
# Open a file for writing
self.fullpath = HilbertRib.rootpath + str(Hilbert.counter) + '.rib'
# Temporary storage for coordinates
self.temppath = '/temp/temp.rib'
self.temp = open(self.temppath, 'w')
self.line_counter = 0
#Opening and setting up the final RIB file
self.rib =open(self.fullpath, 'w')
self.rib.write('Basis "catmull-rom" 1 "catmull-rom" 1\n')
# Give the input data to the base class. This will fill up the temp file with xyz data.
Hilbert.__init__(self, x0, y0, xi, xj, yi, yj, n)
# Writing initial lines to final RIB
self.rib.write('Curves "cubic" [%d] "nonperiodic" "P" [' % (self.line_counter + 2))
# Open temp file again, for reading data
self.temp = open(self.temppath, 'r')
lines = self.temp.readlines()
# Transfer the temp data into final RIB
for n in range (len(lines)):
if n == 0:
if n == len(lines) - 1:
# Close the file - we're done
self.rib.write(']\n "constantwidth" [%1.3f]' % width)
# We override the implementation of the proc in the base class
def data(self, x, y):
self.temp.write('%s %s 0\n' % (x,y))
self.line_counter += 1
After we loaded the RIB into Maya, Malcolm gave us the "sparky" script, which traces a curve from keyframes 0 to 1, across it's UV's.
Rendering a sequence with this shader gave me the video at the top of the page.
Although I still find classes confusing, this exercise was a good introduction to the concept. I can see how using classes could be beneficial while writing scripts that handle multiple jobs and heavy workloads. Also, the Hilbert pattern was very interesting, and I had fun creating renders with it. I'm enjoying becoming reacquainted with Renderman's power and quality.