# lrib.py # One of 7 python scripts that implement a simple L system. # Useage: # lrib.render(lstring, path_to_output_rib, database) # # The database is created by lscriptreader.py. # The output (archive) rib file should be rendered by a RenderMan Compliant # renderer. A sample beauty pass rib that can be used to render the geometry # produced by the lrib module is also included in the collection of L system # scripts. It is named "archive_tester.rib". # # Malcolm Kesson # 18 Jan 2012, 26 Jan 2012 import os, random from math import fabs from lmel import getval Cs_stack = [] Os_stack = [] def decr_comp(index, delta): r,g,b = Cs_stack.pop() temp = [r,g,b] temp[index] -= delta if temp[index] < 0.0: temp[index] = 0.0 Cs_stack.append(temp) return temp def incr_comp(index, delta): r,g,b = Cs_stack.pop() temp = [r,g,b] temp[index] += delta if temp[index] > 1.0: temp[index] = 1.0 Cs_stack.append(temp) return temp # Interpret the L string def render(lstr, ribfile, database): rib = [] move_data = database['move'] angle_data = database['angle'] scale_data = database['scale'] curvewidth_data = database['curvewidth'] rgb_delta = database['rgb_delta'] scale_invert_stack = [] scale_invert = False scale_invert_stack.append(scale_invert) move_sign = 1 angle_sign = 1 # RenderMan specific attributes red_sign = 1 green_sign = 1 blue_sign = 1 opaciy_sign = 1 # Lock the random number generator random.seed(database['seed']) Cs_stack.append([1.0,1.0,1.0]) Os_stack.append([1,1,1]) for c in lstr: # Transformations_______________________ if c == '+': move_sign = 1 elif c == '-': move_sign = -1 elif c == '>': angle_sign = 1 elif c == '<': angle_sign = -1 elif c == 'S': scale_invert = (True, False)[scale_invert == True] # toggle True/False elif c == 'x': rib.append('Rotate %1.3f 1 0 0\n' % (fabs(getval(angle_data)) * angle_sign)) elif c == 'y': rib.append('Rotate %1.3f 0 1 0\n' % (fabs(getval(angle_data)) * angle_sign)) elif c == 'z': rib.append('Rotate %1.3f 0 0 1\n' % (fabs(getval(angle_data)) * angle_sign)) elif c == 's': scale = getval(scale_data) scale = (scale, 1.0/scale)[scale_invert == True] rib.append('Scale %1.3f %1.3f %1.3f\n' % (scale, scale, scale)) elif c == 'X': rib.append('Translate %1.3f 0 0 $tnode;\n' % (fabs(getval(move_data)) * move_sign)) elif c == 'Y': rib.append('Translate 0 %1.3f 0 $tnode;\n' % (fabs(getval(move_data)) * move_sign)) elif c == 'Z': rib.append('Translate 0 0 %1.3f $tnode;\n' % (fabs(getval(move_data)) * move_sign)) # Attribute Stack_______________________ elif c == '{': cs = Cs_stack[len(Cs_stack) - 1] Cs_stack.append(cs); rib.append('AttributeBegin\n') scale_invert_stack.append(scale_invert) elif c == '}': cs = Cs_stack.pop(); rib.append('AttributeEnd\n') scale_invert = scale_invert_stack.pop() # Attributes____________________________ elif c == 'r': r,g,b = decr_comp(0, getval(rgb_delta)) elif c == 'g': r,g,b = decr_comp(1, getval(rgb_delta)) elif c == 'b': r,g,b = decr_comp(2, getval(rgb_delta)) elif c == 'R': r,g,b = incr_comp(0, getval(rgb_delta)) elif c == 'G': r,g,b = incr_comp(1, getval(rgb_delta)) elif c == 'B': r,g,b = incr_comp(2, getval(rgb_delta)) # Geometry______________________________ elif c == '4': r,g,b = Cs_stack[len(Cs_stack) - 1] rib.append('Color %1.3f %1.3f %1.3f\n' % (r,g,b)) rib.append('Cone 0.25 1 360\n') rib.append('Translate 0 1 0\n') elif c == '1': r,g,b = Cs_stack[len(Cs_stack) - 1] rib.append('Color %1.3f %1.3f %1.3f\n' % (r,g,b)) rib.append('Curves "linear" [2] "nonperiodic" "P" [0 0 0 0 1 0]\n') rib.append(' "constantwidth" [%1.3f]\n' % (fabs(getval(curvewidth_data)))) rib.append('Translate 0 1 0\n') script_path = database['script_path'] # lprocedural does not provide a path to an output rib file # because it pipes the rib statements to prman directly. if len(ribfile) == 0: return ''.join(rib) else: # Copy the text from the original script so that it can be put # into the output rib file as a header comment script_text = '' if os.path.exists(script_path) and os.path.isfile(script_path): f = open(script_path, 'r') temp = f.readlines() f.close() lines = [] for line in temp: lines.append('# %s' % line) script_text = ''.join(lines) f = open(ribfile, 'w') f.write('# Created by "%s"\n' % script_path) f.write('%s\n' % script_text) f.write('AttributeBegin\n') f.write(''.join(rib)) f.write('AttributeEnd\n') f.close()