pfCAVE CAVE/Performer Library, Version 2.0

June 6, 1996

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 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();
 pfChanScene(pfCAVEMasterChan(),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 pre-draw or post-draw callbacks with pfCAVEPreDrawFunc and pfCAVEPostDrawFunc.

Functions

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 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.
void pfCAVEInitChannels should be called after pfConfig.
pfChannel *pfCAVEMasterChan(void)
Returns the 'master' channel from the pfCAVE channel group.
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. Only simulator display mode 1 (perspective view) is currently available.

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').

Also, because the tracking is not associated with a window, the simulator joystick control is always based on the mouse's screen position, rather than window position.

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: