DCU library, Version 1.1

by Dave Pape (pape@evl.uic.edu)
11 July 1996

Introduction

The DCU library is a set of C++ classes providing utilities for creating interactive CAVE environments. It includes classes for transforming objects, working with bounding volumes, and placing sounds in a 3D world (and a few other things, not all of which are documented here.)

libdcu can be found (at EVL) in ~pape/lib; the header files are in ~pape/include. DCU.tar.gz contains the source code and compiled library for downloading; it also contains a few random, undocumented demo programs. Some of the demos also require the libwave library for rendering Wavefront OBJ-format models.

Library Interface

Major sections:


Audio classes

There are two main parts to the audio classes - samples and the dcuAudioEnv class. The sample classes (dcuSample, dcuLoopSample, dcuTriggerSample, dcuWandTriggerSample, dcuRandomSample) control individual sound samples, playing them and updating them based on the specific class's behavior. The dcuAudioEnv class holds a collection of samples, updates them as a group, and can automatically build an environment from a text description file. The volume classes can be used with samples to control their amplitude and when they are played.

Sample Classes

The interfaces to the various sound sample classes are as follows:

dcuSample

Generic sound sample object; parent of all the other sample classes.

#include "dcuSample.h"

dcuSample::dcuSample(char *file=NULL,float maxAmpl=1)
dcuSample constructor. file is the name of the sound file that the sample will play, maxAmpl is the maximum amplitude. These can be changed later by setFile() and setMaxAmplitude().
void dcuSample::start()
Initializes the sample when it first becomes "active". This will cause a dcuLoopSample to begin playing; all other sample classes currently do nothing.
void dcuSample::play(float *userPos=NULL,float curTime=0)
Sends a message to vss to begin playing the sound sample. userPos is the current position of the user in world space; if it is given, the sample's amplitude will be set based on the user's distance. curTime is the current time; it is used to determine when update() should stop the sample, and in controlling the attack & decay.
void dcuSample::update(float *userPos,float curTime)
Updates the sample, if it is playing. userPos is the current position of the user in world space; curTime is the current time. If the sample's end time has been reached (based on curTime and length()), it will be stopped. Otherwise, its amplitude will be updated, based on the distance from the user to the sound, maxAmplitude(), maxDistance(), attack(), and decay().
Subclasses of dcuSample will also perform their behavior-specific updates in this function, which may include playing the sample (in the dcuTriggerSample and dcuRandomSample classes).
void dcuSample::stop(void)
Sends a message to vss to stop playing the sound sample, if it is playing. The sample is stopped immediately - the decay setting is not used in this case.
int dcuSample::isPlaying(void)
Returns 1 if the sample is currently playing, 0 otherwise. This will be true if play() has been called, and stop() has not been called since then.
int dcuSample::parseOption(char *opt)
Parses a line of sample options from a dcuAudioEnv description file, and sets the sample's values from those options. See below for the dcuAudioEnv description file format.
void dcuSample::setVolume(dcuVolume *vol)
Sets the sample's volume (not to be confused with amplitude). vol is a dcuVolume which represents the space occupied by the sound.
void dcuSample::setDirectory(char *dir)
Sets the sample's directory. A message will be sent to vss to set the directory of the sample's actor.
void dcuSample::setFile(char *file)
Defines the AIFF sound file that the sample will play.
void dcuSample::setLength(float len)
Indicates the length of the sound file. This is used by update() to decide when to stop playing the sample (and when to decay it).
void dcuSample::setMaxAmplitude(float maxamp)
Sets the maximum amplitude for the sample. This is the amplitude that it will be played at when the user's distance from the sample is 0.
void dcuSample::setMaxDistance(float maxdist)
Sets the maximum range for the sample to be audible. When the user's distance from the sample is maxdist or greater, the amplitude will be 0 (it will continue playing, however).
void dcuSample::setAttack(float att)
Defines the attack time for the sample. The sample's amplitude is multiplied by a scaling factor, which linearly increases from 0 to 1 in the first att seconds when it is played.
void dcuSample::setDecay(float dec)
Defines the decay time for the sample. The amplitude scaling factor is linearly decreased from 1 back to 0 in the final dec seconds that the sample is played.
dcuVolume * dcuSample::volume(void)
Returns the sample's volume, as set by setVolume().
char * dcuSample::directory(void)
Returns the sample's directory, as set by setDirectory().
char * dcuSample::file(void)
Returns the sample's AIFF file name, as set by setFile().
float dcuSample::length(void)
Returns the sample's length, as set by setLength().
float dcuSample::maxAmplitude(void)
Returns the sample's maximum amplitude, as set by setMaxAmplitude().
float dcuSample::maxDistance(void)
Returns the sample's maximum audible distance, as set by setMaxDistance().
float dcuSample::attack(void)
Returns the sample's attack time, as set by setAttack().
float dcuSample::decay(void)
Returns the sample's decay time, as set by setDecay().

