Modifications for Varrier on Vellum

From Immersive Visualization Lab Wiki
Revision as of 11:36, 7 November 2008 by Aprudhom (Talk | contribs)

Jump to: navigation, search

Changes made for the implementation of varrier under covise on vellum:

Contents

Covise Config File Changes

The following tracking offsets were made:

<TrackingSystem>
  <Offset x="0" y="-1550" z="-1120" />
  <Orientation h="0" p="90" r="0" />
</TrackingSystem>

<HeadDevice>
  <Offset x="0" y="-25.4" z="38.1" />
  <Orientation h="0" p="-90" r="0" />
</HeadDevice>

<HandDevice>
  <Offset x="0" y="0" z="0" />
  <Orientation h="0" p="-90" r="90" />
</HandDevice>

Screen settings were changed and made different for the headnode:

<LOCAL host="vellum" >
   <!-- one window, two screens horizontally -->
   <!-- two channels in Window 0 one left and one right -->
   <!-- stereoMode: LEFT | VARRIER -->
   <COVER>
     <NumWindows value="1" />
     <NumScreens value="1" />
     <Stereo value="true"/>
     <ChannelConfig>
      <Channel windowIndex="0" stereoMode="LEFT" channel="0" left="0" width="640" bottom="0"  height="480" comment="MASTER" name="0" />
     </ChannelConfig>

     <WindowConfig>
      <Window window="0" pipeIndex="0" left="0" bottom="0" width="640" height="480" comment="MAIN" name="0" decoration="true" resize="on" />
     </WindowConfig>
   </COVER>
</LOCAL>

<LOCAL host="vellum1-10,vellum2-10,vellum3-10,vellum4-10,vellum5-10,vellum6-10,vellum7-10,vellum8-10,vellum9-10,vellum10-10,vellum11-10,vellum12-10,vellum13-10,vellum14-10,vellum15-10" >
   <!-- one window, two screens horizontally -->
   <!-- two channels in Window 0 one left and one right -->
   <!-- stereoMode: LEFT | VARRIER -->
   <COVER>
     <NumWindows value="2" />
     <NumScreens value="4" />
     <Stereo value="true"/>
     <ChannelConfig>
      <Channel windowIndex="0" stereoMode="VARRIER" channel="0" left="0"    width="1600" bottom="0"    height="1200" comment="C_A" name="0" />
      <Channel windowIndex="0" stereoMode="VARRIER" channel="1" left="0"    width="1600" bottom="1200" height="1200" comment="C_B" name="1" />
      <Channel windowIndex="1" stereoMode="VARRIER" channel="2" left="0" width="1600" bottom="0"    height="1200" comment="C_C" name="2" />
      <Channel windowIndex="1" stereoMode="VARRIER" channel="3" left="0" width="1600" bottom="1200" height="1200" comment="C_D" name="3" />
     </ChannelConfig>

     <WindowConfig>
      <Window window="0" pipeIndex="0" left="0" bottom="0" width="1600" height="2400" comment="MAIN" name="0" decoration="false" resize="off" />
      <Window window="1" pipeIndex="0" left="1600" bottom="0" width="1600" height="2400" comment="MAIN" name="1" decoration="false" resize="off" />
     </WindowConfig>
   </COVER>
</LOCAL>

OpenCOVER Files Modified

covise/src/renderer/OpenCOVER/kernel/ARToolKit.cpp

in void ARToolKitNode::drawImplementation(osg::RenderInfo &renderInfo) const: case statement added for Varrier mode

case osg::DisplaySettings::HORIZONTAL_INTERLACE:
case osg::DisplaySettings::VERTICAL_INTERLACE:
case osg::DisplaySettings::ANAGLYPHIC:
case osg::DisplaySettings::VARRIER:                  // ADDED FOR VARRIER
   /* TODO */
   break;

covise/src/renderer/OpenCOVER/kernel/coVRConfig.cpp

in int coVRConfig::parseStereoMode(const char *modeName) const: statement added to parse Varrier stereo mode

else if(modeName[0]=='\0')
  stereoMode = osg::DisplaySettings::ANAGLYPHIC;
else if(strcasecmp(modeName,"VARRIER")==0)                         // ADDED FOR VARRIER
  stereoMode = osg::DisplaySettings::VARRIER;                          // ADDED FOR VARRIER
