Difference between revisions of "CalVR Config File"
(17 intermediate revisions by 2 users not shown) | |||
Line 36: | Line 36: | ||
Sets the far plane value for cameras. | Sets the far plane value for cameras. | ||
<br> | <br> | ||
− | <Stereo separation="64.0" /> | + | <Stereo separation="64.0" omniStereo="false" /> |
− | Value to use for distance between left and right eye for stereo rendering. | + | separation - Value to use for distance between left and right eye for stereo rendering (mm). |
+ | <br> | ||
+ | omniStereo - Used to turn on omnidirectional stereo rendering. In this mode, the viewer position is still determined by the tracked user, but the direction is always towards the center of each screen. This can be good in a large surround system being viewed by many people (e.g. CAVE2). If this attribute is present in the config file (either true or false), there will be a checkbox in the main menu to toggle this feature at runtime. | ||
<br> | <br> | ||
<Stencil value="false" /> | <Stencil value="false" /> | ||
Line 46: | Line 48: | ||
<br> | <br> | ||
<UseDepthPartition value="false" /> | <UseDepthPartition value="false" /> | ||
− | When set to "true", a depth partition node is used at the scene root. This is useful when you have scenes too large to set a static near/far value and there is lots of empty space within the depth range. ( | + | When set to "true", a depth partition node is used at the scene root. This is useful when you have scenes too large to set a static near/far value and there is lots of empty space within the depth range. (e.g. ossimPlanet viewing) |
<br> | <br> | ||
<HidePointer value="false" /> | <HidePointer value="false" /> | ||
Line 53: | Line 55: | ||
<CullingMode value="CALVR" /> | <CullingMode value="CALVR" /> | ||
This value sets what CullVisitor to use for the scene. The options are "CALVR" for our custom visitor and "DEFAULT" for the osg default visitor. The CalVR visitor has some modifications for cluster graphics and uses some special node masks. See [[CalVR Node Masks]] | This value sets what CullVisitor to use for the scene. The options are "CALVR" for our custom visitor and "DEFAULT" for the osg default visitor. The CalVR visitor has some modifications for cluster graphics and uses some special node masks. See [[CalVR Node Masks]] | ||
+ | <br> | ||
+ | <MultiSample value="0" /> | ||
+ | This sets the number of multi-sampling buffers to use. The valid values will depend on graphics hardware, 0, 2, 4 are good bets. | ||
<br> | <br> | ||
<ConfigDebug value="false" /> | <ConfigDebug value="false" /> | ||
Line 99: | Line 104: | ||
<Orientation h="0" p="0" r="0" /> | <Orientation h="0" p="0" r="0" /> | ||
</Body#> | </Body#> | ||
− | These tags allows you to provide a translation/rotation correction on each tracked body in the system(replace # with body id) | + | These tags allows you to provide a translation/rotation correction on each tracked body in the system(replace # with body id). The rotation is done before the translation. |
<br> | <br> | ||
<br>The value for the tracking system defines the system type. | <br>The value for the tracking system defines the system type. | ||
Line 106: | Line 111: | ||
====VRPN==== | ====VRPN==== | ||
A vrpn tracking system must define a vrpn server to connect to. This is done like so: | A vrpn tracking system must define a vrpn server to connect to. This is done like so: | ||
− | <TrackingSystem#> | + | <TrackingSystem# value="VRPN" > |
... | ... | ||
<VRPN> | <VRPN> | ||
Line 115: | Line 120: | ||
====SHMEM==== | ====SHMEM==== | ||
This type of tracking system reads data out of a shared memory block that is an output of trackd. You can define which shared memory id to read for the tracker and controller: | This type of tracking system reads data out of a shared memory block that is an output of trackd. You can define which shared memory id to read for the tracker and controller: | ||
− | <TrackingSystem#> | + | <TrackingSystem# value="SHMEM" > |
... | ... | ||
<SHMEM> | <SHMEM> | ||
Line 123: | Line 128: | ||
... | ... | ||
</TrackingSystem#> | </TrackingSystem#> | ||
+ | |||
===Heads=== | ===Heads=== | ||
To define the heads being tracked, you must first state the number of heads. | To define the heads being tracked, you must first state the number of heads. | ||
Line 138: | Line 144: | ||
<Address system="0" body="1" /> | <Address system="0" body="1" /> | ||
<ButtonMask system0="0xFF" system1="0x00" /> | <ButtonMask system0="0xFF" system1="0x00" /> | ||
− | |||
<Valuator0 system="1" number="0" type="NON_ZERO" /> | <Valuator0 system="1" number="0" type="NON_ZERO" /> | ||
+ | <ButtonMapping value="1,2,0,3,4" /> | ||
</Hand#> | </Hand#> | ||
The Address defines the tracking system and body id to use for the hand position/orientation. | The Address defines the tracking system and body id to use for the hand position/orientation. | ||
<br>The button mask is used to assign buttons to this hand. The mask is in hex. This example tells the hand to use the first 16 buttons from the first system and no buttons from the second. If there are less buttons defined in the system, it will only use that many buttons. Each hand button is given a unique id numbered from the lowest system to the highest. These ids are used in button events. | <br>The button mask is used to assign buttons to this hand. The mask is in hex. This example tells the hand to use the first 16 buttons from the first system and no buttons from the second. If there are less buttons defined in the system, it will only use that many buttons. Each hand button is given a unique id numbered from the lowest system to the highest. These ids are used in button events. | ||
<br> | <br> | ||
− | <br>Each hand may also be assigned a number of valuator(analog) inputs. | + | <br>It is possible to remap the button numbers for a given hand using the ButtonMapping tag as above. The value is a comma separated list of numbers for the new button mapping. In the above example, the old button 0 will now create events with the button id 1 and 1->2, 2->0, etc. The logical button order after this mapping would be: 2,0,1,3,4. It is not required to list a number for every button. However, any button without a new mapping will keeps its origin id. It is possible to have more than one button map to the same id, though this might make event handling more interesting. |
+ | <br> | ||
+ | <br>Each hand may also be assigned a number of valuator(analog) inputs. The valuator numbering must start with zero and increase without skipping. The type value is used when generating valuator events. A value of "NON_ZERO" will create a valuator event when its value is not zero. A value of "CHANGE" will create a valuator event only when the value changes. | ||
<br> | <br> | ||
<br>This is a more complex input definition: | <br>This is a more complex input definition: | ||
Line 178: | Line 186: | ||
<Address system="0" body="1" /> | <Address system="0" body="1" /> | ||
<ButtonMask system0="0x00" system1="0xFF" /> | <ButtonMask system0="0x00" system1="0xFF" /> | ||
− | |||
<Valuator0 system="1" number="0" type="NON_ZERO" /> | <Valuator0 system="1" number="0" type="NON_ZERO" /> | ||
</Hand1> | </Hand1> | ||
Line 185: | Line 192: | ||
==Menu System== | ==Menu System== | ||
− | + | This sections sets the options for the main menu. Here is an example: | |
+ | <MenuSystem type="BOARDMENU"> | ||
+ | <BoardMenu> | ||
+ | <Position distance="3000" /> | ||
+ | <Scale value="1.0" /> | ||
+ | <Buttons select="0" open="1" /> | ||
+ | <Trigger value="DOUBLECLICK" /> | ||
+ | </BoardMenu> | ||
+ | </MenuSystem> | ||
+ | The type defines the menu implementation to use for the main menu. Currently, only the BOARDMENU is implemented. | ||
+ | ===BoardMenu=== | ||
+ | The board menu config looks like so: | ||
+ | <BoardMenu> | ||
+ | <Position distance="3000" /> | ||
+ | <Scale value="1.0" /> | ||
+ | <Buttons select="0" open="1" /> | ||
+ | <Trigger value="DOUBLECLICK" /> | ||
+ | </BoardMenu> | ||
+ | The Position distance defines how far down the pointer the menu appears when it is spawned. The Scale value allows you to scale the size of the whole menu. Two buttons are used to work the menu system. One is used to make the menu appear and the other is used to select items in the menu (think right/left click). The Trigger value defines how to spawn the menu. Currently, only DOUBLECLICK is implemented, meaning the menu is opened by double clicking the open button. | ||
+ | ==Context Menus== | ||
+ | This section defines options used for context menus (the menus used for [[SceneObjects]]) | ||
+ | <br>Here is an example config: | ||
+ | <ContextMenus> | ||
+ | <Scale value="0.4" /> | ||
+ | <MinDistance value="750" /> | ||
+ | <MaxDistance value="1500" /> | ||
+ | <DefaultOpenButton value="1" /> | ||
+ | </ContextMenus> | ||
+ | The Scale value sets the menu size scale for all context menus. The min and max distances set the distance range down the pointer that the menus can spawn. If the [[SceneObject]] intersection is within this range, the menu will appear at the intersection point. Otherwise it will appear a the min/max distance. The DefaultOpenButton sets the button used to open a context menu. This is by default set to the same button as the default board menu open button. | ||
==Plugins== | ==Plugins== | ||
The config file contains an area reserved for information relating to the loading and running of plugins. | The config file contains an area reserved for information relating to the loading and running of plugins. | ||
Line 200: | Line 235: | ||
==Graphics Window Config== | ==Graphics Window Config== | ||
+ | In order to specify a screen configuration in CalVR, you must define pipes, windows, channels, and screens. | ||
+ | |||
+ | ===Pipes=== | ||
+ | A pipe is an interface to the windowing system. In the case of linux, this defines and x server/screen pair. | ||
+ | <br> A sample pipe config looks like this: | ||
+ | <NumPipes value="2" /> | ||
+ | <PipeConfig> | ||
+ | <Pipe server="0" screen="0" name="0" /> | ||
+ | <Pipe server="0" screen="1" name="1" /> | ||
+ | </PipeConfig> | ||
+ | The name attribute defines the pipe number. This must start with 0 and not skip. | ||
+ | |||
+ | ===Windows=== | ||
+ | A window describes a graphics context window using a given pipe. | ||
+ | <br> A sample window config looks like this: | ||
+ | <NumWindows value="2" /> | ||
+ | <WindowConfig> | ||
+ | <Window width="1024" pipeIndex="0" height="768" left="0" bottom="0" name="0" /> | ||
+ | <Window width="1024" pipeIndex="1" height="768" left="0" bottom="0" name="1" /> | ||
+ | </WindowConfig> | ||
+ | The width and height define the window size in pixels. The left and bottom define an offset for the window within the pipe. The pipeIndex selects the pipe for the window. The name defines the window number. This must start with 0 and not skip. | ||
+ | <br> | ||
+ | <br>The following are attributes that can be added to the window tag with their default values: | ||
+ | decoration="false" | ||
+ | If true, the window has a title bar and border. | ||
+ | useCursor="(see below)" | ||
+ | This defines if the mouse cursor is visible when in the window. This defaults to true on the master node and false on the render nodes. | ||
+ | quadBuffer="false" | ||
+ | If true, the window is created for quad buffered stereo. | ||
+ | overrideRedirect="false" | ||
+ | Some distros of linux will do some funny things to created windows, like resize them so the task bars are visible. If the windows are not being created as specified, this can be used to force your configuration. Note: if you alt tab out of a window with this option, there is no way to get back into it, you must kill the process in a terminal. I do not recommend using this on the head node if possible. | ||
+ | |||
+ | ===Channels=== | ||
+ | A channel is a viewport within a graphics window. | ||
+ | <br>A sample channel config looks like this: | ||
+ | <NumChannels value="2" /> | ||
+ | <ChannelConfig> | ||
+ | <Channel width="1024" height="768" left="0" bottom="0" stereoMode="LEFT" windowIndex="0" name="0" /> | ||
+ | <Channel width="1024" height="768" left="0" bottom="0" stereoMode="RIGHT" windowIndex="1" name="1" /> | ||
+ | </ChannelConfig> | ||
+ | The width and height define the size of the viewport in pixels. The left and bottom are the offset of the viewport within the window. The windowIndex is the window number to contain this channel. The name is the channel number. This must start with 0 and not skip. You can also specify an attribute head="(head number)". This will tell the screen to render from the given head number if you are using more than one tracked head. This does not work for all stereo modes, but it works for the main ones. | ||
+ | |||
+ | ====Stereo Mode==== | ||
+ | The stereoMode attribute selects what type of rendering to use in this channel. The standard monoscopic viewing modes are MONO, LEFT, and RIGHT. These do standard perspective rendering from a left , right, or center eye position. | ||
+ | <br> | ||
+ | <br>Your can also set this attribute to render in the default OpenSceneGraph stereo modes: HORIZONTAL_INTERLACE, VERTICAL_INTERLACE, VERTICAL_SPLIT, HORIZONTAL_SPLIT, ANAGLYPHIC, CHECKERBOARD, and QUAD_BUFFER. | ||
+ | <br> | ||
+ | <br>There are a number of stereo options that are used for our multi-viewer work, but they are mainly for research so I will not go into them here. | ||
+ | <br> | ||
+ | <br>You can use the option FIXED_VIEWER to create a channel that renders from a specified position. To do this, you need to specify the position as such: | ||
+ | <Channel width="1024" height="768" left="0" bottom="0" stereoMode="FIXED_VIEWER" windowIndex="0" name="0" > | ||
+ | <ViewerPosition x="0.0" y="-3000" z="0.0" /> | ||
+ | </Channel> | ||
+ | <br>A value of HMD will render the channel as a head mounted display. For this mode, define the screen location in viewer space rather than world space. | ||
+ | <br> | ||
+ | <br>A value of INTERLACED_TOP_BOTTOM will render horizontal interlaced stereo by drawing to and FBO with top bottom stereo and using a shader to create interlaced stereo. This can be useful on some screens that take interlaced stereo, but not top bottom. This mode can look better with lines and allows good use of FSAA. | ||
+ | <br> | ||
+ | <br>A value of LENTICULAR allows use of interleaver rendering for lenticular displays. In order for this mode to work, CalVR must be compiled with the interleaver library. TODO: add library link and config info. | ||
+ | |||
+ | ===Screens=== | ||
+ | A screen defines the CalVR world space parameters to use for a given channel. | ||
+ | <br>A sample screen config looks like this: | ||
+ | <NumScreens value="1" /> | ||
+ | <ScreenConfig> | ||
+ | <Screen width="2000" height="1500" originX="0" originY="0" originZ="0" h="0.0" p="0.0" r="0.0" name="0" /> | ||
+ | </ScreenConfig> | ||
+ | The width and height are the world space size of the screen. For the time being, this is in milimeters. The originX/Y/Z are the world space coordinates of the center of the screen. Note: CalVR uses an x right, y forward, z up coord system. h/p/r are the screen rotations about its center. A screen with no rotation is assumed to be in the x/z plane. Heading is over the z axis, pitch is over the x axis and roll is over the y axis. The order of rotation is roll->pitch->heading. The name attribute defines the screen number. This must start with zero and not skip. | ||
+ | |||
+ | ==Clustering== | ||
+ | For this config, I am assuming you have a graphics cluster set up, there is some sort of ssh key sharing, and the user running CalVR can create a graphics window on the render nodes. | ||
+ | <br>Here is an example config block: | ||
+ | <MultiPC> | ||
+ | <NumSlaves value="5" /> | ||
+ | <MasterInterface value="10.1.1.1" port="11011" /> | ||
+ | <CleanupScript value="tentakel killall -9 CalVR" /> | ||
+ | <Startup value="ssh ${USER}@tile-0-0 if \( \{ test -d `pwd` \} \) cd `pwd` \;CalVR \>\& /tmp/errors.log" name="0" /> | ||
+ | <Startup value="ssh ${USER}@tile-0-1 if \( \{ test -d `pwd` \} \) cd `pwd` \;CalVR \>\& /tmp/errors.log" name="1" /> | ||
+ | <Startup value="ssh ${USER}@tile-0-2 if \( \{ test -d `pwd` \} \) cd `pwd` \;CalVR \>\& /tmp/errors.log" name="2" /> | ||
+ | <Startup value="ssh ${USER}@tile-1-0 if \( \{ test -d `pwd` \} \) cd `pwd` \;CalVR \>\& /tmp/errors.log" name="3" /> | ||
+ | <Startup value="ssh ${USER}@tile-1-1 if \( \{ test -d `pwd` \} \) cd `pwd` \;CalVR \>\& /tmp/errors.log" name="4" /> | ||
+ | </MultiPC> | ||
+ | The NumSlaves is the number of render nodes to use. The MasterInterface is the network interface the render nodes will use to communicate with the master over the given port. If the master node is not able to bind to the given port, it can mean there might still be a process running on a render node. The CleanupScript is automatically run if this happens, I normally set it to try to kill all CalVR instances on the cluster. | ||
+ | <br> | ||
+ | <br>For each render node, there is a startup script specified. This is a standard one we use. It connects into the node, attempts to change to the same directory as the master, and runs CalVR piping output to a file in the tmp directory. The directory change allows use of relative paths, which can be good when passing a file on the command line. On our systems we usually share home/data directories across the cluster, so this works well. | ||
+ | <br>Note: Currently, "CalVR" must be present in the Startup line. At runtime it has parameters added after it. | ||
+ | <br> | ||
+ | <br>The name attribute specifies the node number. Unlike the screen configuration, this number need not start with 0, or go in order. It must, however, be between 0 and 100. | ||
==Example== | ==Example== | ||
Until I can make some clean examples, a good place to look is in the files in the ${CALVR_HOME}/config directory. | Until I can make some clean examples, a good place to look is in the files in the ${CALVR_HOME}/config directory. |
Latest revision as of 16:19, 20 November 2012
Contents |
Overview
The CalVR config file holds all the configuration information for the CalVR kernel and its plugins. The $CALVR_CONFIG_FILE environment variable specifies a colon separated list of files to load. The files can either be an absolute path or a path relative to the default config directory. This directory defaults to $CALVR_HOME/config but can be changed with the $CALVR_CONFIG_DIR if needed.
Include, local and Priority
Each xml file has the option of including other xml files, for example:
<INCLUDE>xpol-cinter-mobile.xml</INCLUDE>
Where this tag is in the file is not important, its contents is added to global scope.
If you want to allow for different information to be visible on different rendernodes, for a screen configuration for example, you need to use local tags:
<LOCAL host="calit2-137-110-111-71.ucsd.edu" > <NumPipes value="1" /> </LOCAL>
The host attribute is a comma separated list of hosts that will see this tag structure. The LOCAL tag itself is transparent to the application, and thus should not appear in the tag path.
When looking for a config file value, all open xml files are searched until the first instance of the tag/attribute pair is found. If not found, the default value is returned. The file search order starts with the root config file, then looks in its first included file, then those included from that file, etc., then the root's second included file, then its included files... Basically, tag/attribute combinations in a file will override the value defined in any of its included files. If multiple files are listed in $CALVR_CONFIG_FILE, the first file and its includes are search before next file listed, and so on.
Global Tags
CalVR uses the following tag values from the global scope with the following default values:
<MultiThreaded value="SingleThreaded" />
Sets the thread model for rendering. Uses a osgViewer::ViewerBase::ThreadingModel value: "SingleThreaded", "CullThreadPerCameraDrawThreadPerContext", "CullDrawThreadPerContext", "DrawThreadPerContext"
<RenderOnMaster value="true" />
Sets if the master node in a cluster setup should draw. A graphics window is still opened and all other things occure, but the cull/draw is skipped.
<Freeze value="false" />
When set to "true", the camera position stops getting updated by the tracked head position.
<SyncToVBlank value="false" />
When set to "true", sets driver hint to sync buffer swap to vertical blanking.
<Near value="10.0" />
Sets the near plane value for cameras.
<Far value="10000000" />
Sets the far plane value for cameras.
<Stereo separation="64.0" omniStereo="false" />
separation - Value to use for distance between left and right eye for stereo rendering (mm).
omniStereo - Used to turn on omnidirectional stereo rendering. In this mode, the viewer position is still determined by the tracked user, but the direction is always towards the center of each screen. This can be good in a large surround system being viewed by many people (e.g. CAVE2). If this attribute is present in the config file (either true or false), there will be a checkbox in the main menu to toggle this feature at runtime.
<Stencil value="false" />
Sets if the graphics window should be created with a stencil buffer.
<ShowAxis value="false" />
When set to "true", an coord axis is displayed for world space, object space, each hand and each head. x = red, y = green, z = blue.
<UseDepthPartition value="false" />
When set to "true", a depth partition node is used at the scene root. This is useful when you have scenes too large to set a static near/far value and there is lots of empty space within the depth range. (e.g. ossimPlanet viewing)
<HidePointer value="false" />
When set to "true" the wand pointers for the hands are not visible.
<CullingMode value="CALVR" />
This value sets what CullVisitor to use for the scene. The options are "CALVR" for our custom visitor and "DEFAULT" for the osg default visitor. The CalVR visitor has some modifications for cluster graphics and uses some special node masks. See CalVR Node Masks
<MultiSample value="0" />
This sets the number of multi-sampling buffers to use. The valid values will depend on graphics hardware, 0, 2, 4 are good bets.
<ConfigDebug value="false" />
When set to "true", all config value requests are printed with whatever value was found.
<ViewerPosition x="0" y="0" z="0" />
Defines the default location of the viewer camera.
Tracking
This is a simple example of tracking configuration:
<Input> <Threaded FPS="60.0" /> <TrackingSystem0 value="MOUSE"> <Offset x="0" y="0" z="0" /> <Orientation h="0" p="0" r="0" /> <NumBodies value="1" /> <NumButtons value="3" /> <NumValuators value="0" /> <Body0> <Offset x="0" y="0" z="0" /> <Orientation h="0" p="0" r="0" /> </Body0> </TrackingSystem0> <NumHeads value="0" /> <NumHands value="1" /> <Hand0> <Address system="0" body="0" /> <ButtonMask system0="0xFF" /> </Hand0> </Input>
Tracking is configured by defining the tracking systems being used and how the input from these systems is mapped to head(s) and hand(s). The above example is a simple setup that could be used by a desktop. It defines the basic mouse tracking system with with one tracked body and three buttons. There are 0 tracked heads define, so the ViewerPosition value will be used for the head position/orientation. There is 1 hand that uses the mouse body and buttons.
I will now go into more detail on configuring these tags.
TrackingSystem#
An arbitrary number of tracking systems may be define with TrackingSystem# tags. The only restriction is that the system number must start with 0 and must increment without skipping.
Within the TrackingSystem# tag there are various options.
<Offset x="0" y="0" z="0" /> <Orientation h="0" p="0" r="0" />
These values define a global transform of the tracking data. The orientation rotates the coordinates of the system and the offset provides a global transformation.(transforms applied roll->pitch->heading)
<NumBodies value="1" /> <NumButtons value="3" /> <NumValuators value="0" />
These values define the number of tracked bodies, buttons, and valuators(analog) values in this tracking system.
<Body#> <Offset x="0" y="0" z="0" /> <Orientation h="0" p="0" r="0" /> </Body#>
These tags allows you to provide a translation/rotation correction on each tracked body in the system(replace # with body id). The rotation is done before the translation.
The value for the tracking system defines the system type.
MOUSE
A mouse tracking system uses the mouse input from the head node. It has at most one tracked body and three buttons. The tracked body is created so that the body origin is at the same point as the camera position. The orientation is calculated based on this point and the intersection of the mouse with the screen. There are no special options for this system.
VRPN
A vrpn tracking system must define a vrpn server to connect to. This is done like so:
<TrackingSystem# value="VRPN" > ... <VRPN> <Server value="Device0@127.0.0.1:7701" /> </VRPN> ... </TrackingSystem#>
SHMEM
This type of tracking system reads data out of a shared memory block that is an output of trackd. You can define which shared memory id to read for the tracker and controller:
<TrackingSystem# value="SHMEM" > ... <SHMEM> <TrackerID value="4126" /> <ControllerID value="4127" /> </SHMEM> ... </TrackingSystem#>
Heads
To define the heads being tracked, you must first state the number of heads.
<NumHeads value="1" />
There must be an entry to define each head.
<Head#Address system="0" body="0" />
The system is the tracking system id and the body is the body id within the tracking system.
Note: When the number of heads is set to 0 the default viewer position/orientation is used and not updated.
Hands
To define the hands being tracked, you must first state the number of hands.
<NumHands value="1" />
You then must define each hand.
<Hand#> <Address system="0" body="1" /> <ButtonMask system0="0xFF" system1="0x00" /> <Valuator0 system="1" number="0" type="NON_ZERO" /> <ButtonMapping value="1,2,0,3,4" /> </Hand#>
The Address defines the tracking system and body id to use for the hand position/orientation.
The button mask is used to assign buttons to this hand. The mask is in hex. This example tells the hand to use the first 16 buttons from the first system and no buttons from the second. If there are less buttons defined in the system, it will only use that many buttons. Each hand button is given a unique id numbered from the lowest system to the highest. These ids are used in button events.
It is possible to remap the button numbers for a given hand using the ButtonMapping tag as above. The value is a comma separated list of numbers for the new button mapping. In the above example, the old button 0 will now create events with the button id 1 and 1->2, 2->0, etc. The logical button order after this mapping would be: 2,0,1,3,4. It is not required to list a number for every button. However, any button without a new mapping will keeps its origin id. It is possible to have more than one button map to the same id, though this might make event handling more interesting.
Each hand may also be assigned a number of valuator(analog) inputs. The valuator numbering must start with zero and increase without skipping. The type value is used when generating valuator events. A value of "NON_ZERO" will create a valuator event when its value is not zero. A value of "CHANGE" will create a valuator event only when the value changes.
This is a more complex input definition:
<Input> <Threaded FPS="60.0" /> <TrackingSystem0 value="MOUSE"> <Offset x="0" y="0" z="0" /> <Orientation h="0" p="0" r="0" /> <NumBodies value="1" /> <NumButtons value="3" /> <NumValuators value="0" /> <Body0> <Offset x="0" y="0" z="0" /> <Orientation h="0" p="0" r="0" /> </Body0> </TrackingSystem0> <TrackingSystem1 value="VRPN"> <NumBodies value="1" /> <NumButtons value="3" /> <NumValuators value="1" /> <VRPN> <Server value="Device0@127.0.0.1:7701" /> </VRPN> </TrackingSystem1> <NumHeads value="1" /> <Head0Address system="1" body="0" /> <NumHands value="2" /> <Hand0> <Address system="0" body="0" /> <ButtonMask system0="0xFF" system1="0x00" /> </Hand0> <Hand1> <Address system="0" body="1" /> <ButtonMask system0="0x00" system1="0xFF" /> <Valuator0 system="1" number="0" type="NON_ZERO" /> </Hand1> </Input>
It defines two tracking systems, one the default mouse and one from a vrpn server. It defines one tracked head device and two hands.
Menu System
This sections sets the options for the main menu. Here is an example:
<MenuSystem type="BOARDMENU"> <BoardMenu> <Position distance="3000" /> <Scale value="1.0" /> <Buttons select="0" open="1" /> <Trigger value="DOUBLECLICK" /> </BoardMenu> </MenuSystem>
The type defines the menu implementation to use for the main menu. Currently, only the BOARDMENU is implemented.
BoardMenu
The board menu config looks like so:
<BoardMenu> <Position distance="3000" /> <Scale value="1.0" /> <Buttons select="0" open="1" /> <Trigger value="DOUBLECLICK" /> </BoardMenu>
The Position distance defines how far down the pointer the menu appears when it is spawned. The Scale value allows you to scale the size of the whole menu. Two buttons are used to work the menu system. One is used to make the menu appear and the other is used to select items in the menu (think right/left click). The Trigger value defines how to spawn the menu. Currently, only DOUBLECLICK is implemented, meaning the menu is opened by double clicking the open button.
Context Menus
This section defines options used for context menus (the menus used for SceneObjects)
Here is an example config:
<ContextMenus> <Scale value="0.4" /> <MinDistance value="750" /> <MaxDistance value="1500" /> <DefaultOpenButton value="1" /> </ContextMenus>
The Scale value sets the menu size scale for all context menus. The min and max distances set the distance range down the pointer that the menus can spawn. If the SceneObject intersection is within this range, the menu will appear at the intersection point. Otherwise it will appear a the min/max distance. The DefaultOpenButton sets the button used to open a context menu. This is by default set to the same button as the default board menu open button.
Plugins
The config file contains an area reserved for information relating to the loading and running of plugins.
Each tag under the Plugin tag is looked at as naming a plugin. The value of this tag defines if the plugin should be loaded or not. An example would be:
<Plugin> <ModelLoader value="on" > <ConfigDir value="/home/aprudhom/data/ModelLoader/" /> <Files> <se_building path="/home/aprudhom/data/falko/se_building.obj" mask="1" /> </Files> </ModelLoader> </Plugin>
The above tells CalVR to try to open a plugin library called "ModelLoader". The rest of the information is used by the plugin itself. Note: the first on/off value for a plugin when reading through the config file will determine if it is loader or not.
Graphics Window Config
In order to specify a screen configuration in CalVR, you must define pipes, windows, channels, and screens.
Pipes
A pipe is an interface to the windowing system. In the case of linux, this defines and x server/screen pair.
A sample pipe config looks like this:
<NumPipes value="2" /> <PipeConfig> <Pipe server="0" screen="0" name="0" /> <Pipe server="0" screen="1" name="1" /> </PipeConfig> The name attribute defines the pipe number. This must start with 0 and not skip.
Windows
A window describes a graphics context window using a given pipe.
A sample window config looks like this:
<NumWindows value="2" /> <WindowConfig> <Window width="1024" pipeIndex="0" height="768" left="0" bottom="0" name="0" /> <Window width="1024" pipeIndex="1" height="768" left="0" bottom="0" name="1" /> </WindowConfig>
The width and height define the window size in pixels. The left and bottom define an offset for the window within the pipe. The pipeIndex selects the pipe for the window. The name defines the window number. This must start with 0 and not skip.
The following are attributes that can be added to the window tag with their default values:
decoration="false"
If true, the window has a title bar and border.
useCursor="(see below)"
This defines if the mouse cursor is visible when in the window. This defaults to true on the master node and false on the render nodes.
quadBuffer="false"
If true, the window is created for quad buffered stereo.
overrideRedirect="false"
Some distros of linux will do some funny things to created windows, like resize them so the task bars are visible. If the windows are not being created as specified, this can be used to force your configuration. Note: if you alt tab out of a window with this option, there is no way to get back into it, you must kill the process in a terminal. I do not recommend using this on the head node if possible.
Channels
A channel is a viewport within a graphics window.
A sample channel config looks like this:
<NumChannels value="2" /> <ChannelConfig> <Channel width="1024" height="768" left="0" bottom="0" stereoMode="LEFT" windowIndex="0" name="0" /> <Channel width="1024" height="768" left="0" bottom="0" stereoMode="RIGHT" windowIndex="1" name="1" /> </ChannelConfig>
The width and height define the size of the viewport in pixels. The left and bottom are the offset of the viewport within the window. The windowIndex is the window number to contain this channel. The name is the channel number. This must start with 0 and not skip. You can also specify an attribute head="(head number)". This will tell the screen to render from the given head number if you are using more than one tracked head. This does not work for all stereo modes, but it works for the main ones.
Stereo Mode
The stereoMode attribute selects what type of rendering to use in this channel. The standard monoscopic viewing modes are MONO, LEFT, and RIGHT. These do standard perspective rendering from a left , right, or center eye position.
Your can also set this attribute to render in the default OpenSceneGraph stereo modes: HORIZONTAL_INTERLACE, VERTICAL_INTERLACE, VERTICAL_SPLIT, HORIZONTAL_SPLIT, ANAGLYPHIC, CHECKERBOARD, and QUAD_BUFFER.
There are a number of stereo options that are used for our multi-viewer work, but they are mainly for research so I will not go into them here.
You can use the option FIXED_VIEWER to create a channel that renders from a specified position. To do this, you need to specify the position as such:
<Channel width="1024" height="768" left="0" bottom="0" stereoMode="FIXED_VIEWER" windowIndex="0" name="0" > <ViewerPosition x="0.0" y="-3000" z="0.0" /> </Channel>
A value of HMD will render the channel as a head mounted display. For this mode, define the screen location in viewer space rather than world space.
A value of INTERLACED_TOP_BOTTOM will render horizontal interlaced stereo by drawing to and FBO with top bottom stereo and using a shader to create interlaced stereo. This can be useful on some screens that take interlaced stereo, but not top bottom. This mode can look better with lines and allows good use of FSAA.
A value of LENTICULAR allows use of interleaver rendering for lenticular displays. In order for this mode to work, CalVR must be compiled with the interleaver library. TODO: add library link and config info.
Screens
A screen defines the CalVR world space parameters to use for a given channel.
A sample screen config looks like this:
<NumScreens value="1" /> <ScreenConfig> <Screen width="2000" height="1500" originX="0" originY="0" originZ="0" h="0.0" p="0.0" r="0.0" name="0" /> </ScreenConfig>
The width and height are the world space size of the screen. For the time being, this is in milimeters. The originX/Y/Z are the world space coordinates of the center of the screen. Note: CalVR uses an x right, y forward, z up coord system. h/p/r are the screen rotations about its center. A screen with no rotation is assumed to be in the x/z plane. Heading is over the z axis, pitch is over the x axis and roll is over the y axis. The order of rotation is roll->pitch->heading. The name attribute defines the screen number. This must start with zero and not skip.
Clustering
For this config, I am assuming you have a graphics cluster set up, there is some sort of ssh key sharing, and the user running CalVR can create a graphics window on the render nodes.
Here is an example config block:
<MultiPC> <NumSlaves value="5" /> <MasterInterface value="10.1.1.1" port="11011" /> <CleanupScript value="tentakel killall -9 CalVR" /> <Startup value="ssh ${USER}@tile-0-0 if \( \{ test -d `pwd` \} \) cd `pwd` \;CalVR \>\& /tmp/errors.log" name="0" /> <Startup value="ssh ${USER}@tile-0-1 if \( \{ test -d `pwd` \} \) cd `pwd` \;CalVR \>\& /tmp/errors.log" name="1" /> <Startup value="ssh ${USER}@tile-0-2 if \( \{ test -d `pwd` \} \) cd `pwd` \;CalVR \>\& /tmp/errors.log" name="2" /> <Startup value="ssh ${USER}@tile-1-0 if \( \{ test -d `pwd` \} \) cd `pwd` \;CalVR \>\& /tmp/errors.log" name="3" /> <Startup value="ssh ${USER}@tile-1-1 if \( \{ test -d `pwd` \} \) cd `pwd` \;CalVR \>\& /tmp/errors.log" name="4" /> </MultiPC>
The NumSlaves is the number of render nodes to use. The MasterInterface is the network interface the render nodes will use to communicate with the master over the given port. If the master node is not able to bind to the given port, it can mean there might still be a process running on a render node. The CleanupScript is automatically run if this happens, I normally set it to try to kill all CalVR instances on the cluster.
For each render node, there is a startup script specified. This is a standard one we use. It connects into the node, attempts to change to the same directory as the master, and runs CalVR piping output to a file in the tmp directory. The directory change allows use of relative paths, which can be good when passing a file on the command line. On our systems we usually share home/data directories across the cluster, so this works well.
Note: Currently, "CalVR" must be present in the Startup line. At runtime it has parameters added after it.
The name attribute specifies the node number. Unlike the screen configuration, this number need not start with 0, or go in order. It must, however, be between 0 and 100.
Example
Until I can make some clean examples, a good place to look is in the files in the ${CALVR_HOME}/config directory.