The default settings for a newly created dcuSample are: no file or directory, length 0, maximum amplitude 1, maximum distance DCU_DEFAULT_MAX_DIST (defined in dcuSample.h), attack and decay 0, and a generic dcuVolume (which occupies infinite space - i.e., the distance to any position is 0).

The dcuSample constructor creates a vss SampleActor for the sound. Hence, samples should not be created until after BeginSoundServer() is called.

A dcuSample object can be used to simply play sound files when needed, or to control dynamic, positional sounds. The following code fragment is an example of playing a sound without any subsequent updates; the sound will be played at the specified maximum amplitude, since it uses the default dcuVolume.

	BeginSoundServer();
	dcuSample * sample = new dcuSample("sound.aiff",0.25);
	sample->setDirectory("/usr/data/sounds");
	sample->play();
	sleep(5);
	delete sample;
	EndSoundServer();
To play a positional sound, the update() function must be called frequently, in order for the amplitude to be adjusted for the user's position. Also, a volume other than the default and a non-zero length must be set. The following fragment starts a sound which is defined to be 240 seconds long; it is assigned a dcuPointVolume (with a default position of (0,0,0)).
	float userPos[3];
	dcuSample * sample = new dcuSample("sound.aiff",0.25);
	sample->setDirectory("/usr/data/sounds");
	sample->setLength(240.0);
	sample->setVolume(new dcuPointVolume);
	CAVEGetPosition(CAVE_HEAD_NAV, userPos);
	sample->play(userPos,CAVEGetTime());
	while (1)
		{
		navigate();
		CAVEGetPosition(CAVE_HEAD_NAV, userPos);
		sample->update(userPos,CAVEGetTime());
		sginap(1);
		}

dcuLoopSample

Infinitely looping sound object.

#include "dcuLoopSample.h"

void dcuLoopSample::start()
Starts playing the sample. A default user position of (1000000,1000000,1000000) is passed to play().
void dcuLoopSample::play(float *userPos,float curTime)
Starts playing the sample.
A dcuLoopSample controls a sound which will loop continually once it is started, until stop() is called. update() will not stop the sound. It is otherwise the same as a dcuSample.

dcuRandomSample

Randomly played sound object.

#include "dcuRandomSample.h"

void dcuRandomSample::setProbability(float prob)
Defines the probability of the sample being played any time update() is called.
void dcuRandomSample::setMinRandomAmplitude(float min)
Sets the minimum value to choose for the sound's amplitude when it plays.
void dcuRandomSample::setMaxRandomAmplitude(float max)
Sets the maximum value to choose for the sound's amplitude when it plays.
float dcuRandomSample::probability(void)
Returns the probability as set by setProbability().
float dcuRandomSample::minRandomAmplitude(void)
Returns the minimum amplitude as set by setMinRandomAmplitude().
float dcuRandomSample::maxRandomAmplitude(void)
Returns the maximum amplitude as set by maxRandomAmplitude().
float dcuRandomSample::update(float *userPos,float curTime)
Updates the sample. If the sample is not currently playing, a random value between 0 and 1 is picked; if the value is less than probability(), the sample is played. Any time the sample is played, a new maximum amplitude is picked from the range [minRandomAmplitude(), maxRandomAmplitude()].
When playing, the sample is updated by the normal dcuSample update() function.
The default setting for probability is 0.005, and for minRadnomAmplitude and maxRandomAmplitude is 1.0.

