This document is not an introduction to the RenderMan interface
itself, it just explains the usage of this particular Python
binding. The binding was written to be compliant to v3.2 of Pixar's
RenderMan Interface specification. However, it also supports some
newer features such as string handles for light sources or object
instances.
2. Using the API
It is safe to import the module using
from ri import *
All the functions that get imported start with the prefix
"Ri
", all constants start with "RI_
" or
"RIE_
", so you probably won't get into a naming conflict.
After importing the module this way you can use the functions just as you're used to from the C API (well, almost).
from ri import *
|
The parameter to RiBegin() determines where the output is directed to. You can pass one of the following:
Example (inside an interactive Python session):
>>> from ri import * >>> print RiPatch.__doc__ RiPatch(type, paramlist) type is one of RI_BILINEAR (4 vertices) or RI_BICUBIC (16 vertices). Number of array elements for primitive variables: ------------------------------------------------- constant: 1 varying: 4 uniform: 1 vertex: 4/16 (depends on type) Example: RiPatch(RI_BILINEAR, [0,0,0, 1,0,0, 0,1,0, 1,1,0]) |
or using the pydoc module:
>>> from pydoc import help # this line isn't required anymore in Python 2.2 or later >>> from ri import * >>> help(RiMotionBegin) Help on function RiMotionBegin in module ri: RiMotionBegin(*times) Start the definition of a moving primitive. You can specify the time values directly or inside a sequence, for example, RiMotionBegin(0,1) or RiMotionBegin([0,1]). Example: RiMotionBegin(0.0, 1.0) RiTranslate(1.0, 0.0, 0.0) RiTranslate(1.0, 2.0, 0.0) RiMotionEnd() |
or from the shell (outside the Python shell):
$ pydoc ri.RiCropWindow Python Library Documentation: function RiCropWindow in ri RiCropWindow(left, right, bottom, top) Specify a subwindow to render. The values each lie between 0 and 1. Example: RiCropWindow(0.0, 1.0 , 0.0, 1.0) (renders the entire frame) RiCropWindow(0.5, 1.0 , 0.0, 0.5) (renders the top right quarter) |
Wherever the API expects vector types (RtPoint, RtMatrix, RtBound, RtBasis) you can use any value that can be interpreted as a sequence of the corresponding number of scalar values. These can be lists, tuples or your own class that can be used as a sequence.
It is also possible to use nested sequences instead of flat ones. For example, you can specify a matrix as a list of 16 values or as a list of four 4-tuples. The following two calls are identical:
RiConcatTransform([2,0,0,0, 0,2,0,0, 0,0,2,0, 0,0,0,1])
|
RiSurface("plastic", "kd", 0.6, "ks", 0.4)
RiSurface("plastic", "kd", 0.6, "ks", 0.4, RI_NULL)
RiSurface("plastic", "kd", 0.6, "ks", 0.4)
Alternatively, you can use keyword arguments:
RiSurface("plastic", kd=0.6, ks=0.4)
But note that you can't use inline declarations using keyword
arguments. Instead you have to previously declare those variables
using RiDeclare. Also, you can't use keyword arguments if the token
is a reserved Python keyword (like the standard "from" parameter).
The third way to specify the parameter list is to
provide a dictionary including the token/value pairs:
RiSurface("plastic", {"kd":0.6, "ks":0.4})
This is useful if you generate the parameter list on the fly in your program.
For example, in C you might write:
RtPoint points[4] = {0,1,0, 0,1,1, 0,0,1, 0,0,0};
RiPolygon(4, RI_P, (RtPointer)points, RI_NULL);
The number of points has to be specified explicitly. In Python however, this call could look like this:
points = [0,1,0, 0,1,1, 0,0,1, 0,0,0]
RiPolygon(RI_P, points)
The functions that are affected by this rule are:
RiBlobby()
RiColorSamples()
RiCurves()
RiGeneralPolygon()
RiMotionBegin()
RiPoints()
RiPointsGeneralPolygons()
RiPointsPolygons()
RiPolygon()
RiSubdivisionMesh()
RiTransformPoints()
RiTrimCurve()
4.4 User defined functions
Some RenderMan functions allow to take user defined functions as
input which will be used during rendering. Since this implementation
only outputs RIB streams it's not possible to use your own functions
in these cases, instead you always have to use one of the predefined
functions.
RiTranslate()
,
RiRotate()
, RiScale()
and RiSkew()
have been extended in a way that is not part of the official spec.
Each of these functions takes one or two vectors as input which
usually are provided as 3 separate scalar values, like the axis
of a rotation for example:
RiRotate(45, 0,0,1)
Now in this implementation you can choose to provide such vectors as sequences of 3 scalar values:
axis = vec3(0,0,1)RiRotate(45, [0,0,1])
RiRotate(45, axis)
4.6 Empty stubs
All the functions do what they're supposed to do (well, hopefully ;)
except for the function RiTransformPoints(). This function is defined
but it does nothing, it's only an empty stub (since the module only
outputs RIB and doesn't maintain transformation matrices).
5. Implementation specific options
There's currently one option that's specific to this RenderMan binding
and that won't produce any RIB call but will control what gets written
to the output stream:
If you install a new error handler with RiErrorHandler() only the three standard error handlers will produce an output in the RIB stream, if you install RiErrorException or your own handler then the handler is installed but no RIB output is produced.
The module does some error checking, however there are still quite a bit of possible error cases that are not reported. For example, the module checks if parameters are declared, but it is not checked if you provide the correct number of values. In general, the module also does not check if a function call is valid in a given state (e.g. the module won't generate an error if you call RiFormat() inside a world block).
The RenderMan (R) Interface Procedures and Protocol are:
Copyright 1988, 1989, 2000, Pixar
All Rights Reserved
RenderMan (R) is a registered trademark of Pixar