The RenderMan Interface - Paul Bourke
The RenderMan Interface - Paul Bourke
The RenderMan Interface - Paul Bourke
- No tags were found...
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
A more efficient method for accessing subdivision routines is to write them as dynamic<br />
shared objects (DSOs) 1 , and dynamically load them into the renderer executable<br />
at run-time. In this case, you write your subdivision and free routines in C, exactly<br />
as you would if you were writing them to be linked into the renderer using the C<br />
RiProcedural interface. DSOs are compiled with special compiler options to make<br />
them run-time loadable and are specified in the RIB file by the name of the shared<br />
object file. <strong>The</strong> renderer will load the DSO the first time that the subdivision routine<br />
must be called, and from then on, it is called as if (and executes as fast as if) it were<br />
statically linked. DSOs are more efficient than external programs because they avoid<br />
the overhead of interprocess communication.<br />
When writing a procedural primitive DSO, you must create three specific public subroutine<br />
entry points, named Subdivide, Free, and ConvertParameters. Subdivide is a<br />
standard RiProcedural() primitive subdivision routine, taking a blind data pointer to<br />
be subdivided and a floating-point detail to estimate screen size. Free is a standard<br />
RiProcedural primitive free routine, taking a blind data pointer to be released. ConvertParameters<br />
is a special routine that takes a string and returns a blind data pointer.<br />
It will be called exactly once for each DynamicLoad procedural primitive in the RIB<br />
file, and its job is to convert a printable string version of the progenitor’s blind data<br />
(which must be in ASCII in the RIB file), into something that the Subdivide routine<br />
will accept.<br />
<strong>The</strong> C prototypes for these functions are as follows:<br />
RtPointer ConvertParameters(char * initialdata );<br />
void Subdivide(RtPointer blinddata, RtFloat detailsize );<br />
void Free( RtPointer blinddata );<br />
Note that if the DSO Subdivide routine wants to recursively create child procedural<br />
primitives of the same type as itself, it should specify a direct recursive call to<br />
itself, with RiProcedural(newdata,newbound,Subdivide,Free), not call itself as a DynamicLoad<br />
procedural. <strong>The</strong> latter would eventually just call the former after wasting<br />
time checking for and reloading the DSO.<br />
<strong>The</strong> conventions for how dynamic objects are compiled are implementation-dependent<br />
(and also very likely OS-dependent).<br />
RIB BINDING<br />
Procedural ”DynamicLoad” [dsoname paramdata] [boundingbox]<br />
<strong>The</strong> argument list is an array of two strings. <strong>The</strong> first element is the name of the<br />
shared object file that contains the three required entry points and has been compiled<br />
and prelinked as described earlier. <strong>The</strong> second element is the ASCII printable<br />
string that represents the initial data to be sent to the ConvertParameters routine. <strong>The</strong><br />
boundingbox is an array of six floating-point numbers, which is xmin, xmax, ymin,<br />
ymax, zmin, zmax in the current object space.<br />
EXAMPLE<br />
RtString args[] = { ”mydso.so”, ”” };<br />
RtBound mybound = { -1, 1, -1, 1, 0, 6 };<br />
RiProcedural ((RtPointer)args, mybound, RiProcDynamicLoad, RiProcFree);<br />
1 on some systems called dynamically linked libraries, or DLLs<br />
91