A dcuRandomSample is a sound sample which is triggered at random intervals by update(). The maximum amplitude of the sample is also set randomly, each time it is started by update(). update() will not start more than one instance of the sound at a time.

dcuTriggerSample

Sound object triggered by user proximity.

#include "dcuTriggerSample.h"

void dcuTriggerSample::setRadius(float rad)
Defines the triggering radius. When the user moves within rad distance of the sample, it will be played.
float dcuTriggerSample::radius(void)
Returns the radius as set by setRadius().
float dcuTriggerSample::update(float *userPos,float curTime)
Updates the sample. If the distance from the user to the sample's volume is less than the defined radius, the sound begins playing; the volume used for triggering is the same as that used for amplitude control. Once the sample has been triggered, it will not be played again until the user first moves outside of its radius (i.e. it will only play once while the user is inside the radius).
When playing, the sample is updated by the normal dcuSample update() function.
The default trigger radius is 1.

A dcuTriggerSample is a sound which is automatically played whenever the user moves near it. Whenever update() determines that the user has entered the sample's area of effect, it is immediately played. The sample then latches until the user moves back outside the area of effect, so that it will only be played one time whenever the user enters the area. When the sample is triggered, it plays once for its entire length - it does not stop if the user moves outside of the triggering radius.

dcuWandTriggerSample

Sound object triggered by wand proximity; subclass of dcuTriggerSample.

#include "dcuWandTriggerSample.h"

float dcuWandTriggerSample::update(float *userPos,float curTime)
Updates the sample. update gets the current navigated position of the wand; the sound is triggered as in the dcuTriggerSample, except using the distance to the wand instead of the distance to the user.
When playing, the sample is updated by the normal dcuSample update() function.
A dcuWandTriggerSample functions exactly like a dcuTriggerSample, except that it is triggered by the wand position rather than the user's position.

dcuAudioEnv Class

Audio environment manager object. A dcuAudioEnv is used to collect dcuSample objects into a group; the dcuAudioEnv can then automatically handle the updates for all the samples at once. It can also read in an audio environment description file an create all the samples defined in the file.

#include "dcuAudioEnv.h"

void dcuAudioEnv::addSample(dcuSample *sample)
Adds a sample to the dcuAudioEnv's list of samples to update. If the sample does not have a directory already set, it will be assigned the environment's default directory.
void dcuAudioEnv::removeSample(dcuSample *sample)
Removes the given sample from the environment's list of samples (if it is found). If the sample is active, it will be sent a stop() command.
void dcuAudioEnv::removeAllSamples(int del=0)
Removes all the samples from the environment's list. stop() is called for any samples which are active. If the flag del is true, each sample object is deleted as it is removed from the list.
void dcuAudioEnv::update(int state=1)
Updates all samples in the environment. state is an optional flag indicating whether the environment should be active or not. If state is true (it is active), update() is called for each of the environment's samples. Whenever the environment changes from an inactive to active state, start() is called for each sample; when it transitions from active to inactive, stop() is called for each sample. The samples are updated using the current CAVE user's head position in world coordinates (i.e., CAVEGetPosition(CAVE_HEAD_NAV,userPos)) and the current CAVE time (CAVEGetTime()).
void dcuAudioEnv::setDefaultDirectory(char *dir)
Sets the default directory for samples which are subsequently added to the environment.
char * dcuAudioEnv::defaultDirectory(void)
Returns the directory set by setDefaultDirectory().
void dcuAudioEnv::readEnvFile(char *file)
Reads a dcuAudioEnv description file and adds all the listed samples to the environment.


Volume Classes

The volume classes represent simple bounding volumes; they provide functions for computing the distance of a point to the volume and for determining if a point is inside the volume. Volumes can be 3, 2, 1, or 0 dimensional. Volumes are used with the sample classes to compute the distance from the user to the sound. The available classes are dcuVolume, dcuPointVolume, dcuSphereVolume, and dcuBoxVolume.

The interfaces to the different classes are as follows:

