Difference between revisions of "COVISE and OpenCOVER support"
(→Tracker Data) |
|||
Line 256: | Line 256: | ||
} | } | ||
</pre> | </pre> | ||
+ | |||
+ | ===Wall Clock Time=== | ||
+ | |||
+ | If you are going to animate anything, keep in mind that the rendering system runs anywhere between 1 and 100 frames per second, so you can't rely on the time between frames being anything you assume. Instead, you will want to know exactly how much time has passed since you last rendered something, i.e., you last preFrame() call. You should use cover->frameTime(), or better cover->frameDuration(); these return a double value with the number of seconds (at an accuracy of milli- or even microseconds) passed since the start of the program, or since the last preFrame(), respectively. | ||
===Tracker Data=== | ===Tracker Data=== |
Revision as of 11:21, 23 February 2012
COVISE Tutorial
There is a six-lecture video course on Youtube at:
Lecture 1, Lecture 2, Lecture 3, Lecture 4, Lecture 5, Lecture 6
The accompanying slides are at:
Lecture 1, Lecture 2, Lecture 3, Lecture 4, Lecture 5, Lecture 6
Some of the slides of this course have been generously provided by Dr. Uwe Woessner from HLRS.
General information about COVISE modules
The entire COVISE installation, including all plugins, is located at /home/covise/covise/. Each user should have a link in their home directory named 'covise' which points to this directory. There should also be a link 'plugins' which points to the plugins directory: /home/covise/plugins/. You should put all the plugins you write into the directory: plugins/calit2/.
Other directories you might need throughout the project are:
- covise/src/renderer/OpenCOVER/kernel/: core OpenCOVER functionality, especially coVRPluginSupport.cpp
- covise/src/kernel/OpenVRUI/: OpenCOVER's user interface elements. useful documentation in doc/html subdirectory; browse by running Firefox on index.html
- covise/src/renderer/OpenCOVER/osgcaveui/: special CaveUI functions, not required in class but useful
You compile your plugin with the 'make' command, or 'make verbose' if you want to see the full compiler commands. This creates a library file in covise/rhel5/lib/OpenCOVER/plugins/. Covise uses qmake, so the make file is being generated by the .pro file. The name of the plugin is determined by the project name in the .pro file in your plugin directory (first line, keyword TARGET). I defaulted TARGET to be p1<username> for project #1. It is important that the TARGET name be unique, or else you will overwrite somebody else's plugin. You can change the name of your source files or add additional source files (.cpp,.h) by listing them after the SOURCES tag in the .pro file.
You run OpenCOVER by typing 'opencover' anywhere at the command line. You quit opencover by hitting the 'q' key on the keyboard or ctrl-c in the shell window you started it from.
Good examples for plugins are plugins/Volume and plugins/PDBPlugin. Look at the code in these plugins to find out how to add menu items and how to do interaction. Note that there are two ways to do interaction: with pure OpenCOVER routines, or with OSGCaveUI. In this course we will try to use only OpenCOVER's own routines. Plugins do not get loaded by opencover before they are configured in the configuration file.
Important Directories and URLs
- /home/covise/covise/config: configuration files
- /home/covise/covise/src/renderer/OpenCOVER/plugins/calit2: Calit2 plugin code
- /home/covise/covise/extern_libs/src/OpenSceneGraph-2.8.2: OpenSceneGraph installation directory
- /home/covise/covise/src/renderer/OpenCOVER: OpenCOVER source directory; core functions are in kernel subdirectory
- /home/covise/covise/src/kernel/OpenVRUI: virtual reality user interface widgets
- http://www.openscenegraph.org: main OSG web site
- http://openscenegraph.org/archiver/osg-users: OSG email archive. If you have an OSG problem, this is a good place to start.
Covise configuration files
The configuration files are in the directory /home/covise/covise/config. The most important files are:
- ivl.xml: general configuration information for all lab machines on the 2nd floor and room 6307
- NODENAME.xml: node specific information, e.g., sand.xml for sand.ucsd.edu
- cwall.xml: C-wall specific configuration information (cwall-1 and cwall-2.ucsd.edu)
- Xml configuration files can be syntax validated with xmllint, e.g. xmllint --debug --noout sand.xml
The configuration files are XML files which can be edited with any ASCII text editor (vi, emacs, nedit, gedit, ...). There are sections specific for certain machines. To load your plugin (e.g., MyPlugin) on one or more machines (e.g., chert and sand), you need to add or modify a section to contain:
<LOCAL host="chert,sand"> <COVER> <Plugin> <MyPlugin value="on" /> </Plugin> </COVER> </LOCAL>
Screen configuration:
OpenCOVER requires the following global tags to be configured for a proper display configuration: PipeConfig, WindowConfig, and ChannelConfig. Another required tag, ScreenConfig, needs to be set on a node by node basis, because it differs for every screen. In the following example, a cluster with one graphics card (pipe) per rendering node, one large desktop in Twinview mode (window) of size 3840x1200 pixels, and two separate rendering windows (channels), each 1920x1200 pixels, are being configured.
<PipeConfig> <Pipe display=":0.0" name="0" screen="0" pipe="0" /> </PipeConfig> <WindowConfig> <Window width="3840" comment="MAIN" window="0" pipeIndex="0" height="1200" left="0" bottom="0" name="0" decoration="false" /> </WindowConfig> <ChannelConfig> <Channel windowIndex="0" stereoMode="LEFT" channel="0" left="0" width="1920" bottom="0" height="1200" comment="C_A" name="0" /> <Channel windowIndex="0" stereoMode="LEFT" channel="1" left="1920" width="1920" bottom="0" height="1200" comment="C_B" name="1" /> </ChannelConfig>
The display parameters for the tiles are set on a per node basis with the ScreenConfig tag. The following example configures two tiles for node 'tile-0-0'. On each tile, the visible screen dimensions are 520x325 millimeters. The centers of the monitors are offset from the world coordinate system horizontaly by -1100 and -570 millimeters, respectively, and -360 millimeters vertically. A proper configuration file will list a section like the one below for every rendering node.
<LOCAL host="tile-0-0.local"> <COVER> <ScreenConfig> <Screen width="520" h="0.0" height="325" p="0.0" originX="-1100" comment="S_A" originY="0" r="0.0" name="0" originZ="-360" screen="0" /> <Screen width="520" h="0.0" height="325" p="0.0" originX="-570" comment="S_B" originY="0" r="0.0" name="1" originZ="-360" screen="1" /> </ScreenConfig> </COVER> </LOCAL>
The head node needs to be configured in the same way. If you are navigating with a mouse on the head node, you probably want to configure a larger screen size for the head node, so that it covers a larger area of the tiled screen. You can do this by adjusting the width and height values, but you want to make sure that the aspect ratio of the new values corresponds to the one of the OpenCOVER window.
Create new plugin using SVN and copy over to StarCAVE
To create new plugin:
> cd ~/plugins/calit2
> mkdir your_new_plugin_folder
> svn add your_new_plugin_folder
> cd your_new_plugin_folder
> svn commit
Move to StarCAVE:
Loggin to StarCAVE
> cd ~/plugins/calit2
> svn update your_new_plugin_folder
From now on, just use svn update and commit inside your plugin folder.
Change Default VRUI Menu Position/Size
Let WindowTitle be the title of the window (the text in its title bar). Then add the following section to the config file:
<COVER> <VRUI> <WindowTitle> <Menu> <Position x="0" y="0" z="0" /> <Size value="1.0" /> </Menu> </WindowTitle> </VRUI> </COVER>
Configure Lighting
By default there is a light source from 45 degrees up behind the viewer. To change this the following parameters can be set in the config file:
<COVER> <Lights> <Sun> <Specular value="on" r="1.0" g="1.0" b="1.0" /> <Diffuse value="on" r="1.0" g="1.0" b="1.0" /> <Ambient value="on" r="0.3" g="0.3" b="0.3" /> <Position value="on" x="0.0" y="0.0" z="10000.0" /> <Spot value="on" x="0.0" y="0.0" z="1.0" expo="0.0" angle="180.0" /> </Sun> <Lamp> <Specular value="on" r="1.0" g="1.0" b="1.0" /> <Diffuse value="on" r="1.0" g="1.0" b="1.0" /> <Ambient value="on" r="0.3" g="0.3" b="0.3" /> <Position value="on" x="0.0" y="0.0" z="10000.0" /> <Spot value="on" x="0.0" y="0.0" z="1.0" expo="0.0" angle="180.0" /> </Lamp> <Light1> <Specular value="on" r="1.0" g="1.0" b="1.0" /> <Diffuse value="on" r="1.0" g="1.0" b="1.0" /> <Ambient value="on" r="0.3" g="0.3" b="0.3" /> <Position value="on" x="0.0" y="0.0" z="10000.0" /> <Spot value="on" x="0.0" y="0.0" z="1.0" expo="0.0" angle="180.0" /> </Light1> <Light2> <Specular value="on" r="1.0" g="1.0" b="1.0" /> <Diffuse value="on" r="1.0" g="1.0" b="1.0" /> <Ambient value="on" r="0.3" g="0.3" b="0.3" /> <Position value="on" x="0.0" y="0.0" z="10000.0" /> <Spot value="on" x="0.0" y="0.0" z="1.0" expo="0.0" angle="180.0" /> </Light2> </Lights> </COVER>
Debugging OpenCover Plugins
OpenCover code can be debugged with gdb. If it throws a 'Segmentation Fault' make sure the core is getting dumped with 'unlimit coredumpsize'. Then you should find a file named 'core' or 'core.<pid>' in the directory you are running opencover from. Let's assume your latest core file is called core.4567 then you can run gdb with:
- gdb ~/covise/rhel5/bin/Renderer/OpenCOVER core.4567
RETURN through the startup screens until you get a command prompt. The two most important commands are:
- bt: to display the stack trace. The topmost call is the one which caused the segmentation fault.
- quit: to quit gdb
Documentation for gdb is at: http://sourceware.org/gdb/documentation/
Create OpenCOVER Menus
Here is an example which creates a sub-menu off the main OpenCOVER menu with two check boxes.
In header file:
Step #1: Derive plugin class from coMenuListener. Example:
class MyClass : public coVRPlugin, public coMenuListener
Step #2: Declare attributes for menu items. Example:
coSubMenuItem* _myMenuItem; coRowMenu* _myMenu; coCheckboxMenuItem* _myFirstCheckbox, *_mySecondCheckbox;
Step #3: Declare menu callback function. Example:
void menuEvent(coMenuItem*);
In .cpp file:
Step #4: Create menu in init() callback. Example:
void MyClass::createMenus() { _myMenuItem = new coSubMenuItem("My Menu"); _myMenu = new coRowMenu("My Menu"); _myMenuItem->setMenu(_myMenu); _myFirstCheckbox = new coCheckboxMenuItem("First Checkbox", true); _myMenu->add(_myFirstCheckbox); _myFirstCheckbox->setMenuListener(this); _mySecondCheckbox = new coCheckboxMenuItem("Second Checkbox", false); _myMenu->add(_mySecondCheckbox); _mySecondCheckbox->setMenuListener(this); cover->getMenu()->add(_myMenuItem); }
Step #5: Create callback function for menu interaction. Example:
void MyClass::menuEvent(coMenuItem* item) { if(item == _myFirstCheckbox) { _myFirstCheckbox->setState(true); _mySecondCheckbox->setState(false); } if(item == _mySecondCheckbox) { _myFirstCheckbox->setState(false); _mySecondCheckbox->setState(true); } }
Wall Clock Time
If you are going to animate anything, keep in mind that the rendering system runs anywhere between 1 and 100 frames per second, so you can't rely on the time between frames being anything you assume. Instead, you will want to know exactly how much time has passed since you last rendered something, i.e., you last preFrame() call. You should use cover->frameTime(), or better cover->frameDuration(); these return a double value with the number of seconds (at an accuracy of milli- or even microseconds) passed since the start of the program, or since the last preFrame(), respectively.
Tracker Data
Here is a piece of code to get the pointer (=wand) position (pos1) and a point 1000 millimeters from it (pos2) along the pointer line:
osg::Vec3 pointerPos1Wld = cover->getPointerMat().getTrans(); osg::Vec3 pointerPos2Wld = osg::Vec3(0.0, 1000.0, 0.0); pointerPos2Wld = pointerPos2Wld * cover->getPointerMat();
This is the way to get the head position in world space:
Vec3 viewerPosWld = cover->getViewerMat().getTrans();
Or in object space:
Vec3 viewerPosWld = cover->getViewerMat().getTrans(); Vec3 viewerPosObj = viewerPosWld * cover->getInvBaseMat();