4.3.3 Differences between the C and Python API

The Python RenderMan binding is rather close to the C API, however there are some minor differences you should know about.

Types

In this binding typing is not as strict as in the C API. For compatibility reasons, the RenderMan types (RtBoolean, RtInt, RtFloat, etc.) do exist but they are just aliases to the corresponding built-in Python types and you never have to use them explicitly. In the ctypes-based cri module, the types refer to the respective ctypes types and you may want to use them occasionally to construct arrays.

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]) 

RiConcatTransform([[2,0,0,0], [0,2,0,0], [0,0,2,0], [0,0,0,1]])

Parameter lists

When passing parameter lists you have to know the following points:

Arrays

In the C API functions that take arrays as arguments usually take the length of the array as a parameter as well. This is not necessary in the Python binding. You only have to provide the array, the length can be determined by the function.

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()

When using the cri module it is particularly advantageous to pass arrays as ctypes arrays or numpy arrays. In this case, no data conversion is required which makes the function call considerably faster (particularly for large amounts of data).

# Creating a ctypes array of floats
points = (12*RtFloat)(0,1,0, 0,1,1, 0,0,1, 0,0,0)

# Creating a numpy array of floats
points = numpy.array([0,1,0, 0,1,1, 0,0,1, 0,0,0], dtype=numpy.float32)

User defined functions

Some RenderMan functions may take user defined functions as input which will be used during rendering. When using the cri module to link to an actual RenderMan library you can use Python functions in addition to the standard functions. However, in the case of the generic (ri) module, you can only use the predefined standard functions.

Filter functions

It is not possible to use your own filter functions in combination with the ri module, you have to use one of the predefined filters:

Procedurals

It is not possible to use your own procedurals directly in the RIB generating program, you can only use one of the predefined procedural primitives:

However, this is not really a restriction since you always can use RiProcRunProgram to invoke your Python program that generates geometry.

Extended transformation functions

The transformation 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:

RiRotate(45, [0,0,1]) 

axis = vec3(0,0,1)
RiRotate(45, axis)

Empty stubs

In the ri module, the function RiTransformPoints() always returns None and never transforms points (as the module just outputs RIB and does not maintain transformations matrices). In the cri module, on the other hand, the function is available and can be used to transform points.