dcuVolume

Generic volume object; parent of all other volume classes.

#include "dcuVolume.h"

float dcuVolume::distanceSq(const float p[3])
float dcuVolume::distanceSq(float x,float y,float z)
Returns the square of the distance from point p (or x,y,z) to the volume. Any point within the volume has distance of 0; for points outside the volume, the distance is that to the nearest point on the volume's edge.
float dcuVolume::distance(float p[3])
float dcuVolume::distance(float x,float y,float z)
Returns the distance from a point to the volume. This requires computing a square root, and so is sometimes more expensive than distanceSq().
int dcuVolume::contains(const float p[3])
int dcuVolume::contains(float x,float y,float z)
Returns true if the given point is within the volume, false otherwise.
void setCenter(const float p[3])
void setCenter(float x,float y,float z)
Sets the position of the volume. This is typically the volume's origin, which it is centered around.
void setDimensions(int dim)
Defines which dimensions to use in computing distances to the volume. dim is a bitmask, formed by OR'ing any or all of the constants DCU_X_DIM, DCU_Y_DIM, and DCU_Z_DIM. Only these dimensions will be used by the distance functions; the volume effectively extends infinitely in all other dimensions.
void setTransform(dcuTransform *t)
Sets a transformation associated with the volume. When a dcuTransform t is assigned to a volume, all distance and containment tests will be performed with the volume transformed by t.
void getCenter(float p[3])
Returns the center of the volume, as set by setCenter().
int dimensions(void)
Returns the dimensions as set by setDimensions().
dcuTransform * getTransform(void)
Returns the transformation as set by setTransform().
The default dimensions for a volume are all 3, DCU_X_DIM | DCU_Y_DIM | DCU_Z_DIM; the default position is (0,0,0).

The generic dcuVolume class is primarily a parent for the other volume classes. It represents an infinite space - any point is inside the space, and the distance functions will always return 0.

dcuPointVolume

Single point volume.

#include "dcuPointVolume.h"

A dcuPointVolume represents a single point. The distance of any point from the volume is the Euclidean distance from the volume's position defined by setCenter().

dcuSphereVolume

Spherical volume.

#include "dcuSphereVolume.h"

void dcuSphereVolume::setRadius(float rad)
Defines the radius of the volume.
float radius(void)
Returns the radius as set by setRadius().
The default radius of a dcuSphereVolume is 1.

A dcuSphereVolume represents an n-dimensional sphere - it contains all points which are within radius() units of the volume's origin (getCenter()).

dcuBoxVolume

Axis-aligned box volume.

#include "dcuBoxVolume.h"

void dcuBoxVolume::setRange(const float r[6])
void dcuBoxVolume::setRange(float minX,float maxX,float minY,float maxY,float minZ,float maxZ)
Defines the range covered by the box in each dimension. r[0] is the minimum X of the box, r[1] is the maximum X, r[2] is the minimum Y, r[3] is the maximum Y, r[4] is the minimum Z, and r[5] is the maximum Z. The center of the volume will be set to the middle of these ranges.
void dcuBoxVolume::setSize(const float size[3])
void dcuBoxVolume::setSize(float x,float y,float z)
Defines the size of the box. The volume will extend by size[d]/2 units from the center in both directions, in each dimension d.
void dcuBoxVolume::setCenterAndSize(const float center[3],const float size[3])
Sets both the center and the size of a box in one call.
void dcuBoxVolume::getSize(const float size[3])
Gets the box's size, as defined by setSize().
void dcuBoxVolume::getRange(float r[6])
Gets the box's range, as defined by setRange(), or by the size and center.
The default size of a box is 1 in each dimension.

A dcuBoxVolume is an axis-aligned box; points which lie between the box's minimum & maximum in each dimension are inside the box.


Transformation Classes

The transformation classes handle GL transformations for 3D objects. The base dcuTransform class stores its matrix in shared memory, and so can be used to manipulate a transformation from any process.

The dcuGrabber subclass is for grabbing objects with the wand or other sensors; it takes care of switching between world-space and sensor-space coordinates, so that when an object is grabbed or released it stays in the same position and orientation.

