A Unix command is a single word, which
is the name of an executable program. You've already used some of
these, including
diversifly.
Commands of relevance are:
- diversifly
- dpf-config
and dtk-config
- dpf-bounds
- dpf-listDSOs
- dpf-transform
- dtk-destroySharedMem
and several others. Here's a summary of each one:
loads model files, which are specified
as command parameters. Examples:
% diversifly sub.pfb
loads the model file "sub.pfb" using the default
configuration for this system. Press the escape (ESC) key, with the cursor in
the graphics window, to exit the program.
% diversifly cube.pfb
loads the model file "cube.pfb" using the default
configuration for this system.
% diversifly sub.pfb cube.pfb
loads both the model file "sub.pfb" and "cube.pfb" using the default
configuration for this system.
% diversifly esprit.flt
loads the model file "esprit.flt" using the default
configuration for this system. What
went wrong?
% diversifly --examine esprit.flt
loads the model file "esprit.flt" using the default
configuration for this system, and specifying the diversifly command
option "--examine".
This option tells diversifly to move and scale the object so it's in
front of you, and can fit in your display window.
With the cursor in the graphics window, press the "?" key. Notice that the
"ORIGIN" is non-zero, and the "SCALE" is not one. The "--examine"
option is very useful to quickly see and object when you know nothing
about its geometry.
% diversifly --origin .246 -4.96 .541 0 0 0 --scale .409 esprit.flt
does the same thing as the
previous command, but the origin and scale are specified manually as
command options.
% diversifly
prints out the diversifly "Usage"
command, as you specified no models to load. It prints out all of
the options and parameters which diversifly can use.
- dpf-config
and dtk-config
are used to print useful information
about the DPF and DTK installations on the system where the command is
run. You can use the output of this command to make shell scripts
more portable, find files, check versions and so forth. Each
command, by itself, will print a "Usage" statement with all possible
options. Try it, and a few of the parameters:
% dpf-config --about
% dtk-config --about
% dpf-config --env
% dtk-config --env
is used to tell you the size of one or
more model files. You can use this information to calculate the
origin and scale options for
diversifly.
The
dpf-bounds command,
by itself, will print a "Usage" statement with all possible
options. For example:
% dpf-bounds esprit.flt
returns a radius of 2.44. The inverse of this number is the
--scale option you passed to
diversifly. The X and Z
values are the X and Z values you used in the
--origin option to
diversifly. The Y option
value is the negation of twice the radius of the bounding sphere plus
the Y center of the object. See the
DPF
Programmer's Guide if you need more details.
is one of several ways to modify the
position, orientation and size of one or more model files. It
takes one or more model files as input, and a single model file as
output.
Don't use the same file
for both input and output! The
dpf-transform command, by
itself, will print a "Usage" statement with all possible options.
For example:
% dpf-bounds sub.pfb
% dpf-transform --center sub.pfb /tmp/sub.pfb
% dpf-bounds /tmp/sub.pfb
Notice that the center of
/tmp/sub.pfb
is at the origin.
Another way to modify the position, orientation and size of a model
file is using a "pseudo loader". These are Performer file loaders
which apply a transformation when loading a model file. For
example:
% diversifly esprit.flt.-0.246,4.95,-0.54.trans.0.41,0.41,0.41.scale
invokes the
trans
pseudo-loader to translate the model by (-0.246, 4.95, -0.54) and the
scale pseudo-loader to scale
the model by .041 in all directions. The advantage of
pseudo-loaders is that you can specify the exact order of all
transformations, nesting them as deeply as you wish, all in one
command. You can combine pseudo loaders with the dpf-transform
command and the options to dpf-transform will apply to the file loaded
via the pseudo loaders. For example:
% dpf-transform --euler 0 0 60 \
esprit.flt.-0.246,4.95,-0.54.trans.0.41,0.41,0.41.scale /tmp/esprit.pfb
% diversifly /tmp/esprit.pfb
lists all the DSOs installed on the
system on which the command run. This is real handy when you
can't remember the exact spelling (and CaSe counts too!) of a
DSO.
More about this later.
erases DTK shared memory segments on
the system on which the command was run. More about this
later. You generally need to run this command after every reboot.
The environment variable
"DPF_DSO_FILES" is used to specify a list of DSOs to be loaded when you
run a DPF command. An environment variable is set in a window,
and affects only commands typed in that particular window. For
example:
% #notice the value of DPF_DSO_FILES
% dpf-config --env
% export DPF_DSO_FILES="desktopCaveSimGroup"
% #notice the value of DPF_DSO_FILES
% dpf-config --env
You use them like this:
% # this erases the variable so you get the default
% unset DPF_DSO_FILES
% # press "?" and there's no head or wand- we're in desktop mode!
% diversifly sub.pfb
% # use the cave simulator group
% export DPF_DSO_FILES="desktopCaveSimGroup"
% # press up-arrow twice to reuse- press "?" and there's now a head and a wand!
% diversifly sub.pfb
So what's a DSO? A DSO:
- is a separately compiled C++ program that can be loaded into any
existing DIVERSE program
- this means a DSO can be re-used in other programs
- is used to:
- describe the display setup (desktop, simulator, CAVE)
- implement user interfaces, such as navigations
- provide access to input hardware, either real or simulated
- can load and unload other DSOs:
- The desktopCaveSimGroup
DSO is a DSO which just loads other DSOs to create a simulator
environment
- usually does one specific thing, and is used in conjunction with
other DSOs to create more complicated functionality. This
promotes both reusability, modularity and flexibility.
- replace static configuration files with programs that can perform
complex and dynamic operations.
Here's the
desktopCaveSimGroup
DSO:
% # Warning- trick shell stuff below!
% # It might not work on all machines depending on permisions
% dpf-config --source
% ls `!!`
% cat `dpf-config --source`/DSOs/desktopCaveSimGroup.C
The heart of the DSO are the lines:
if(app->load("caveSimDisplay:"
"xkeyboardMouseInput:"
"iconSleepKeyboardMod:"
"caveSimInput:"
"wandJoystickNav:"
"toggleObjectsGroup:"
"buttonNavControl:"
"keyboardNavControl:"
"debugHeadsUp"))
When you load this DSO you're really loading all of these other
DSOs. These DSOs have their programs executed in the order
they're listed, so one DSO can communicate with other DSOs. The
above DSOs are:
configures the graphical output to be a
single window, with a "symmetric" view frustum, field of view and scale
to match a CAVE system
loads the keyboard and mouse hardware
input devices using the X window system
is a little program that puts the
program that this DSO gets inserted into in a sleep state when all of
its graphical displays have been unmapped (minimized). Notice
that this DSO assumes a display has been created, and a keyboard device
has been loaded.
creates simulated head, wand, joystick
and button devices using the keyboard and mouse, which must already be
loaded. These devices are commonly found in an immersive system
such as a CAVE.
is an immersive navigation that uses
the wand and joystick to navigate a virtual environment. This DSO
requires a wand and joystick be created, but doesn't know if the wand and
joystick are real hardware devices, or simulated by other DSOs.
displays little model files which help
debug a virtual environment. It uses the keyboard to toggle the
visibility of the objects, such a cube showing the CAVE walls.
uses the buttons on a wand to control
aspects of the current navigation, such as response, and to switch
between all of the loaded navigational DSOs
does the same thing as buttonNavControl, but uses keys
on the keyboard instead of wand buttons.
brings up an informational display when
the "?" key is pressed.
So when you load this one DSO, you get all this functionality by
combining other, simpler DSOs in a specific order, You can set
the
DPF_DSO_FILES
environment variable to contain a list of DSOs to load if you want to
create your own lists, or add to other group DSOs.
Notice that you can load more than one navigation, and switch between
them. For example, let's say you wanted to load the
wandJoystickHPRNav navigation
in addition to the navigation loaded by the
desktopCaveSimGroup DSO.
% # use the cave simulator group
% export DPF_DSO_FILES="desktopCaveSimGroup"
% # press "?" and notice what navigation you're using- try rotating with space and mouse L/R
% diversifly sub.pfb
% # multiple DSOs are separated by a ":"
% export DPF_DSO_FILES="desktopCaveSimGroup:wandJoystickHPRNav"
% # press "?" and notice what navigation you're using- try rotating
% diversifly sub.pfb
Notice how the sub rotates around the wand in the virtual CAVE?
Try again with just
desktopCaveSimGroup,
press "j" to jump outside the CAVE and
rotate the sub,
press "w" to see the wand,
and "h" to see the head
The
centerPivotNavMod DSO
calculates the center of the loaded model files, and rotates about
their center:
% export DPF_DSO_FILES="desktopCaveSimGroup:centerPivotNavMod"
% diversifly sub.pfb
and try rotating the sub again.
There are many more DSOs to do all sorts of interesting things.
My job at NIST consists primarily of creating DSOs and pseudo-loaders
which can be used to implement different visualization techniques.
DTK shared memory can be used to let
different DSOs and processes share information, DTK shared
memory can reside on a single machine, or can be networked and shared
between multiple networked shared memory.
DTK shared memory is stored in one or more segments. Each segment
is like a file, and contains data for a particular purpose. Two
commonly used segments are named
head
and
wand, for the
position
and orientation of the head and wand in the CAVE, or simulator.
First, we'll use DTK shared memory on a single machine.
% # destroy any existing DTK shared memory segments
% # don't worry if this gives an error
% dtk-destroySharedMem -r
% # write the simulated head and wand data to shared memory
% export DPF_DSO_FILES=desktopCaveSimGroup:caveDTKOutput
% # run diversifly as a detached process
% # look at the head data by using the "?" key
% # press "j" to jump outside, and "h" to see the head
% # move the head with the cursor arrows
% diversifly sub.pfb &
% # read the head data from shared memory
% dtk-readFloats head
Other programs use shared memory- these are used to debug the CAVE
input devices:
% dtk-caveDeviceSimulator &
% dtk-gnomonDisplay head &
% dtk-floatSliders head -s 3 -180 180 0 -s 4 -180 180 0 -s 5 -180 180 0 -l x y z h p r &
% dtk-readFloats head
Now, quit all diverse programs and
destroy shared memory again.
You can play the same games with the keyboard, joystick, buttons, and
any other segment used by the DSOs.
Now, we can do the same thing across the network. I (
ONLY ME!!) do
these
commands again to send out CAVE and navigation data
% export DPF_DSO_FILES=desktopCaveSimGroup:caveDTKOutput
% diversifly sub.pfb &
% dtk-caveDeviceSimulator &
% dtk-gnomonDisplay head &
% dtk-floatSliders head -s 3 -180 180 0 -s 4 -180 180 0 -s 5 -180 180 0 -l x y z h p r &
Now you follow my head: