Applications should be recompiled from source, using the new headers,
before linking with the 2.6 library, due to these changes.
The values of most of the constants defined in cave.h, and the definitions
of many of the structs have changed.
The tracker daemon's data format has changed. This means that the new
library will not work with older versions of the daemon (the new format
is designed to be more tolerant of future changes). There is a special
backwards-compatible version of the new daemon (called 'trackd_bc') which
stores tracking and wand data in both the new and old formats, allowing
pre-2.6 applications to still run, with the appropriate configuration file.
The sensor data struct (CAVE_SENSOR_ST) has changed. The former azi
field is now called azim (for textual symmetry), and there are two
new fields - timestamp and calibrated. timestamp contains
the time that that sensor reading was taken (equivalent to a 32-bit struct
timeval); calibrated is a boolean flag indicating whether this sensor
data has been corrected by the CAVE calibration.
The old tracker macros (CAVEGetHead, CAVEWandOrientation, etc.) have
been removed from cave.h and placed in a separate header file - cave.macros.h.
The ProjectionCorners configuration option has been replaced by ProjectionData
(see below). To update existing config files, for any lines such as:
ProjectionCorners screen0 -5 0 -5 -5 10 -5 0 0 -5
add the corresponding new configuration line, e.g.:
Both of these lines can be in the same config file - the ProjectionData
will be used by 2.6, while the ProjectionCorners will be used by earlier
libraries.
CAVE_MAX_SENSORS, CAVE_MAX_BUTTONS, and CAVE_MAX_VALUATORS have all
been increased to 32. This shouldn't be annoying, but might affect some
programs in unforeseen ways.
Performer 1.2 is no longer supported; only 2.0 is supported. (We don't
have a system still running 1.2 to test.)
CAVEConfig->ProjectionData is now a 2 dimensional array,
indexed by wall and eye. Eye index 0 corresponds to the left eye; index
1 to the right eye. e.g. CAVEConfig->ProjectionData[CAVE_FRONT_WALL][0]
gives the data for the [front wall,left eye] view.
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 depth buffer.
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); glClear(GL_DEPTH_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 been called. 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 applications).
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
process.
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 given CAVE_WALL_ID.
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 CAVE.
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 machines.
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
without colliding.
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 two values.)
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
- see above.
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 CAVENavTransform().
OpenGL windows are cleared when they are first opened.
Other changes
It should (finally) be possible to call CAVEDisplay(), CAVEInitApplication(),
and CAVEFrameFunction() before calling CAVEInit().
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 instead.
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 projections.
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
a wall.
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
use 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.