pfCAVE CAVE/Performer Library (CAVELib Version 2.6)
2 March 1997
- Electronic Visualization Laboratory
- University of Illinois at Chicago
- 851 S. Morgan St., Room 1120
- Chicago, IL 60607-7053
- (312) 996-3002
- (312) 413-7585 fax
(c) 1996,1997 Electronic Visualization Laboratory, University of Illinois at Chicago
Written by Dave Pape.
Introduction
pfCAVE is a small interface library which allows developers
to use Iris Performer in the CAVE. It takes care of
the details of creating Performer pipes and channels for the CAVE display,
and uses CAVE library functions to handle tracking and to generate the
correct perspective projections. It also provides some functions to translate
between the two different coordinate systems used by Performer and the CAVE.
The current version of pfCAVE is for Performer version 2.0 and
includes the "Performer coordinates" version of the CAVE library.
Basic pfCAVE Program
The basic form of a Performer/CAVE program is as follows:
#include <Performer/pf.h>
#include <pfcave.h>
pfScene * create_scene(void);
int main(int argc,char **argv)
{
pfInit();
pfCAVEConfig(&argc,argv,NULL);
pfConfig();
pfCAVEInitChannels();
/* In C, do this: */
pfChanScene(pfCAVEMasterChan(),create_scene());
/* In C++, do this instead:
pfCAVEMasterChan()->setScene(create_scene());
*/
while (!getbutton(ESCKEY))
{
pfSync();
pfCAVEPreFrame();
pfFrame();
pfCAVEPostFrame();
}
pfCAVEHalt();
pfExit();
}
pfScene * create_scene(void)
{
return pfNewScene();
}
These function calls must be added to a Performer program in order
to use the pfCAVE library:
- pfCAVEConfig(&argc,argv,NULL)
- The equivalent of CAVEConfig(). This must be called after
pfInit() and before pfConfig().
- pfCAVEInitChannels()
- Creates all the channels, and makes them a single channel group.
This must be called after pfConfig().
- pfCAVEPreFrame()
- Updates the tracker data and sets up new projections for each channel.
Should be called once per frame before pfFrame().
- pfCAVEPostFrame()
- Updates non-latency-critical data. Should be called once per frame
after pfFrame().
The header file (pfcave.h) is in /usr/local/CAVE/include;
the library binaries (libpfcave_igl.a and libpfcave_ogl.a)
are in /usr/local/CAVE/lib.
pfCAVE Functions
Overview
As shown in the example program above, the functions pfCAVEConfig,
pfCAVEInitChannels, pfCAVEPreFrame,
and pfCAVEPostFrame take care of the basic CAVE control, and
must be called in any pfCAVE program.
The CAVE library contains functions to set up transformations based on
tracker or navigation data. pfCAVE provides DCS functions to add
equivalent transformations to a Performer scene graph.
pfCAVEDCSHeadTransform, pfCAVEDCSWandTransform,
pfCAVEDCSSensorTransform,
pfCAVEDCSNetHeadTransform, pfCAVEDCSNetWandTransform,
and pfCAVEDCSNavTransform will each update a DCS with the latest
transformation that would be generated by the similarly named CAVE function.
The DCS will need to be updated once per frame using these functions.
pfCAVE defines its own channel draw function (via pfChanTravFunc)
in order to handle the stereo buffering and the additional rendering
for the simulator and arpafloor displays. This function calls
pfDraw to render the Performer scene graph. If an application
needs to call its own rendering functions as well, it can do so
by registering draw callbacks with pfCAVEPreDrawFunc, pfCAVEDrawFunc,
or pfCAVEPostDrawFunc.
Functions
- pfList * pfCAVEChannels(void)
- Returns a pfList which contains pointers to all of the channels created
by pfCAVE (the elements are all of type pfChannel *).
- void pfCAVEConfig(int *argc, char **argv, char **appdefaults)
- Reads the CAVE configuration, and initializes pfCAVE operations.
This function calls CAVEConfigure (passing it argc,argv,appdefaults)
to initialize the CAVE library data. It then configures Performer in
multipipe mode for the number of walls selected, and starts the CAVE
tracking and networking processes if they are needed.
pfCAVEConfig must be called after pfInit and before
pfConfig.
- void pfCAVEDCSHeadTransform(pfDCS *dcs)
- Modifies the given pfDCS to contain the same translation and rotation
as the head tracker (the scaling part of the DCS is not changed).
The data used are in CAVE tracker coordinates.
- void pfCAVEDCSNavTransform(pfDCS *dcs)
- Modifies the given pfDCS to contain the current CAVE navigation
transformation. This DCS will transform from physical tracker coordinates
to navigated world coordinates; tracker coordinates are the base pfCAVE
coordinate system, so this DCS should not be under any other DCS/SCS in
a scene graph.
- void pfCAVEDCSNetHeadTransform(pfDCS *dcs,volatile CAVE_USER_ST *user)
- Modifies the given pfDCS to contain the same translation and rotation
as the head tracker for the networked user user
(the scaling part of the DCS is not changed).
The data used are in navigated coordinates, so the DCS should be placed under
a CAVE navigation DCS (pfCAVEDCSNavTransform).
- void pfCAVEDCSNetWandTransform(pfDCS *dcs,volatile CAVE_USER_ST *user)
- Modifies the given pfDCS to contain the same translation and rotation
as the wand tracker for the networked user user
(the scaling part of the DCS is not changed).
The data used are in navigated coordinates, so the DCS should be placed under
the CAVE navigation DCS (pfCAVEDCSNavTransform).
- void pfCAVEDCSWandTransform(pfDCS *dcs)
- Modifies the given pfDCS to contain the same translation and rotation
as the wand tracker (the scaling part of the DCS is not changed).
The data used are in CAVE tracker coordinates.
- void pfCAVEDCSSensorTransform(pfDCS *dcs,CAVE_SENSOR_ST *sensor)
- Modifies the given pfDCS to contain the same translation and rotation
as the given sensor (the scaling part of the DCS is not changed).
The data used are in CAVE tracker coordinates.
- void pfCAVEDrawFunc(pfChanFuncType func)
- Sets a drawing callback function. func will be
called by pfCAVE's channel draw function in place of pfDraw.
It will be passed pointers to the channel and the channel data.
- void pfCAVEHalt(void)
- Cleans up before exiting. pfCAVEHalt calls CAVEHalt and
runs the exit commands (from the configuration file) for each active wall.
It should be called prior to pfExit.
- void pfCAVEInitChannels(void)
- Creates the pfCAVE channels. This function creates a separate channel
for each (eye,wall) combination that is active. The channels are
all put into a single channel group, which shares the scene, EarthSky model,
cull function, draw function, near & far clipping planes, and buffer
swap.
pfCAVEInitChannels should be called after pfConfig.
- pfChannel *pfCAVEMasterChan(void)
- Returns the 'master' channel from the pfCAVE channel group.
- pfList * pfCAVEPipes(void)
- Returns a pfList which contains pointers to all the pipes that were
created (the elements are all of type pfPipe *).
- void pfCAVEPostDrawFunc(pfChanFuncType func)
- Sets a post-pfDraw application callback. func will be
called by pfCAVE's channel draw function immediately after pfDraw.
It will be passed pointers to the channel and the channel data.
- void pfCAVEPostFrame(void)
- Performs non-latency-critical post rendering actions.
pfCAVEPostFrame currently only updates CAVE networking data.
It should be called at the end of the frame loop, after pfFrame.
- void pfCAVEPreDrawFunc(pfChanFuncType func)
- Sets a pre-pfDraw application callback. func will be
called by pfCAVE's channel draw function immediately before pfDraw.
It will be passed pointers to the channel and the channel data.
If no pre-draw callback has been set, the pfCAVE channel draw function
calls pfClearChan; if a callback has been set, it is up to the
callback to clear the channel.
- void pfCAVEPreFrame(void)
- Performs latency-critical pre-rendering actions.
This function updates tracking and sets up the
projections for each of the pfCAVE channels.
It should be called once per frame, before pfFrame.
Special Notes
Simulator mode
pfCAVE supports the CAVE simulator display and tracking. The simulator
display includes the same controls and the CAVE and wand rendering as in
the CAVE library; the timing command displays Performer's channel
statistics.
Tracking is updated in the main application process (by
pfCAVEPreFrame); when multiprocessing, this process does not have
a window associated with it, so there is no advantage to using serial tracking
with the simulator tracker. In fact, it can significantly increase the time
taken by the application stage. In this case, you may get better
performance by adding 'SerialTracking n' to your configuration
for simulator mode (after 'Simulator y' or 'TrackerType simulator').
CAVE library functions & variables
All of the normal CAVE library functions and global variables can be
used in a pfCAVE application, with the following exceptions:
- *CAVETime is not updated; use pfGetFrameTimeStamp() instead.
- *CAVEFramesPerSecond is not updated.
- The function CAVEWallTransform() is not available.
- CAVEInit, CAVEDisplay, CAVEInitApplication,
CAVEFrameFunction, and CAVEStopApplication should not be called.
- Only the network related callbacks should be used with CAVEAddCallback.