Class interfaces:

dcuTransform

Stores and manipulates a 4x4 transformation matrix. The standard GL-style translate, rotate, and scale operations can be applied to the matrix. The matrix is stored in shared memory; a CAVELOCK is used to control access to it.
Note: The inverse matrix routines assume that the transformation is affine. If a non-affine matrix is created (via loadMatrix(), preMultMatrix(), or postMultMatrix()), the results are undefined.

#include "dcuTransform.h"

void dcuTransform::glTransform(void)
Applies the transform's current matrix, using glMultMatrix().
void dcuTransform::makeIdentity(void)
Loads the transform's matrix with the identity matrix.
void dcuTransform::translate(float x,float y,float z)
Adds a translation by (x,y,z) to the transform's matrix.
void dcuTransform::rotate(float angle,float x,float y,float z)
Adds a rotation by angle degrees around the axis (x,y,z) to the transform's matrix.
void dcuTransform::scale(float s)
Adds a uniform scaling by s to the transform's matrix.
void dcuTransform::scale(float sx,float sy,float sz)
Adds a scaling by (sx,sy,sz) to the transform's matrix.
void dcuTransform::getMatrix(float m[4][4])
Returns the current matrix.
void dcuTransform::getInverseMatrix(float inv[4][4])
Returns the inverse of the current matrix.
void dcuTransform::loadMatrix(float m[4][4])
Replaces the transform's matrix with m.
void dcuTransform::postMultMatrix(float m[4][4])
void dcuTransform::postMultMatrix(float *m)
Post-multiplies the transform's matrix by m.
void dcuTransform::preMultMatrix(float m[4][4])
void dcuTransform::preMultMatrix(float *m)
Pre-multiplies the transform's matrix by m.
void dcuTransform::transformPoint(float p[3])
Multiplies the point p by the current matrix; the result is returned in p.
void dcuTransform::transformVector(float v[3])
Multiplies the direction vector v by the current matrix; the result is returned in v. A vector will be affected by the transform's rotation and scaling, but not by translation.
void dcuTransform::inverseTransformPoint(float v[3])
Multiplies the point p by the inverse of the current matrix; the result is returned in p.
void dcuTransform::inverseTransformVector(float v[3])
Multiplies the direction vector v by the inverse of the current matrix; the result is returned in v. A vector will be affected by the transform's rotation and scaling, but not by translation.
The dcuTransform constructor loads the identity matrix by default. Because it allocates shared memory and a lock, a dcuTransform cannot be created until after CAVEConfigure() has been called.

The following code fragment demonstrates the basic use of a dcuTransform to animate an object:

	dcuTransform *transform;
	
	main(int argc,char **argv)
	{
	 CAVEConfigure(&argc,argv,NULL);
	 transform = new dcuTransform;
	 CAVEInit();
	 CAVEDisplay(draw_fn,0);
	 while (1)
		{
		transform->rotate(2.0, 0.0,1.0,0.0);
		sginap(10);
		}
	}

	void draw_fn(void)
	{
	...
	glPushMatrix();
	transform->glTransform();
	draw_the_object();
	glPopMatrix();
	...
	}

dcuGrabber

Class for grabbing objects with a CAVE sensor; subclass of dcuTransform.

#include "dcuGrabber.h"

dcuGrabber::dcuGrabber(CAVE_SENSOR_ST *sensor=CAVESENSOR(1))
Constructor. sensor is a pointer to the CAVE sensor to "attach" the dcuGrabber to when it grabs; the default is the wand sensor.
void dcuGrabber::setSensor(CAVE_SENSOR_ST *sensor)
Defines the sensor to which the dcuGrabber is attached when grab() is called. If the dcuGrabber is in a grabbed state when this is called, it will automatically release() itself before changing sensors, and then grab() again after changing sensors.
CAVE_SENSOR_ST * dcuGrabber::sensor(void)
Returns the CAVE sensor set by setSensor().
void dcuGrabber::grab(void)
Activates the dcuGrabber. While in a grabbed state, the dcuGrabber's will move and rotate with its sensor.
void dcuGrabber::release(void)
Deactivates the dcuGrabber. When released, the dcuGrabber will remain fixed in world space. Any release() calls made when not in a grabbed state are ignored.
int dcuGrabber::grabbed(void)
Returns true if the dcuGrabber is currently in a grabbed state, false otherwise.
A dcuGrabber's grab() state flag and sensor pointer are stored in shared memory.

