Changes in CAVE Library Version 2.6f
(released 27 February 1998)
Applications should be recompiled from source, using the new headers,
before linking with the 2.6 library, due to these changes.
Bug fixes from Versions 2.5.6 a - f
- 2.5.6a (16 June 1996) - Fixed bug in multisampling in OpenGL library;
had been possible to get a multisampled color buffer with no
- 2.5.6b (13 July) - Fixed networking bug in pfCAVE libraries;
incorrect orientation data was being broadcast.
- 2.5.6c (15 July) - Fixed serious networking bug which caused
application data to be mangled when using CAVENetReceive().
- 2.5.6d (4 November) - Fixed networking bug which messed up CAVEUser
array when a user was deleted.
- 2.5.6e (11 November) - Made DefaultTrackerPosition configuration option
be scaled by Units and CAVEScale options.
CPUlocking is disabled if the system call to mplock fails.
- 2.5.6f (2 February 1997) - Fixed various bugs in pfCAVE libraries - stereo
projection was wrong when the head roll angle was non-zero
(when the user tilts his head); HMD projection was completely wrong;
CAVEGetVector() computed incorrect up, down, left, and right vectors;
CAVEGetSensorOrientation() reversed azimuth & roll.
Significant new features
- N32 & 64
- There are now n32 and 64-bit versions of the OpenGL CAVE and pfCAVE libraries.
They are -lcave_ogl_n32, -lcave_ogl_64, -lpfcave_ogl_n32, and -lpfcave_ogl_64.
The default versions of the library are still the old 32-bit format.
- New display process design
- The display loop and window management have been redesigned to better support
having multiple displays on a single graphics pipe, such as in a 2-IR
4 wall CAVE. All walls which use the same display (except
those with "window" geometry) are handled by a single process.
The rendering process opens one window which contains all of the walls'
display areas, and switches viewports appropriately when rendering.
Note that OpenGL applications should not disable the Scissor Test while
clearing the screen, or they will fail under this system.
The display function is called for each [wall,eye] combination being
rendered by a process; the FrameFunction
is called only once per frame in each display process, not once per wall;
similarly, the InitApplication function is only called once by each process.
The variable CAVEWall is considered undefined during the FrameFunction and
InitApplication callbacks (see the function CAVEGetPipeChannels()
if you need an equivalent). Also, CAVEMasterDisplay() can now return
true for multiple walls; use CAVEMasterWall() if you need to identify
a single wall, as opposed to a single display process.
The pfCAVE library uses the same approach to define its Performer pipes
and channels (in fact, the idea for the new design was
stolen from Performer).
- New display options
- Several new configuration options have been added which greatly expand the
flexibility of the display system:
- ProjectionData - The special HMD walls 'left_eye' and 'right_eye' have been
removed; instead their functionality has been merged with the 'screen#'
walls. The ProjectionData option replaces the old ProjectionCorners option,
which is no longer used. It adds a field for specifying whether a screen
is a 'wall' (as in a CAVE, IDesk, or IWall), or an 'hmd' (as in a helmet
display or BOOM). There is also a field for specifying the eye(s) along
with the wall being configured, allowing different screen corners to be
given for the left and right eyes' views; this is primarily useful with HMDs.
- Viewport - The Viewport option defines a subregion within a wall's
window which will be used for a given eye's rendering viewport. This
can be used to replicate the functionality of the 'oldstereo' display mode
or the 'dual_eye' wall, both of which have been removed.
- Colormask - The Colormask defines which color channels (red, green,
or blue) are to be used when rendering a given [wall,eye] display. This
can be used to generate anaglyphic stereo.
One major problem - this will not work if you call czclear() or,
on Reality Engines, glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT).
You must make
separate clear calls (clear();zclear(); or glClear(GL_COLOR_BUFFER_BIT);
- ViewportMask - A viewport mask file can be created, which consists of
a list of polygons covering areas of the screen which are to be blacked out.
The mask is drawn by the library after the application's display function has
This can be used to create non-rectangular viewports, and to replace the
'arpafloor' wall, which has been removed.
- Distributed CAVE redesign
- The internal design of the 'distributed CAVE' code (i.e. that for a CAVE system
using multiple workstations to drive all the displays) has been completely
revised. This change should be mostly invisible to applications, with the
exceptions that more than two machines are now supported (up to 32), and
that the raw Hippi protocol is no longer supported (it tended to be worse
than TCP over Hippi for the small data packets typically used in CAVE
CAVEDisplay(), CAVEInitApplication(), and CAVEFrameFunction() now
all synchronize between machines in distributed CAVE, before setting
function pointers. This should help make sure that application functions are
first called at the same frame on each machine.
A new programming interface has been created to help programs share and
synchronize application data between machines in a distributed CAVE.
This is described in the "New4Wall" page.
(It is unchanged since alpha3, except for bug fixes.)
- Projection code revision
- The method for setting up the CAVE projection transformation has been changed.
The transformation can now be entirely loaded into the Projection matrix,
without using the ModelView matrix. This should cause reflection-mapped
textures and specular highlights to match accurately between walls of the CAVE
(however, it breaks fog).
As of beta3, this option is enabled by calling CAVESetOption(CAVE_PROJ_USEMODELVIEW,0).
Note: this change only applies to the base IrisGL/OpenGL CAVE libraries,
not to the Performer CAVE libraries.
New library functions
- CAVEProcessType() - indicates whether the calling process is a display
or application process.
- CAVEDisplaySync() - blocks until the end of the current frame being
rendered. This function can be used by
any number of processes simultaneously, and is preferable to the
old method of using CAVEDisplay()'s blocking side-effect.
- CAVEGetFrameNumber() - returns the number of the current frame being
rendered. Frames are numbered starting from 0. Given the new display
loop design, this is more reliable than counting the number of times the
display function has been called.
- CAVENavWorldTranslate(), CAVENavWorldRot(), CAVENavWorldScale(),
CAVENavPreMultMatrix() - allow navigation transformations to be done in
world coordinates, rather than CAVE coordinates.
- CAVEScramnetMalloc(), CAVEScramnetFree() - allocates/frees chunks
of Scramnet memory. To use these functions, you must call
CAVESetOption(CAVE_SCRAMNET_ARENASIZE,...) to set the Scramnet arena size,
as the default size is 0. NB: CAVEMalloc(), which previously could be configured
to use Scramnet memory, now only allocates regular Unix shared memory.
- CAVEGetViewport() - returns the viewport geometry for the view currently
being rendered (should only be called from within the display callback).
- CAVEMasterWall() - returns TRUE if the wall currently being rendered
is the 'master' wall. This supplements CAVEMasterDisplay(), which will
return TRUE for any wall which is being drawn by the master rendering
- CAVEGetPipeChannels() - returns a set of flags indicating which [wall,eye]
views are being rendered by the calling process. This is a generalized
alternative to the CAVEWall variable for the new display system.
- CAVEGetActiveChannels() - returns a set of flags indicating all of
the [wall,eye] views that are being rendered by the application.
- CAVEXDisplay(), CAVEXWindow(), CAVEXVisualInfo(),
CAVEGLXContext() - return X window information for the display process
(OpenGL library only).
- CAVEWallName() - returns a string with the name corresponding to a
- CAVENewID() - returns a unique integer; can be used to generate IDs for
the new distributed CAVE system's display data.
- pfCAVEChannels() - returns a pfList of all the pfChannels that are active
in a pfCAVE application.
- pfCAVEPipes() - returns a pfList of all the pfPipes that are active
in a pfCAVE application.
- pfCAVEDrawFunc() - defines a drawing callback function, to be called in
place of pfDraw().
New configuration options
There are now brief and full versions of the configuration information that is
printed when a program starts; the brief version is the default. The environment
variable CAVEDEBUGCONFIG can be used to select what is printed; possible values
are 'off' (don't print any config info at all), 'brief', 'full', and 'verbose'
(print every option as it is read).
- StereoBuffer - A flag indicating whether to use stereo quadbuffering.
When this is 'y', left eye views are rendered in the left buffer and right
eye views are rendered in the right buffer; when 'n', both views use the
same buffer, and should be separated by different Viewports or Colormasks.
- Exec - Gives a shell command which will be executed via a system()
call as soon as the line is encountered.
- CAVETranslate, CAVERotate, CAVERotationMatrix - These options can be used to shift
the CAVE to a different location in the virtual space, or rotate it.
The projection data for the walls and the tracking data are modified by
the translation and rotation (and the CAVEScale option); CAVENavRot()
is also modified in order to still rotate about the center of the shifted
- Scramnet - When the Scramnet option is 'n', a chunk of regular shared
memory is created to simulate Scramnet memory. The simulated Scramnet will
be used exactly the same as actual physical Scramnet, except for not being
shared between machines.
- SimScramKey - If the SimScramKey option is set to a non-zero value, the
simulated Scramnet memory (when used) will be a System V style shared memory
segment with the given key. This allows multiple independent copies of a
program running on a single machine to communicate through the simulated
Scramnet, just as they would through real Scramnet when running on separate
- ScramnetPrefix - The ScramnetPrefix is a 16-bit value which will be
prefixed to all Scramnet memory segment IDs when the library allocates
pieces of Scramnet for various tasks. The purpose of this option is to
allow multiple independent CAVE systems to share a single Scramnet network
- SyncBirds - This option now accepts the values 'type1', 'type2', or 'n'.
- ActiveSensors - A list of which tracker sensors are to be considered
active. The tracking process (or daemon) will read all of the tracker's
sensors, but only the data from those listed in ActiveSensors will be
used by the library; all the other sensors will be set to the DefaultTrackerPosition
and DefaultTrackerOrientation values. The values are 0=head sensor, 1=wand
sensor, 2=second wand, etc.
- TrackerPort - The TrackerPort option will now accept up to CAVE_MAX_SENSORS
values. (However, none of the current tracker drivers actually use more than
- Network UDP - The UDP option for networking is a simple, non-multicast
UDP protocol. It can be used point-to-point between two CAVEs, or with
a server (as soon as one is written).
- NetworkUDPHost - Specifies the name of the remote host to communicate with
when using UDP networking mode.
- MOUSEWINX, MOUSEWINY - These pseudo-device names can
now be used in config files for options such as ControllerValuators.
These devices return the mouse pointer's position in window coordinates,
rather than screen coordinates as reported by MOUSEX/MOUSEY.
- VerboseConfig - Used to switch the verbose configuration debugging
mode on and off within a config file.
- Controller - The 'Wand' option is now officially called 'Controller',
for consistency. 'Wand' is still supported, however.
- ProjectionData, Viewport, Colormask, ViewportMask -
Bug / Feature fixes
- Borderless OpenGL windows will now be opened automatically, without requiring
changes to your .Xdefaults.
- Simulator view modes 0 and 2 (wall-view and outside-view) are available in pfCAVE.
- The OpenGL simulator will display timing information in the graphics window, as
in the IrisGL version.
- Fixed a bug in the networking code where the CAVEUser list could become messed
up when there are more than 2 users, and users leave and re-enter over the
course of time.
- CAVEWallTransform() should work for all wall types.
- CAVEGetWindowGeometry() returns the geometry of the actual GLX window
that is being used, rather than of its framing parent window (in the OpenGL library).
- The DefaultTrackerPosition config value is correctly converted when Units other
than feet are used.
- Applications can no longer reinitialize the Scramnet header and memory segment
table (there were too many problems being caused by this). A separate program
(scramctl) must be used to initialize or alter this data.
- Functions which get data in navigated coordinates (e.g.
CAVEGetPosition( CAVE_HEAD_NAV, ...) ) will use the saved copy
of the nav matrix (that used by CAVENavTransform()) when called
in a display process. Previously they used the 'global' matrix,
which could be different (i.e. newer) than the one for
- OpenGL windows are cleared when they are first opened.
- It should (finally) be possible to call CAVEDisplay(),
CAVEInitApplication(), and CAVEFrameFunction() before calling
- CAVEMalloc() now uses an arena that is attached at a fixed
address, so that shared memory addresses should match between
machines in a distributed CAVE. The attach address defaults
to 0x70000000; it can be changed by CAVESetOption(CAVE_SHMEM_ADDRESS,...).
- CAVEMalloc() only allocates Unix shared memory; Scramnet memory
allocation should be done explicitly via CAVEScramnetMalloc().
- Added CAVE_NUM_WALL_IDS constant - the number of different CAVE_WALL_IDs
(equal to CAVE_MAX_WALL_ID+1).
- Made AppDistribution default to same method as Distribution, if it
is not set by any config file or argument.
- Made NetworkAppPort default to NetworkPort+1, if it is not set
by any config file or argument.
Features which have been removed
- 'ReverseStereo' config option. Setting InterocularDistance to a negative value
will accomplish roughly the same thing.
- 'AudioServer' config option.
- 'TrackerPortType' config option, and the unused support for special ASO serial ports.
- MessageQueue distribution. Use simulated Scramnet in its place.
- Raw Hippi distribution. TCP over Hippi gives better performance in typical
applications, and works better with the new distribution architecture.
- dual_eye wall. Use the Viewport option with a Screen# wall to reproduce it.
- oldstereo display mode. Use the Viewport option to reproduce it.
- 'Tracking' config option. To disable tracking, set both the TrackerType and the
Controller to 'none'.
- 'ProjectionCorners' config option.
- Optional CAVEComm networking version of library.
- Optional BOOM3 version of library. A separate BOOM3 tracker daemon can be used
Further changes to the beta release
- beta1 - modified pfCAVE's handling of the draw callbacks
(pfCAVEPreDrawFunc, pfCAVEDrawFunc, pfCAVEPostDrawFunc) to
use pfCycleBuffers, to be more reliable & predictable.
- beta2 - fixed configuration initialization to only apply the
CAVERotate and CAVETranslate to wall-type projections, not to HMD
- beta3 - Added CAVESetOption() option CAVE_PROJ_USEMODELVIEW to control
whether the CAVE projection uses the ModelView matrix or just the
Projection matrix (see Projection code revision above).
Using just the Projection matrix will make reflection-mapped textures
match between walls; however, it causes fog to not work (except in the
simulator or front wall of the CAVE). This flag is on (i.e. use the
ModelView matrix) by default.
Added CAVESetOption() options CAVE_SIM_DRAWWAND, CAVE_SIM_DRAWUSER,
CAVE_SIM_DRAWOUTLINE, CAVE_SIM_DRAWTIMING, and CAVE_SIM_VIEWMODE.
These can be used to control the simulator display, as is done
interactively with the 'w', 'u', 'INSERT', 't', and '0'/'1'/'2' keys.
- beta4 - Added CAVENumPipes() and CAVEPipeNumber() functions, for
getting the number of drawing processes and distinguishing between them.
Added CAVE_PROJ_INCLUDENAVIGATION option (for CAVESetOption()). When true,
the navigation transformation will automatically be included in the
projection matrix; CAVENavTransform() does not need to be called in this
case. The option is false by default. This also works in pfCAVE - no
DCS is needed for navigation when it is used.
Added CAVENavInverseTransform() function.
Removed Polhemus tracking, as we no longer have a system to test
it with. The old Polhemus code can be put into a tracker daemon
for later use.
Added "putenv" configuration option, for setting environment variables
from config file.
Modified display loop, so that the pipe's full window (including both
stereo buffers and all color planes) is selected before the FrameFunction
is called. This will allow the FrameFunction to clear the color buffer
for the entire pipe
at once, without separate clears for each channel in the draw function
(although the depth buffer will still have to be cleared by each draw).
Modified multicast networking to allow multiple copies of an application
running on a single machine.
- beta5 - Fixed pfCAVE's simulator joystick, so that its value is based
on the mouse's position in the window, rather than on the screen (so now
it's the same as the plain IrisGL/OpenGL CAVElibs).
Removed SimJoystickFullScreen config option.
Fixed bug which caused core dumps when WallGeometry was not specified for
Post-release bug fixes
- 2.6a (25 May 1997) - Corrected bug that occurs when the CAVE_PROJ_USEMODELVIEW
option is disabled while a program is running (ModelView matrix was not being
reset). This bug does not show up if the option is only set before CAVEInit().
- 2.6b (6 June 1997) - Removed a barrier statement from the pfCAVE libraries'
display process initialization; this barrier caused a deadlock on triple-keyboad
systems. However, its removal may cause occasional mis-synchronization of
walls in a multi-pipe system.
- 2.6c (30 July 1997) - Changed pfCAVE window initialization to
assign appropriate XVisual, rather than using Performer's
pfPWinFBConfigAttrs(). The Performer function would improperly
throw out stereo if the initial config request failed.
- 2.6d (17 Sep 1997) - Changed pfCAVE window initialization in n64
library to get borderless windows to work (using hack posted by Sharon
Clay to info-performer); one bug remains - the X-offset fails to work,
and windows end up on the left edge of the screen.
Fixed pfCAVE networking bug (which was supposedly corrected in 2.5.6b,
but the fix was lost) - incorrect orientation data was being broadcast.
- 2.6e (4 Nov 1997) - Corrected CAVEGetVector() and
CAVEGetSensorVector() to return unit length vectors when the
navigation matrix includes scaling.
- 2.6f (26 Feb 1998) - Removed pfCAVE's swap function, which appears to cause
a deadlock under Performer 2.2. The distributed-CAVE swap function is still
included, which might also cause a deadlock - this has not been tested.
Last modified 26 Feb 1998.