else
  cerr << "Unknown stereo mode \"" << modeName << "\"" << endl;

OpenSceneGraph-2.4 Files Modified

covise/extern_libs/src/OpenSceneGraph/include/osg/DisplaySettings

in class OSG_EXPORT DisplaySettings : public osg::Referenced

        enum StereoMode
        {
            QUAD_BUFFER,
            ANAGLYPHIC,
            HORIZONTAL_SPLIT,
            VERTICAL_SPLIT,
            LEFT_EYE,
            RIGHT_EYE,
            HORIZONTAL_INTERLACE,
            VERTICAL_INTERLACE,
            CHECKERBOARD,
            VARRIER                              // ADDED FOR VARRIER
        };

covise/extern_libs/src/OpenSceneGraph/include/osgUtil/SceneView

include added:

#include </home/covise/covise/extern_libs/include/VarrierCombiner.h>

in class OSGUTIL_EXPORT SceneView : public osg::Object, public osg::CullSettings

public functions added:
static void setVarrierTestPattern(bool b);
static bool isVarrierTestPattern();

protected members added:
static bool                                 _varrierTestPattern;
static VarrierCombiner**                    _varrier;
int _delayCount; 

covise/extern_libs/src/OpenSceneGraph/src/osgViewer/GraphicsWindowX11.cpp