The following code fragment demonstrates the basic use of a dcuGrabber:

	dcuGrabber *grabber;

	main(int argc,char **argv)
	{
	...
	grabber = new dcuGrabber;
	...
	while (1)
		{
		int cb1 = CAVEButtonChange(1);
		if (cb1 == 1)			/* Grab whenever button 1 is pressed */
			grabber->grab();
		else if (cb1 == -1)		/* Release when button 1 is released */
			grabber->release();
		...
		}
	}

	void draw_fn(void)
	{
	...
	glPushMatrix();
	grabber->glTransform();
	draw_the_object();
	glPopMatrix();
	...
	}
A dcuGrabber can be assigned to a dcuVolume as the volume's transform. This code fragment shows how to use a grabber and a volume together to grab an object only when the wand is within its bounding volume:
	dcuGrabber *grabber;

	main(int argc,char **argv)
	{
	...
	grabber = new dcuGrabber;
	dcuSphereVolume *volume = new dcuSphereVolume;
	volume->setCenter(objectCenter);	/* Define the object's bounding sphere */
	volume->setRadius(objectRadius);
	volume->setTransform(grabber);
	...
	while (1)
		{
		int cb1 = CAVEButtonChange(1);
		if (cb1 == 1)			/* Grab when button 1 is pressed */
			{			/* inside the volume */
			float wandPos[3];
			CAVEGetPosition(CAVE_WAND_NAV,wandPos);
			if (volume->contains(wandPos))
				grabber->grab();
			}
		else if (cb1 == -1)		/* Release when button 1 is released */
			grabber->release();
		...
		}
	}

	void draw_fn(void)
	{
	...
	glPushMatrix();
	grabber->glTransform();
	draw_the_object();
	glPopMatrix();
	...
	}


Image & Texture classes

dcuImage

Class for loading SGI format images. Images are stored 32 bit longword arrays.

#include "dcuImage.h"

dcuImage::dcuImage(char *file=NULL,int byteOrder=DCU_ABGR)
Constructor. file is the name of an image file to load; byteOrder is the ordering of longword bytes to use - either DCU_ABGR or DCU_RGBA. If no file name is given, a 1x1 dummy image is created.
void dcuImage::setByteOrder(int order)
Sets the longword byte ordering to use in the image data; either DCU_ABGR or DCU_RGBA. DCU_ABGR is the traditional longimagedata() ordering; DCU_RGBA corresponds to OpenGL's preferred GL_RGBA ordering. If an image has already been loaded, and order is different than the current byte ordering, the image data will be converted to the new ordering.
int dcuImage::loadFile(char *filename)
Loads the image file filename. If another image is already loaded, its data is freed before reading the new one. loadFile() returns TRUE if the image was read successfully, FALSE if it fails.
void dcuImage::setImage(unsigned long *img,int xdim,int ydim)
Sets the image data to the given pointer and dimensions. Any previous image data is freed.
void dcuImage::copyImage(unsigned long *image,int xdim,int ydim)
Copies the xdim x ydim array image and makes this the new image data. Any previous image data is freed.
void dcuImage::createImage(int xdim,int ydim)
Creates a new image data array of xdim x ydim longwords. The array is initialized to all zeroes.
int dcuImage::writeFile(char *filename)
Saves the image in the SGI image file filename. It is saved as a 4 channel image. The dcuImage's file name is not changed by this operation.
unsigned long *dcuImage::image(void)
Returns a pointer to the image data. The data is an array of xdim() x ydim() longwords.
int dcuImage::xdim(void)
Returns the width of the image.
int dcuImage::ydim(void)
Returns the height of the image.
void dcuImage::dimensions(int dim[2])
Returns the dimensions of the image in dim; dim[0] is the width, dim[1] is the height.
char *dcuImage::filename(void)
Returns the name of the currently loaded file, as set by either the constructor or loadFile().
int dcuImage::byteOrder(void)
Returns the byte ordering of the image, either DCU_ABGR or DCU_RGBA.

