Sierpinski Fractal



The goal of this assignment was to create and manipulate a Sierpinski gasket using Cutter and Pixar's Renderman for Maya.


Initial Gasket Generation

The steps for generating the 3D points of the gasket are as follows:

  1. set four points that define the vertices of a tetrahedron,

  2. choose an arbitary location (seed point) within the tetrahedron,

  3. pick one vertex of the tetrahedron at random,

  4. find the mid point between the random vertex and the seed point,

  5. store the mid point in a list.

These steps are then repeated, with the newly generated midpoint serving as the new seed point on each loop.

# This code produces the coordinates of the midpoint between two 3D points.
from random import choice

def halfstep(p1,p2):
     xval = (p1[0] + p2[0]) / 2
     yval = (p1[1] + p2[1]) / 2
     zval = (p1[2] + p2[2]) / 2
     return (xval, yval, zval)

# Next, we wrote a short script to pick a random item from a given list.
from random import choice
def pickpnt(pnts):
     result = choice(pnts)
     return result


RIB Generation

Next, we wrote a script to generate these points in a loop, then write the coordinates into a .rib file. We can then take this file in Maya and use it to generate a renderable point cloud.


cloud = []
# Open a MEL script
rib = open('/home/cfetze20/mount/stuhome/tech312/Sierpinski/data/sier2.rib','w')
# Vertices of a tetrahedron
p1 = (-1.155, 0.052, -2.000)
p2 = (-1.155, 0.052, 2.000)
p3 = (2.309, 0.052, 0.000)
p4 = (0.000, 3.180, 0.000)
vertices = [p1,p2,p3,p4]

seed = (0.0, 0.5, 0.0)

rib.write('Points "P" [\n')

for n in range(1000000):
     vert = pickpnt(vertices)
     pos = halfstep(vert,seed)
     rib.write('%1.3f %1.3f %1.3f\n' % (pos[0],pos[1],pos[2]))
     seed = pos

rib.write('] "constantwidth" [0.01] \n')
rib.close()


I then began to alter the procedure. Adding a fourth side to the pyramid was as easy as listing a fifth point into the "vertices" group.

Next, I tried to implement pnoise into my generated points. The function is fairly straightforward, but figuring out the syntax took a little time. Finally, I figured out that it functions as follows:

rib.write('%1.13f %1.13f %1.13f\n' % (pnoise(pos[0],pos[0],pos[0]), pnoise(pos[1],pos[1],pos[1]), pnoise(pos[2],pos[2],pos[2])))

Renders


Conclusion

This exercise was fun, and a great introduction to Python. The Sierpinski gasket is an interesting concept, and I enjoyed manipulating the formula with Cutter. Additionally, the exercise was a great refresher on Renderman for Maya. This process could be improved by creating a UI in Maya to manipulate the settings, instead of having to compile new code for every tweak. Maybe I can achieve this at a later point in the course.