in bool GraphicsWindowX11::createWindow(): added code to force override redirect.

    swatt.background_pixel = 0;
    swatt.border_pixel = 0;
    swatt.event_mask =  0;
    unsigned long mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;

    // START OF VARRIER ADDED CODE

    bool overrideRedirect = false;

    char * override = getenv("OSG_OVERRIDE_REDIRECT");

    if(override != NULL && (std::string(override) == "1" || std::string(override) == "true"))
    {
        overrideRedirect = true;
    }

    if (overrideRedirect)
    {
        swatt.override_redirect = true;
        mask |= CWOverrideRedirect;
    }

    _window = XCreateWindow( _display, _parent, ......

Added to fix title bars showing up randomly on some nodes. Not good to use on master node. The following:

if($HOST != "vellum") then
  setenv OSG_OVERRIDE_REDIRECT 1
endif

at the end of .cshrc will make it only work on tile nodes. NOTE: using this flag reverses the right and left eye in varrier, don't ask me why.

covise/extern_libs/src/OpenSceneGraph/src/osg/DisplaySettings.cpp

static ApplicationUsageProxy DisplaySetting_e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO_MODE <mode>","QUAD_BUFFER | ANAGLYPHIC | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE | VERTICAL_INTERLACE | HORIZONTAL_INTERLACE | VARRIER");  // VARRIER ADDED

in void DisplaySettings::readEnvironmentalVariables()

    if( (ptr = getenv("OSG_STEREO_MODE")) != 0)
    {
        if (strcmp(ptr,"QUAD_BUFFER")==0)
        {
            _stereoMode = QUAD_BUFFER;
        }
        ......
        else if (strcmp(ptr,"VARRIER")==0)
        {
            _stereoMode = VARRIER;
        }
    }

in void DisplaySettings::readCommandLine(ArgumentParser& arguments)

    if (arguments.getApplicationUsage())
    {
        arguments.getApplicationUsage()->addCommandLineOption("--display <type>","MONITOR | POWERWALL | REALITY_CENTER | HEAD_MOUNTED_DISPLAY");
        arguments.getApplicationUsage()->addCommandLineOption("--stereo","Use default stereo mode which is ANAGLYPHIC if not overriden by environmental variable");
        arguments.getApplicationUsage()->addCommandLineOption("--stereo <mode>","ANAGLYPHIC | QUAD_BUFFER | HORIZONTAL_SPLIT | VERTICAL_SPLIT | VARRIER | LEFT_EYE | RIGHT_EYE | HORIZONTAL_INTERLACE | VERTICAL_INTERLACE | CHECKERBOARD | ON | OFF ");   // VARRIER ADDED
        ......

    while ((pos=arguments.find("--stereo"))!=0)
    {
        if (arguments.match(pos+1,"ANAGLYPHIC"))            { arguments.remove(pos,2); _stereo = true;_stereoMode = ANAGLYPHIC; }
        else if (arguments.match(pos+1,"QUAD_BUFFER"))      { arguments.remove(pos,2); _stereo = true;_stereoMode = QUAD_BUFFER; }
        else if (arguments.match(pos+1,"HORIZONTAL_SPLIT")) { arguments.remove(pos,2); _stereo = true;_stereoMode = HORIZONTAL_SPLIT; }
        else if (arguments.match(pos+1,"VERTICAL_SPLIT"))   { arguments.remove(pos,2); _stereo = true;_stereoMode = VERTICAL_SPLIT; }
        else if (arguments.match(pos+1,"HORIZONTAL_INTERLACE")) { arguments.remove(pos,2); _stereo = true;_stereoMode = HORIZONTAL_INTERLACE; }
        else if (arguments.match(pos+1,"VERTICAL_INTERLACE"))   { arguments.remove(pos,2); _stereo = true;_stereoMode = VERTICAL_INTERLACE; }
        else if (arguments.match(pos+1,"CHECKERBOARD"))     { arguments.remove(pos,2); _stereo = true;_stereoMode = CHECKERBOARD; }
        else if (arguments.match(pos+1,"VARRIER"))          { arguments.remove(pos,2); _stereo = true;_stereoMode = VARRIER; }    // ADDED FOR VARRIER
        .....

covise/extern_libs/src/OpenSceneGraph/src/osgUtil/SceneView.cpp

added static init:

VarrierCombiner ** SceneView::_varrier = NULL;
bool SceneView::_varrierTestPattern = false;

in SceneView::SceneView(DisplaySettings* ds): at end

    _delayCount = 10;

in SceneView::SceneView(const SceneView& rhs, const osg::CopyOp& copyop): at end

    _delayCount = rhs._delayCount;

in void SceneView::draw(): case added for switch(_displaySettings->getStereoMode())

           case(osg::DisplaySettings::VARRIER):
            {
              enum {VARRIER_LEFT_EYE = 0, VARRIER_RIGHT_EYE = 1};
              float screenLoc[60][9] =   // screen locations from vellum.lua FIXME: read from file instead
              {
                      { -4.7547, 1.5459, 0.6620, -0.0992, -0.0000, -1.3263, -0.0000, 1.0000, -0.0000 },
                      .....
              };
              float line_screen[60][5] = {

                      //{ 536.85342, -10.46, 0.0244, -0.0004, 0.75 },
                      { 536.85342, -10.445, 0.0231, 0.00075, 0.75 },
                      .....
              };
              int nodeLUT[15] = {14, 11, 8, 5, 2, 13, 10, 7, 4, 1, 12, 9, 6, 3, 0};

              osg::notify(osg::DEBUG_INFO) << "osgUtil::SceneView in varrier mode called" << std::endl;

              if (_delayCount >= 0)
              {
                --_delayCount;
                if (_delayCount==0)
                {

                  if(_varrier == NULL)
                  {
                    int maxContext = _renderInfo.getState()->getGraphicsContext()->getMaxContextID();
                    _varrier = new VarrierCombiner*[maxContext+1];

                    for(int i = 0; i <= maxContext; i++)
                    {
                      _varrier[i] = NULL;
                    }
                  }
                }
              }
              else    // call every time once init has been called
              {
                static int swidth = 0;
                static int sheight = 0;
                static float squality = 0.0;
                int contextid = _renderInfo.getState()->getContextID();
                // Initialize varrier combiner if not already initialized:
                if (_varrier[contextid] == NULL)
                {
                  swidth = int(getViewport()->width());
                  sheight = int(getViewport()->height());
                  char * qual = getenv("OSG_VARRIER_QUALITY");
                  if(qual == NULL)
                  {
                    squality = 1.0;
                  }
                  else
                  {
                    squality = atof(qual);
                    if(squality <= 0.0 || squality > 1.0)
                    {
                      squality = 1.0;
                    }
                  }
                  osg::notify(osg::DEBUG_INFO) << "viewport size: " << swidth << " x " << sheight << std::endl;
                  _varrier[contextid] = new VarrierCombiner(swidth, sheight, squality);
                  osg::notify(osg::DEBUG_INFO) << "initializing varrier in context: " << contextid << " with quality: " << squality << std::endl;
                }

                // Varrier coordinates are like OpenGL: x=right, y=up, z=out
                // Get eye positions from OSG:
                osg::Camera* camLeft  = _renderStageLeft->getCamera();
                osg::Camera* camRight = _renderStageRight->getCamera();
                Vec3 leftEye, rightEye, center, up;

                computeLeftEyeView(getViewMatrix()).getLookAt(leftEye,center, up);
                computeRightEyeView(getViewMatrix()).getLookAt(rightEye,center, up);

                // Rotate eyes 90 deg about x axis (Varrier uses y up coordinates):
                Matrixd rot;
                rot.makeRotate(90.0 * M_PI / 180.0, 1.0, 0.0, 0.0);
                leftEye  = rot * leftEye;
                rightEye = rot * rightEye;


                // Translate coordinate system to floor in center of screen circle:
                leftEye[1]  += 1120;  leftEye[2]  -= 1550;
                rightEye[1] += 1120;  rightEye[2] -= 1550;

                // Convert eyes to float array and feet:
                float eyeLeft[3];
                float eyeRight[3];
                const double MM_IN_FEET = 0.0032808399;
                for (int i=0; i<3; ++i) eyeLeft[i]  = leftEye[i] * MM_IN_FEET;
                for (int i=0; i<3; ++i) eyeRight[i] = rightEye[i] * MM_IN_FEET;

                osg::notify(osg::DEBUG_INFO) << "FEET: Left eye: "  << eyeLeft[0] << ", "  << eyeLeft[1] << ", "  << eyeLeft[2] << std::endl;
                osg::notify(osg::DEBUG_INFO) << "FEET: Right eye: " << eyeRight[0] << ", " << eyeRight[1] << ", " << eyeRight[2] << std::endl;

                osg::Viewport * vport = getViewport();
                vport->setViewport(vport->x(), vport->y(), swidth * squality , sheight * squality);
                setViewport(vport);

                // Get OpenGL viewport location on desktop:
                int x = int(getViewport()->x());
                int y = int(getViewport()->y());
                int width  = int(swidth);
                int height = int(sheight);

                osg::notify(osg::DEBUG_INFO) << "viewport: " << x << ", " << y << ", " << width << " x " << height << std::endl;

                // Calculate which screen index is being rendered:
                char hostname[33];
                gethostname(hostname, 32);
                int node;
                int screen;
                int quadrant;
                sscanf(hostname, "vellum%d-10", &node);
                --node;
                if (node<0) node = 0;  // for head node
                else node = nodeLUT[node];
                if (x==0 && y==0) quadrant = 0;
                else if (x==0 && y>0) quadrant = 1;
                else if (x>0 && y==0) quadrant = 2;
                else quadrant = 3;
                screen = node * 4 + (contextid * 2) + quadrant;
                osg::notify(osg::DEBUG_INFO) << "rendering using varrier combiner on " << hostname << ", node " << node << ", screen " << screen << std::endl;

                VarrierCombiner::Display varrierConfig;
                varrierConfig.viewport_x = x;
                varrierConfig.viewport_y = y;
                varrierConfig.viewport_w = width;
                varrierConfig.viewport_h = height;
                varrierConfig.quality = squality;

                // Create absolute points from vellum.lua values:
                varrierConfig.screen_BL[0] = screenLoc[screen][0];
                varrierConfig.screen_BL[1] = screenLoc[screen][1];
                varrierConfig.screen_BL[2] = screenLoc[screen][2];
                varrierConfig.screen_BR[0] = screenLoc[screen][0] + screenLoc[screen][3];
                varrierConfig.screen_BR[1] = screenLoc[screen][1] + screenLoc[screen][4];
                varrierConfig.screen_BR[2] = screenLoc[screen][2] + screenLoc[screen][5];
                varrierConfig.screen_TL[0] = screenLoc[screen][0] + screenLoc[screen][6];
                varrierConfig.screen_TL[1] = screenLoc[screen][1] + screenLoc[screen][7];
                varrierConfig.screen_TL[2] = screenLoc[screen][2] + screenLoc[screen][8];

                osg::notify(osg::DEBUG_INFO) <<
                  "screen - BL: " << varrierConfig.screen_BL[0] << ", " << varrierConfig.screen_BL[1] << ", " << varrierConfig.screen_BL[2] << ", " <<
                  "BR: " << varrierConfig.screen_BR[0] << ", " << varrierConfig.screen_BR[1] << ", " << varrierConfig.screen_BR[2] << ", " <<
                  "TL: " << varrierConfig.screen_TL[0] << ", " << varrierConfig.screen_TL[1] << ", " << varrierConfig.screen_TL[2] << ", " << std::endl;

                varrierConfig.pitch = line_screen[screen][0];
                varrierConfig.angle = line_screen[screen][1];
                varrierConfig.thick = line_screen[screen][2];
                varrierConfig.shift = line_screen[screen][3];
                varrierConfig.cycle = line_screen[screen][4];

                if( getDrawBufferValue() !=  GL_NONE)
                {
                    _renderStageLeft->setDrawBuffer(getDrawBufferValue());
                    _renderStageLeft->setReadBuffer(getDrawBufferValue());

                    _renderStageRight->setDrawBuffer(getDrawBufferValue());
                    _renderStageRight->setReadBuffer(getDrawBufferValue());
                }

                // ensure that all color planes are active.
                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
                if (cmask)
                {
                    cmask->setMask(true,true,true,true);
                }
                else
                {
                    cmask = new osg::ColorMask(true,true,true,true);
                    _localStateSet->setAttribute(cmask);
                }
                _renderStageLeft->setColorMask(cmask);
                _renderStageRight->setColorMask(cmask);

                _renderInfo.getState()->getContextID();
                osg::notify(osg::DEBUG_INFO) << "GL context ID: " << _renderInfo.getState()->getContextID() << std::endl;

                //_localStateSet->setAttribute(getViewport());
                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
                _renderStageRight->drawPreRenderStages(_renderInfo,previous);

                glPushAttrib(GL_ALL_ATTRIB_BITS);

    // render left eye:
                _varrier[contextid]->prepare(&varrierConfig, VARRIER_RIGHT_EYE);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                 osg::notify(osg::DEBUG_INFO) << "GL context ID: " << _renderInfo.getState()->getContextID() << std::endl;

                _renderStageLeft->draw(getRenderInfo(),previous);
                osg::notify(osg::DEBUG_INFO) << "After renderleft." << std::endl;

                if (_varrierTestPattern)
                {
                  glClearColor(0.0, 1.0, 0.0, 1.0);
                  glClear(GL_COLOR_BUFFER_BIT);
                }

    // render right eye:
                _varrier[contextid]->prepare(&varrierConfig, VARRIER_LEFT_EYE);
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

                _renderStageRight->draw(getRenderInfo(),previous);
                osg::notify(osg::DEBUG_INFO) << "After renderright." << std::endl;

                if (_varrierTestPattern)
                {
                  glClearColor(1.0, 0.0, 1.0, 1.0);
                  glClear(GL_COLOR_BUFFER_BIT);
                }

    // combine eyes:
                _varrier[contextid]->combine(&varrierConfig, eyeLeft, eyeRight);

                osg::notify(osg::DEBUG_INFO) << "After combine." << std::endl;

                glPopAttrib();
              }
            } // end varrier style
            break;

in bool SceneView::getStats(Statistics& stats): case added

        switch(_displaySettings->getStereoMode())
        {
        case(osg::DisplaySettings::QUAD_BUFFER):
        case(osg::DisplaySettings::ANAGLYPHIC):
        case(osg::DisplaySettings::HORIZONTAL_SPLIT):
        case(osg::DisplaySettings::VERTICAL_SPLIT):
        case(osg::DisplaySettings::VERTICAL_INTERLACE):
        case(osg::DisplaySettings::HORIZONTAL_INTERLACE):
        case(osg::DisplaySettings::VARRIER):                           // ADDED FOR VARRIER
        {
            bool resultLeft = _renderStageLeft->getStats(stats);
            bool resultRight = _renderStageRight->getStats(stats);
            return resultLeft && resultRight;
        }

functions added:

void SceneView::setVarrierTestPattern(bool b)
{
  _varrierTestPattern = b;
}

bool SceneView::isVarrierTestPattern()
{
  return _varrierTestPattern;
}

NOTE: osg needs to link against the varrier library, thus it needs to be added to the linking operation. Adding it to (osgDir)/src/osgViewer/CMakeFiles/osgViewer.dir/link.txt worked for me.

.cshrc Changes

#sets varrier quality mode
setenv OSG_VARRIER_QUALITY 0.5

#sets override flag for all but headnode
if($HOST != "vellum") then
  setenv OSG_OVERRIDE_REDIRECT 1
endif

Varrier Combiner

File:VarrierCombiner.tar