dcuTexture

Creates an OpenGL texture map from a dcuImage. The texture object extension (glBindTextureEXT()) will be used in defining and binding the texture, if the graphics hardware supports it; if not, a display list will be used.

#include "dcuTexture.h"

dcuTexture::dcuTexture(char *filename=NULL,int byteOrder=DCU_ABGR,int mipmap=0)
Constructor; creates a dcuImage from the SGI image filename, with the byte ordering byteOrder. Sets the mipmapping flag to mipmap.
void dcuTexture::define(void)
Defines an OpenGL texture map using the current image. The texture parameters will be set from the selected filtering and wrapping values. If mipmap() is true, a mipmapped texture will be created via gluBuild2DMipmaps(). If the image's dimensions are not powers of two, a copy will be made which is scaled to the largest powers of 2 less than the image's size.
void dcuTexture::bind(void)
Enables texture mapping and binds the texture, if it has been defined. If the texture has not been defined yet, bind() will disable texturing. (Call dontChangeTextureMode() to prevent bind() from enabling or disabling texturing.)
void dcuTexture::setImage(dcuImage *image)
Sets the dcuImage to use when the texture is defined.
void dcuTexture::setMinFilter(GLint val)
Sets the minification filter to use in define(). val should be an appropriate value for the GL_TEXTURE_MIN_FILTER texture parameter.
void dcuTexture::setMagFilter(GLint val)
Sets the magnification filter to use in define(). val should be an appropriate value for the GL_TEXTURE_MAG_FILTER texture parameter.
void dcuTexture::setWrapS(GLint val)
Sets the S-coordinate wrapping mode to use in define(). val should be an appropriate value for the GL_TEXTURE_WRAP_S texture parameter.
void dcuTexture::setWrapT(GLint val)
Sets the T-coordinate wrapping mode to use in define(). val should be an appropriate value for the GL_TEXTURE_WRAP_T texture parameter.
void dcuTexture::setWrap(GLint val)
Sets both the S- and T-coordinate wrapping modes.
void dcuTexture::setMipmap(int flag=1)
Sets the mipmapping flag for define().
void dcuTexture::dontChangeTextureMode(void)
Prevents bind() from calling glDisable(GL_TEXTURE_2D) or glEnable(GL_TEXTURE_2D).
dcuImage * dcuTexture::image(void)
Returns the dcuImage used by the texture, which was either created by the constructor or set by setImage().
GLint dcuTexture::minFilter(void)
Returns the minification filter as set by setMinFilter().
GLint dcuTexture::magFilter(void)
Returns the magnification filter as set by setMagFilter().
GLint dcuTexture::wrapS(void)
Returns the S-coordinate wrapping mode as set by setWrapS().
GLint dcuTexture::wrapT(void)
Returns the T-coordinate wrapping mode as set by setWrapT().
int dcuTexture::mipmap(void)
Returns true if mipmapping is enabled, false if not.
The default minification and magnification filters are GL_NEAREST. The default wrapping modes are GL_REPEAT.

dcuSharedImage

Loads an SGI format image, storing the data in shared memory. A subclass of dcuImage.

#include "dcuSharedImage.h"

The public interface to dcuSharedImage is identical to that of dcuImage. However, when an image is loaded, its data (and dimensions) are placed in shared memory, allocated by CAVEMalloc(). As long as the dcuSharedImage object itself is created before calling CAVEInit(), the image data will be visible to all CAVE processes, even if an image is loaded after CAVEInit(). dcuSharedImage::setImage() should only be passed pointers to image data in shared memory; for non-shared data, use copyImage().

