RenderMan Procedural Primitives
Implementations in Python, Tcl and 'C'

return to main index


A helper app is an executible that is loaded by a RenderMan complient renderer as a result of reading a Procedural "RunProgram" statement from a rib file or a rib stream. For example,

    Procedural "RunProgram" 
               ["H:/rman/helpers/hairball" "2.0  200  0.03"]
               [-2 2 -2 2 -2 2] 

In this example, the call to Procedural informs the renderer that it should run a program called hairball.exe located in the "H:/rman/helpers/" directory. The three parameters,

    "2.0 200 0.03"

are values that are passed to the program. The six values,

    "-2 2 -2 2 -2 2"

define the size of the bounding box of the geometry the helper app will create. When the renderer calls a helper app it not only passes the parameter values, it also calculates the number of pixels the bounding box of the object will cover in the rendered image. This value can help the app make level of detail decisions ie. should it generate a low, medium or a hi-res version of the geometry?

This tutorial provides the reader with simple example of the implementation and use of a helper app. Three implementations are given. Listing 2 is in the 'C' programming language, listing 3 is in Python, and listing 4 is in Tcl. All three implementations create the same geometry, a single quadric sphere, and all three implementations expect two parameters. The first, pixel coverage, is ignored. The second parameter specifies the radius of the sphere. It will be assumed the binary or script for each of the example implementations is located at one of the following locations,

    H:/rman/helpers/demo <.c .py .tcl>
    /home/$USER/rman/helpers/demo <.c .py .tcl>
    /Users/$USER/Documents/rman/helpers/demo <.c .py .tcl>

Basic Code

The following template code is based on the web notes, "Writing Procedural Primitives with RenderDotC"

Other sources of information about helper apps can be found by searching the RenderMan documents that accompany Pixars prman. Pages 119/120 of "Advanced RenderMan" by Tony Apodaca and Larry Gritz is also an excellent source of information about this topic. A sample python helper scipt that generates an arbitary number of polygons can be found in the tutorial "RSL:Color By Height".

Listing 1 is a simple rib file that can be used to run each of the helper apps provided in listings 2, 3 and 4.

Listing 1 (rib)

Display "untitled" "framebuffer" "rgba"
Format 400 400 1
Projection "perspective" "fov" 30
ShadingRate 5
# Head light
LightSource "distantlight" 1 "intensity" 1.5 "from" [0 0 0] "to" [0 0 1]
Translate  0 0 5
Rotate -30 1 0 0
Rotate 20   0 1 0
Scale 1 1 -1
        Surface "plastic"
        # Procedural "RunProgram" goes next. Refer to the notes on each
        # helper app implementation for examples of the correct syntax.

Python Implementation

Listing 2 (

import sys
args = sys.stdin.readline()
while args:
    arg = args.split()
    pixels = float(arg[0])
    rad = float(arg[1])
    print 'TransformBegin'
    print 'Sphere %s %s %s 360' % (rad, -rad, rad)
    print 'TransformEnd'
    # read the next set of inputs
    args = sys.stdin.readline()

In the rib file the script would be invoked as follows,

  # Windows
  Procedural "RunProgram" 
    ["python H:/rman/helpers/" "1"]
    [-1 1 -1 1 -1 1]
  # Linux
  Procedural "RunProgram" 
    ["/usr/bin/python /home/$USER/rman/helpers/" "1"]
    [-1 1 -1 1 -1 1]
  # MocOSX
  Procedural "RunProgram" 
    ["/usr/bin/python /Users/$USER/Documents/rman/helpers/" "1"] 
    [-1 1 -1 1 -1 1]

Tcl Implementation

Listing 3 (demo.tcl)

fconfigure stdout -translation binary
while { [gets stdin args] != -1 } {
    set pixels [lindex $args 0]
    set rad [lindex $args 1]
    puts "TransformBegin"
    puts "Sphere $rad -$rad $rad 360"
    puts "TransformEnd"
    puts "\377" 
    flush stdout

In the rib file the script would be invoked as follows,

  # Windows
  Procedural "RunProgram" 
    ["tclsh H:/rman/helpers/demo.tcl" "1"]
    [-1 1 -1 1 -1 1]
  # Linux
  Procedural "RunProgram" 
    ["/usr/bin/tclsh /home/$USER/rman/helpers/demo.tcl" "1"]
    [-1 1 -1 1 -1 1]
  # MocOSX
  Procedural "RunProgram" 
    ["/usr/bin/tclsh /Users/$USER/Documents/rman/helpers/demo.tcl" "1"] 
    [-1 1 -1 1 -1 1]

'C' Language Implementation

The code in listing 2 will build a helper app called demo.

Listing 4 (demo.c)

#include <stdio.h>
void main()
float pixels, rad;
char  args[256];
    sscanf(args, "%f %f", &pixels, &rad);
    printf("Sphere %f %f %f 360\n", rad, -rad, rad);
    printf("%c", '\377');

In the rib file this app would be invoked as follows,

  # Windows
  Procedural "RunProgram" 
    ["H:/rman/helpers/demo" "1"]
    [-1 1 -1 1 -1 1]
  # Linux
  Procedural "RunProgram" 
    ["/home/$USER/rman/helpers/demo" "1"]
    [-1 1 -1 1 -1 1]
  # MocOSX
  Procedural "RunProgram" 
    ["/Users/$USER/Documents/rman/helpers/demo" "1"] 
    [-1 1 -1 1 -1 1]

How it Works

Although it is not apparent from the code, the demo app automatically has access to three streams by which it can receive and send data, namely, stdin, stdout and stderr. Ordinarily, the first stream is connected to the keyboard, the others are connected to the console.

Figure 1

When the renderer invokes a helper app it redirects its own the stdin and stdout streams to those of the helper app so that, for example, input and output from functions/procs such as printf(), print and puts no longer use the console but instead "feed" data to the renderer.

© 2002- Malcolm Kesson. All rights reserved.