26.01.2015 Views

The RenderMan Interface - Paul Bourke

The RenderMan Interface - Paul Bourke

The RenderMan Interface - Paul Bourke

SHOW MORE
SHOW LESS
  • 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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!