A dcuSharedImage can be used with a dcuTexture to create a "delayed texture", so that a program does not have to wait for all the images to be loaded before beginning rendering. The following code fragment demonstrates this:

	dcuTexture *texmap;

	void defineTexture(void)
	{
	 texmap->define();
	}

	void drawfn(void)
	{
	...
	 texmap->bind(); /* If the texture hasn't been defined, this will just turn off texturing */
	 glBegin(GL_TRIANGLE_STRIP);
	  glTexCoord3fv(tc[0]);
	  glVertex3fv(vert[0]);
	  glTexCoord3fv(tc[1]);
	  glVertex3fv(vert[1]);
	  glTexCoord3fv(tc[2]);
	  glVertex3fv(vert[2]);
	 glEnd();
	...
	}

	main(int argc,char **argv)
	{
	 dcuSharedImage *img;
	 CAVEConfigure(&argc,argv,NULL);
	 texmap = new dcuTexture;	/* Create the texture, but don't wait to load the image */
	 img = new dcuSharedImage;
	 texmap->setImage(img);
	 CAVEInit();
	 CAVEDisplay(drawfn,0);
	 img->loadFile("texture.rgb");	/* Now load the image in parallel with the graphics */
	 CAVEInitApplication(defineTexture,0);	/* Tell the graphics to define() the texture */
	...
	}
This method can also be used to change a texture map dynamically, without making the display processes take time to read the file from disk.


Trigger Class

A dcuTrigger associates callback functions with a volume. Whenever the position data passed to the trigger enters or leaves the volume, the corresponding function is called.

#include "dcuTrigger.h"

dcuTrigger::dcuTrigger(dcuVolume *vol=NULL)
Constructor; vol is the volume to test position data against.
typedef void (*dcuCallback)(void *)
The type for trigger callback functions.
void dcuTrigger::setEnterCallback(dcuCallback callback,void *data)
Defines the function to be called whenever the volume is entered. The pointer data is passed as the function's argument.
void dcuTrigger::setLeaveCallback(dcuCallback callback,void *data)
Defines the function to be called whenever the volume is exited. The pointer data is passed as the function's argument.
void dcuTrigger::setVolume(dcuVolume *v)
Defines the volume to test for entering/exiting.
void dcuTrigger::update(float pos[3])
Updates the trigger. The position pos is tested to see if it is inside the trigger's volume. If pos is inside the volume, and was not inside last time update() was called, the enter callback function is called. If pos is outside of the volume, and was inside the last time update() was called, the leave callback function is called.
dcuCallback dcuTrigger::enterCallback(void)
Returns the enter callback function, as set by setEnterCallback().
void * dcuTrigger::enterCallbackData(void)
Returns the enter callback function's data pointer, as set by setEnterCallback().
dcuCallback dcuTrigger::leaveCallback(void)
Returns the leave callback function, as set by setLeaveCallback().
void * dcuTrigger::leaveCallbackData(void)
Returns the leave callback function's data pointer, as set by setLeaveCallback().
dcuVolume * dcuTrigger::volume(void)
Returns the trigger's volume, as set by setVolume() or the constructor.


Miscellaneous Utilities

#include "dcu.h"

int dcuQueryGLExtension(char *name)
Returns TRUE if the OpenGL extension name is supported by graphics hardware. The test is case-sensitive.
void dcuDumpStereoWindow(char *basename)
Reads the contents of the both front buffers of a CAVE display window, and saves them as a pair of SGI images. The left eye image is saved as "basename.left.sgi"; the right eye image is saved as "basename.right.sgi".
void dcuDumpWindow(char *imgname)
Saves the contents of the CAVE window's front buffer as an SGI image; imgname is the name of the image file.
char *dcuNextToken(char **string)
Extracts the next token from a string; tokens are delimited by whitespace characters. A pointer to the beginning of the token is returned; the first whitespace after the token is replaced by a null character. *string is modified to point to the next character in the string after the returned token.
int dcuGetStringID(char *str,struct _dcukeyword *table)
Looks up the string str in the table table, and returns the integer associated with that string. If str is not found, -1 is returned. The string comparison is case insensitive. The table is an array of _dcukeyword structs; the struct is defined as:
	struct _dcukeyword {  char *str;  int id;  };
The last entry in table must have a str member of NULL, to mark the end of the array.


Last modified 13 October 1997.
Dave Pape, pape@evl.uic.edu