Modifications for Varrier and Alioscopy

From Immersive Visualization Lab Wiki
Jump to: navigation, search

Changes made for the implementation of varrier and alioscopy under covise on kaustalio:

Contents

OpenSceneGraph-2.8 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
            ALIOSCOPY                             // ADDED FOR ALIOSCOPY
        };

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

include added:

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


in struct ComputeStereoMatricesCallback:public osg::Referenced of the SceneView Class, following functions added:

            virtual osg::Matrixd computeEyeProjection(int i) const
            {
               (void)i;
               return osg::Matrixd();
            }
            virtual osg::Matrixd computeEyeView(int i) const
            {
               (void)i;
               return osg::Matrixd();
            }


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

public inline functions added:
        inline osg::Matrixd computeEyeProjection(int i)  const
        {
            if (_computeStereoMatricesCallback.valid()) return _computeStereoMatricesCallback->computeEyeProjection(i);
            else return osg::Matrixd();
        }

        inline osg::Matrixd computeEyeView(int i) const
        {
            if (_computeStereoMatricesCallback.valid()) return _computeStereoMatricesCallback->computeEyeView(i);
            else return osg::Matrixd();
        }

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

protected variables added:
        osg::ref_ptr<osgUtil::CullVisitor> *        _cullVisitorAlioscopy;
        osg::ref_ptr<osgUtil::StateGraph>  *        _rendergraphAlioscopy;
        osg::ref_ptr<osgUtil::RenderStage> *        _renderStageAlioscopy;

	static bool                 		    _varrierTestPattern;
        static VarrierCombiner**                    _varrier;

	static float                    	    _alioscopyDebug;
	static il_context **                	    _alioscopyContext;
	static il_display **                	    _alioscopyDisplay;
	static int                   		    _alioscopyEyes;
	static float                    	    _alioscopyIPD;
        static float                    	    _alioscopyIPDmm;
	static float                    	    _alioscopyViewDistance;
	float *                     	 	    _alioscopyEyePosition;

        int _delayCount;   // HACK WARNING: why is this necessary? tried putting this in ::init() but wouldn't get called

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

Change the line:

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”);

to the following:

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 | ALIOSCOPY");
                                                                  // VARRIER & ALIOSCOPY 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;
        }
        else if (strcmp(ptr,"ALIOSCOPY")==0)
        {
            _stereoMode = ALIOSCOPY;
        }
    }

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 | ALIOSCOPY 
         | LEFT_EYE | RIGHT_EYE | HORIZONTAL_INTERLACE | VERTICAL_INTERLACE | CHECKERBOARD | ON | OFF ");   // VARRIER & ALIOSCOPY 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
        else if (arguments.match(pos+1,"ALIOSCOPY"))        { arguments.remove(pos,2); _stereo = true;_stereoMode = ALIOSCOPY; }  // ADDED FOR ALIOSCOPY
        .....

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

Added the following includes and defines:

#include <iostream>
#include <sstream>
#include <sys/time.h>
//#define ALIOSCOPY1X4
//#define ALIOSCOPY2X2
//#define ALIOSCOPY3X2
#define ALIOSCOPY3X3

added following declarations:

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

float SceneView::_alioscopyDebug = 1.0;
il_context ** SceneView::_alioscopyContext = NULL;
il_display ** SceneView::_alioscopyDisplay = NULL;
int SceneView::_alioscopyEyes = 8;
float SceneView::_alioscopyIPD = 0.208;
float SceneView::_alioscopyViewDistance = 9.7;
float SceneView::_alioscopyIPDmm = 63.3984;

added the following static function:

static void read_dsp_conf(const char *filename, struct il_display *D, int eyes)
{
    /* Parse the display options from the named config file. */

    FILE *fp;

    if ((fp = fopen(filename, "r")))
    {
        char  s[256];
        char  k[256];
        char *v;
        int   i;
        int   n;
        float f;

        while (fgets(s, 256, fp))
        {
            sscanf(s, "%s%n", k, &n);
            v = s + n;

            if      (!strcmp(k, "pitch")) sscanf(v, "%f", &D->pitch);
            else if (!strcmp(k, "angle")) sscanf(v, "%f", &D->angle);
            else if (!strcmp(k, "thick")) sscanf(v, "%f", &D->thick);
            else if (!strcmp(k, "shift")) sscanf(v, "%f", &D->shift);

            else if (!strcmp(k, "cycle"))
            {
                sscanf(v, "%d %f", &i, &f);
                if (0 <= i && i < eyes) D->cycle[i] = f;
            }
            else if (!strcmp(k, "step0"))
            {
                sscanf(v, "%d %f", &i, &f);
                if (0 <= i && i < eyes) D->step0[i] = f;
            }
            else if (!strcmp(k, "step1"))
            {
                sscanf(v, "%d %f", &i, &f);
                if (0 <= i && i < eyes) D->step1[i] = f;
            }
            else if (!strcmp(k, "step2"))
            {
                sscanf(v, "%d %f", &i, &f);
                if (0 <= i && i < eyes) D->step2[i] = f;
            }
            else if (!strcmp(k, "step3"))
            {
                sscanf(v, "%d %f", &i, &f);
                if (0 <= i && i < eyes) D->step3[i] = f;
            }
            else if (!strcmp(k, "depth"))
            {
                sscanf(v, "%d %f", &i, &f);
                if (0 <= i && i < eyes) D->depth[i] = f;
            }

            else if (!strcmp(k, "screen_BL"))
                sscanf(v, "%f %f %f\n", D->BL+0, D->BL+1, D->BL+2);
            else if (!strcmp(k, "screen_BR"))
                sscanf(v, "%f %f %f\n", D->BR+0, D->BR+1, D->BR+2);
            else if (!strcmp(k, "screen_TL"))
                sscanf(v, "%f %f %f\n", D->TL+0, D->TL+1, D->TL+2);
        }
        fclose(fp);
    }
}


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

    _varrier = NULL;
    _delayCount = 10;

    _cullVisitorAlioscopy = NULL;
    _rendergraphAlioscopy = NULL;
    _renderStageAlioscopy = NULL;

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

    _varrier = rhs._varrier;
    _delayCount = rhs._delayCount;

    _cullVisitorAlioscopy = rhs._cullVisitorAlioscopy;
    _rendergraphAlioscopy = rhs._rendergraphAlioscopy;
    _renderStageAlioscopy = rhs._renderStageAlioscopy;


In void SceneView::cull(), after the following block:

       else if (_displaySettings->getStereoMode()==osg::DisplaySettings::RIGHT_EYE)
        {
            // set up the right eye.
            _cullVisitor->setTraversalMask(_cullMaskRight);
            computeRightEyeViewport(getViewport());
            bool computeNearFar = cullStage(computeRightEyeProjection(getProjectionMatrix()),computeRightEyeView(getViewMatrix()),
                                            _cullVisitor.get(),_stateGraph.get(),_renderStage.get(),_viewportRight.get());

            if (computeNearFar)
            {
                CullVisitor::value_type zNear = _cullVisitor->getCalculatedNearPlane();
                CullVisitor::value_type zFar = _cullVisitor->getCalculatedFarPlane();
                _cullVisitor->clampProjectionMatrix(getProjectionMatrix(),zNear,zFar);
            }

        }

add the following else-if block:

	else if(_displaySettings->getStereoMode()==osg::DisplaySettings::ALIOSCOPY)
        {
            if(_cullVisitorAlioscopy == NULL)
            {
              _cullVisitorAlioscopy = new osg::ref_ptr<osgUtil::CullVisitor>[_alioscopyEyes];
              _rendergraphAlioscopy = new osg::ref_ptr<osgUtil::StateGraph>[_alioscopyEyes];
              _renderStageAlioscopy = new osg::ref_ptr<osgUtil::RenderStage>[_alioscopyEyes];

              for(int i = 0; i < _alioscopyEyes; i++)
              {
                _cullVisitorAlioscopy[i] = dynamic_cast<CullVisitor*>(_cullVisitor->clone());
                _rendergraphAlioscopy[i] = dynamic_cast<StateGraph*>(_stateGraph->cloneType());
                _renderStageAlioscopy[i] = dynamic_cast<RenderStage*>(_renderStage->clone(osg::CopyOp::DEEP_COPY_ALL));
              }
            }
            bool computeNearFar = false;
            for(int i =0; i < _alioscopyEyes; i++)
            {
              _cullVisitorAlioscopy[i]->setDatabaseRequestHandler(_cullVisitor->getDatabaseRequestHandler());
              _cullVisitorAlioscopy[i]->setClampProjectionMatrixCallback(_cullVisitor->getClampProjectionMatrixCallback());
              _cullVisitorAlioscopy[i]->setTraversalMask(_cullMaskLeft);
              computeNearFar = cullStage(computeEyeProjection(i),computeEyeView(i),_cullVisitorAlioscopy[i].get(),_rendergraphAlioscopy[i].get(),_renderStageAlioscopy[i].get(), getViewport());
            }
            if(computeNearFar)
            {
              CullVisitor::value_type zNear = osg::minimum(_cullVisitorAlioscopy[0]->getCalculatedNearPlane(),_cullVisitorAlioscopy[1]->getCalculatedNearPlane());
              CullVisitor::value_type zFar =  osg::maximum(_cullVisitorAlioscopy[0]->getCalculatedFarPlane(),_cullVisitorAlioscopy[1]->getCalculatedFarPlane());
              for(int i = 2; i < _alioscopyEyes; i++)
              {
                zNear = osg::minimum(zNear,_cullVisitorAlioscopy[i]->getCalculatedNearPlane());
                zFar =  osg::maximum(zFar,_cullVisitorAlioscopy[i]->getCalculatedFarPlane());
              }
              _cullVisitor->clampProjectionMatrix(getProjectionMatrix(),zNear,zFar);
            }
            if(!_cullVisitorAlioscopy[0].valid() || !_rendergraphAlioscopy[0].valid() || !_renderStageAlioscopy[0].valid())
            {
               osg::notify(osg::ALWAYS) << "Render Invalid." << std::endl; 
            }
	}


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

           case(osg::DisplaySettings::ALIOSCOPY):
           {
	      static int numberOfDisplays = 9;
              static float alioscopyQuality = 1.0;
	      if (_delayCount >= 0)
              {
                if (_delayCount==0)
                {
                  char * qual = getenv("OSG_ALIOSCOPY_QUALITY");
                  if(qual == NULL)
                  {
                    alioscopyQuality = 1.0;
                  }
                  else
                  {
                    alioscopyQuality = atof(qual);
                    if(alioscopyQuality <= 0.0 || alioscopyQuality > 1.0)
                    {
                      alioscopyQuality = 1.0;
                    }
                  }

                  if(_alioscopyContext == NULL)
                  {
                    int maxContext = _renderInfo.getState()->getGraphicsContext()->getMaxContextID();
                    _alioscopyContext = new il_context*[maxContext+1];
		    _alioscopyDisplay = new il_display*[numberOfDisplays];

                    for(int i = 0; i <= maxContext; i++)
                    {
                      _alioscopyContext[i] = NULL;
                    }
		    for(int i = 0; i < numberOfDisplays; i++)
		    {
		      _alioscopyDisplay[i] = NULL;
                    }
                  }
                }
                --_delayCount;
              }
              else    // call every time once init has been called
              {
                //struct timeval start, end, end1, end2, end3;
                //gettimeofday(&start, NULL);
                
		//static float alioscopyQuality = 1.0;
                int contextid = _renderInfo.getState()->getContextID();
		int vx = int(getViewport()->x());
                int vy = int(getViewport()->y());
                static int vwidth = int(getViewport()->width());
                static int vheight = int(getViewport()->height());
                int display = 0;
                switch(vx)
                {
                  case 1920:
                    display = 1;
                    break;
                  case 3840:
                    display = 2;
                    break;
                  case 5760:
                    display = 3;
                    break;
                  default:
                    display = 0;
                    break;
                }

                char hostname[33];
                gethostname(hostname, 32);
		int node;
                sscanf(hostname, "kaust2d%d-10", &node);

		node--;
		display += 2 * node;

#ifdef ALIOSCOPY3X2
                //osg::notify(osg::ALWAYS) << "Hostname: " << hostname << std::endl;
                sscanf(hostname, "kaust2d%d-10", &node);
                //osg::notify(osg::ALWAYS) << "Node: " << node << std::endl;
                if(node == 1)
                {
                    if(vx == 0 && vy == 1200)
                    {
                       display = 0;
                    }
                    else if(vx == 1920 && vy == 1200)
                    {
                       display = 1;
                    }
                    else if(vx == 0 && vy == 0)
                    {
                       display = 2;
                    }
                    else if(vx == 1920 && vy == 0)
                    {
                       display = 3;
                    }
                }

                if(node == 2)
                {
                    if(vx == 0 && vy == 0)
                    {
                        display = 4;
                    }
                    else if(vx == 1920 && vy == 0)
                    {
                        display = 5;
                    }
                }

                //osg::notify(osg::ALWAYS) << "Display: " << display << std::endl;

#endif

#ifdef ALIOSCOPY3X3
                //osg::notify(osg::ALWAYS) << "Hostname: " << hostname << std::endl;
                sscanf(hostname, "kaust2d%d-10", &node);
                //osg::notify(osg::ALWAYS) << "Node: " << node << std::endl;
                //osg::notify(osg::ALWAYS) << "vx: " << vx << " vy: " << vy << std::endl;
                if(node == 1)
                {
                    if(vx == 0 && vy == 1200)
                    {
                       display = 0;
                    }
                    else if(vx == 1920 && vy == 1200)
                    {
                       display = 3;
                    }
                    else if(vx == 0 && vy == 0)
                    {
                       display = 6;
                    }
                    else if(vx == 1920 && vy == 0)
                    {
                       display = 7;
                    }
                }

                if(node == 2)
                {
                    if(vx == 0 && vy == 1200)
                    {
                       display = 1;
                    }
                    else if(vx == 1920 && vy == 1200)
                    {
                       display = 2;
                    }
                    else if(vx == 0 && vy == 0)
                    {
                       display = 4;
                    }
                    else if(vx == 1920 && vy == 0)
                    {
                       display = 5;
                    }
                }

                if(node == 3)
                {
                    display = 8;
                }

                //osg::notify(osg::ALWAYS) << "Display: " << display << std::endl;

#endif

                
                if (_alioscopyContext[contextid] == NULL)
                {
                  _alioscopyContext[contextid] = il_init_context(_alioscopyEyes, vwidth, vheight, alioscopyQuality,
                                   "/home/demo/covise/alioscopy/interleaver.vert",
                                   "/home/demo/covise/alioscopy/interleaver.frag");
                }

                
                if(_alioscopyDisplay[display] == NULL)
                {
                  osg::notify(osg::ALWAYS) << "quality for display " << display << " set to " << alioscopyQuality << std::endl;
                  _alioscopyDisplay[display] = il_init_display(_alioscopyEyes);

                  //osg::notify(osg::ALWAYS) << "Mark2" << std::endl;

                  std::stringstream file;
                  std::string extra = "";

#ifdef ALIOSCOPY2X2
                  extra = "-2x2";
#endif

#ifdef ALIOSCOPY3X2
                  extra = "-3x2";
#endif

#ifdef ALIOSCOPY3X3
                  extra = "-3x3";
#endif

                  file << "/home/demo/covise/alioscopy/alioscopy" << display << extra  << ".dat";
                  std::string filepath = file.str();

                  osg::notify(osg::ALWAYS) << "Alioscopy display: " << display << " loading file: " << file.str() << std::endl;

                  read_dsp_conf(filepath.c_str(), _alioscopyDisplay[display], _alioscopyEyes);

                  _alioscopyDisplay[display]->viewport_x = vx;
                  _alioscopyDisplay[display]->viewport_y = vy;
                  _alioscopyDisplay[display]->viewport_w = vwidth;
                  _alioscopyDisplay[display]->viewport_h = vheight;
                  _alioscopyDisplay[display]->quality = alioscopyQuality;
                  
		  _alioscopyEyePosition = new float[_alioscopyEyes * 3];

		  il_viewpoints(_alioscopyDisplay[display], _alioscopyIPD, _alioscopyViewDistance, _alioscopyEyePosition, _alioscopyEyes);


                }
                



                if( getDrawBufferValue() !=  GL_NONE)
                {
                  for(int i = 0; i < _alioscopyEyes; i++)
                  {
                    _renderStageAlioscopy[i]->setDrawBuffer(getDrawBufferValue());
                    _renderStageAlioscopy[i]->setReadBuffer(getDrawBufferValue());
                  }
                }
	
                glDrawBuffer(GL_BACK);

                osg::Viewport * vport = getViewport();
                vport->setViewport(vport->x(), vport->y(), vwidth * alioscopyQuality , vheight * alioscopyQuality);
                setViewport(vport);
	
                // 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);
                }
                
                for(int i = 0; i < _alioscopyEyes; i++)
                {
                  _renderStageAlioscopy[i]->setColorMask(cmask);
                }

                _alioscopyDisplay[display]->debug = _alioscopyDebug;

                
		for(int i = 0; i < _alioscopyEyes; i++)
                {
                  il_prep(_alioscopyContext[contextid], _alioscopyDisplay[display], i);
                   

                    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
                    _renderStageAlioscopy[i]->drawPreRenderStages(_renderInfo,previous);
                    _renderStageAlioscopy[i]->draw(getRenderInfo(),previous);
                } 
                

		glDepthMask(GL_FALSE);
                il_draw(_alioscopyContext[contextid], _alioscopyDisplay[display], _alioscopyEyePosition);
                glDepthMask(GL_TRUE);

              }
              break;
          } 
	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 },
		      { -4.8353, 1.5405, -0.7548, 0.2762, -0.0000, -1.3010, -0.0000, 1.0000, -0.0000 },
		      { -4.5227, 1.5454, -2.1410, 0.7438, -0.0000, -1.1026, -0.0000, 1.0000, -0.0000 },
		      { -3.7233, 1.5362, -3.3223, 0.9735, 0.0000, -0.9062, -0.0000, 1.0000, -0.0000 },
		      { -2.6867, 1.5383, -4.2895, 1.2358, 0.0000, -0.4916, -0.0000, 1.0000, -0.0000 },
		      { -1.3612, 1.5348, -4.7881, 1.3169, 0.0000, -0.1859, -0.0000, 1.0000, -0.0000 },
		      { 0.0483, 1.5439, -4.9570, 1.3081, 0.0000, 0.2402, -0.0000, 1.0000, -0.0000 },
		      { 1.4365, 1.5349, -4.6690, 1.2082, 0.0000, 0.5560, -0.0000, 1.0000, -0.0000 },
		      { 2.7175, 1.5320, -4.0578, 1.0408, 0.0000, 0.8280, -0.0000, 1.0000, -0.0000 },
		      { 3.8199, 1.5252, -3.1666, 0.6945, 0.0000, 1.1343, -0.0000, 1.0000, -0.0000 },
		      { 4.5554, 1.5322, -1.9444, 0.2977, 0.0000, 1.2962, -0.0000, 1.0000, -0.0000 },
		      { 4.8400, 1.5271, -0.5580, -0.0394, 0.0000, 1.3294, -0.0000, 1.0000, -0.0000 },

		      { -4.7413, 2.6376, 0.6630, -0.1046, -0.0000, -1.3259, -0.0000, 1.0000, -0.0000 },
		      { -4.8316, 2.6317, -0.7526, 0.2739, -0.0000, -1.3015, -0.0000, 1.0000, -0.0000 },
		      { -4.5208, 2.6346, -2.1384, 0.7318, -0.0000, -1.1105, -0.0000, 1.0000, -0.0000 },
		      { -3.7290, 2.6260, -3.3240, 0.9757, 0.0000, -0.9039, -0.0000, 1.0000, -0.0000 },
		      { -2.6899, 2.6284, -4.2915, 1.2345, 0.0000, -0.4948, -0.0000, 1.0000, -0.0000 },
		      { -1.3608, 2.6242, -4.7861, 1.3166, 0.0000, -0.1885, -0.0000, 1.0000, -0.0000 },
		      { 0.0421, 2.6326, -4.9545, 1.3059, 0.0000, 0.2518, -0.0000, 1.0000, -0.0000 },
		      { 1.4345, 2.6227, -4.6695, 1.2040, 0.0000, 0.5650, -0.0000, 1.0000, -0.0000 },
		      { 2.7151, 2.6196, -4.0544, 1.0474, 0.0000, 0.8197, -0.0000, 1.0000, -0.0000 },
		      { 3.8244, 2.6132, -3.1738, 0.6933, 0.0000, 1.1350, -0.0000, 1.0000, -0.0000 },
		      { 4.5526, 2.6203, -1.9457, 0.3029, 0.0000, 1.2950, -0.0000, 1.0000, -0.0000 },
		      { 4.8494, 2.6155, -0.5613, -0.0428, 0.0000, 1.3293, -0.0000, 1.0000, -0.0000 },

		      { -4.7359, 3.7294, 0.6636, -0.1045, -0.0000, -1.3259, -0.0000, 1.0000, -0.0000 },
		      { -4.8400, 3.7213, -0.7525, 0.2867, -0.0000, -1.2987, -0.0000, 1.0000, -0.0000 },
		      { -4.5153, 3.7251, -2.1358, 0.7265, -0.0000, -1.1140, -0.0000, 1.0000, -0.0000 },
		      { -3.7299, 3.7159, -3.3192, 0.9699, 0.0000, -0.9101, -0.0000, 1.0000, -0.0000 },
		      { -2.6939, 3.7198, -4.2908, 1.2363, 0.0000, -0.4904, -0.0000, 1.0000, -0.0000 },
		      { -1.3646, 3.7143, -4.7893, 1.3165, 0.0000, -0.1889, -0.0000, 1.0000, -0.0000 },
		      { 0.0413, 3.7216, -4.9477, 1.3064, 0.0000, 0.2494, -0.0000, 1.0000, -0.0000 },
		      { 1.4302, 3.7125, -4.6629, 1.2035, 0.0000, 0.5660, -0.0000, 1.0000, -0.0000 },
		      { 2.7136, 3.7108, -4.0478, 1.0489, 0.0000, 0.8177, -0.0000, 1.0000, -0.0000 },
		      { 3.8294, 3.7043, -3.1712, 0.6967, 0.0000, 1.1329, -0.0000, 1.0000, -0.0000 },
		      { 4.5557, 3.7101, -1.9476, 0.3013, 0.0000, 1.2954, -0.0000, 1.0000, -0.0000 },
		      { 4.8522, 3.7051, -0.5633, -0.0390, 0.0000, 1.3294, -0.0000, 1.0000, -0.0000 },

		      { -4.7318, 4.8198, 0.6652, -0.1032, -0.0000, -1.3260, -0.0000, 1.0000, -0.0000 },
		      { -4.8418, 4.8134, -0.7494, 0.2946, -0.0000, -1.2969, -0.0000, 1.0000, -0.0000 },
		      { -4.5157, 4.8145, -2.1335, 0.7232, -0.0000, -1.1162, -0.0000, 1.0000, -0.0000 },
		      { -3.7401, 4.8044, -3.3262, 0.9731, 0.0000, -0.9066, -0.0000, 1.0000, -0.0000 },
		      { -2.6974, 4.8118, -4.2907, 1.2362, 0.0000, -0.4907, -0.0000, 1.0000, -0.0000 },
		      { -1.3641, 4.8049, -4.7855, 1.3162, 0.0000, -0.1910, -0.0000, 1.0000, -0.0000 },
		      { 0.0388, 4.8109, -4.9500, 1.3032, 0.0000, 0.2654, -0.0000, 1.0000, -0.0000 },
		      { 1.4274, 4.8011, -4.6579, 1.2025, 0.0000, 0.5682, -0.0000, 1.0000, -0.0000 },
		      { 2.7140, 4.8004, -4.0516, 1.0465, 0.0000, 0.8208, -0.0000, 1.0000, -0.0000 },
		      { 3.8304, 4.7949, -3.1738, 0.6931, 0.0000, 1.1351, -0.0000, 1.0000, -0.0000 },
		      { 4.5577, 4.8000, -1.9487, 0.2982, 0.0000, 1.2961, -0.0000, 1.0000, -0.0000 },
		      { 4.8563, 4.7941, -0.5626, -0.0422, 0.0000, 1.3293, -0.0000, 1.0000, -0.0000 },

		      { -4.7225, 5.9098, 0.6635, -0.1103, -0.0000, -1.3254, -0.0000, 1.0000, -0.0000 },
		      { -4.8441, 5.9038, -0.7523, 0.3006, -0.0000, -1.2956, -0.0000, 1.0000, -0.0000 },
		      { -4.5118, 5.9038, -2.1335, 0.7080, -0.0000, -1.1259, -0.0000, 1.0000, -0.0000 },
		      { -3.7395, 5.8948, -3.3236, 0.9718, 0.0000, -0.9080, -0.0000, 1.0000, -0.0000 },
		      { -2.6990, 5.9053, -4.2860, 1.2364, 0.0000, -0.4900, -0.0000, 1.0000, -0.0000 },
		      { -1.3701, 5.8958, -4.7857, 1.3168, 0.0000, -0.1869, -0.0000, 1.0000, -0.0000 },
		      { 0.0361, 5.9009, -4.9443, 1.3020, 0.0000, 0.2713, -0.0000, 1.0000, -0.0000 },
		      { 1.4257, 5.8907, -4.6504, 1.2024, 0.0000, 0.5684, -0.0000, 1.0000, -0.0000 },
		      { 2.7117, 5.8916, -4.0457, 1.0466, 0.0000, 0.8206, -0.0000, 1.0000, -0.0000 },
		      { 3.8255, 5.8861, -3.1692, 0.7000, 0.0000, 1.1309, -0.0000, 1.0000, -0.0000 },
		      { 4.5563, 5.8899, -1.9505, 0.2948, 0.0000, 1.2969, -0.0000, 1.0000, -0.0000 },
		      { 4.8578, 5.8829, -0.5649, -0.0340, 0.0000, 1.3296, -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 },
		      { 536.85342, -10.47, 0.0226, -0.00145, 0.75 },
		      { 536.85342, -10.5, 0.023, -0.0011, 0.75 },
		      { 536.85342, -10.465, 0.023, -0.00095, 0.75 },
		      { 536.85342, -10.48, 0.0245, -0.00045, 0.75 },
		      { 536.85342, -10.51, 0.0239, -0.00015, 0.75 },
		      { 536.85342, -10.485, 0.0254, 0.0003, 0.75 },
		      { 536.85342, -10.47, 0.0234, 0.0006, 0.75 },
		      { 536.85342, -10.465, 0.0226, -0.0015, 0.75 },
		      { 536.85342, -10.445, 0.0239, -0.00105, 0.75 },
		      { 536.85342, -10.52, 0.025, 0.0006, 0.75 },
		      { 536.85342, -10.49, 0.0237, -0.0006, 0.75 },
		      { 536.85342, -10.43, 0.025, -0.0004, 0.75 },
		      { 536.85342, -10.445, 0.0227, -1e-04, 0.75 },
		      { 536.85342, -10.45, 0.0236, -0.0002, 0.75 },
		      { 536.85342, -10.48, 0.0228, -0.00045, 0.75 },
		      { 536.85342, -10.44, 0.0245, 0.0004, 0.75 },
		      { 536.85342, -10.44, 0.0235, 0.0001, 0.75 },
		      { 536.85342, -10.43, 0.0252, -0.0011, 0.75 },
		      { 536.85342, -10.42, 0.0234, -0.00095, 0.75 },
		      { 536.85342, -10.47, 0.0236, -0.0016, 0.75 },
		      { 536.85342, -10.44, 0.0244, -0.0001, 0.75 },
		      { 536.85342, -10.46, 0.0233, -0.0009, 0.75 },
		      { 536.85342, -10.46, 0.0243, 0.00045, 0.75 },
		      { 536.85342, -10.405, 0.0239, -0.00125, 0.75 },
		      { 536.85342, -10.46, 0.0221, -0.0008, 0.75 },
		      { 536.85342, -10.48, 0.0235, 0.00025, 0.75 },
		      { 536.85342, -10.475, 0.0229, -1e-04, 0.75 },
		      { 536.85342, -10.44, 0.024, 0.0007, 0.75 },
		      { 536.85342, -10.46, 0.0244, -0.0004, 0.75 },
		      { 536.85342, -10.445, 0.0244, 0.0005, 0.75 },
		      { 536.85342, -10.49, 0.0237, 5e-05, 0.75 },
		      { 536.85342, -10.43, 0.0234, -0.00265, 0.75 },
		      { 536.85342, -10.46, 0.0235, -0.0011, 0.75 },
		      { 536.85342, -10.46, 0.0241, 0.00055, 0.75 },
		      { 536.85342, -10.5, 0.0233, -0.00095, 0.75 },
		      { 536.85342, -10.37, 0.0224, 0.00045, 0.75 },
		      { 536.85342, -10.495, 0.0235, -0.00155, 0.75 },
		      { 536.85342, -10.45, 0.0234, -0.00085, 0.75 },
		      { 536.85342, -10.495, 0.0232, -0.00105, 0.75 },
		      { 536.85342, -10.46, 0.0234, -0.0008, 0.75 },
		      { 536.85342, -10.46, 0.0225, -0.0006, 0.75 },
		      { 536.85342, -10.46, 0.0238, -0.00235, 0.75 },
		      { 536.85342, -10.46, 0.0236, 0.00045, 0.75 },
		      { 536.85342, -10.48, 0.0241, -0.00305, 0.75 },
		      { 536.85342, -10.47, 0.0228, 0.00055, 0.75 },
		      { 536.85342, -10.46, 0.0233, -0.0027, 0.75 },
		      { 536.85342, -10.39, 0.0239, -0.00315, 0.75 },
		      { 536.85342, -10.44, 0.0226, -0.00015, 0.75 },
		      { 536.85342, -10.5, 0.023, -0.001, 0.75 },
		      { 536.85342, -10.43, 0.0232, -0.0005, 0.75 },
		      { 536.85342, -10.52, 0.0242, -0.00105, 0.75 },
		      { 536.85342, -10.54, 0.0226, 0.00035, 0.75 },
		      { 536.85342, -10.46, 0.0231, -0.0005, 0.75 },
		      { 536.85342, -10.48, 0.025, 5e-05, 0.75 },
		      { 536.85342, -10.49, 0.023, -0.0004, 0.75 },
		      { 536.85342, -10.43, 0.0254, -0.004, 0.75 },
		      { 536.85342, -10.46, 0.0232, -0.0016, 0.75 },
		      { 536.85342, -10.48, 0.0229, -0.0003, 0.75 },
		      { 536.83342, -10.48, 0.0233, 0.00065, 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;
                struct timeval start, end;
                gettimeofday(&start, NULL);
                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];
/*
                osg::notify(osg::DEBUG_INFO) << "line_screen: " << line_screen[screen][0] << ", " << 
                  line_screen[screen][1] << ", " << line_screen[screen][2] << ", " << 
                  line_screen[screen][3] << ", " << line_screen[screen][4] << std::endl;
*/

                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);

                gettimeofday(&end, NULL);
                osg::notify(osg::NOTICE) << "Time of SceneView:Draw():Header: " << (end.tv_sec - start.tv_sec) + ((end.tv_usec - start.tv_usec)/ 100000.0) << std::endl;

    // render left eye:
                _varrier[contextid]->prepare(&varrierConfig, VARRIER_RIGHT_EYE);
                gettimeofday(&end, NULL);
                osg::notify(osg::NOTICE) << "Time of SceneView:Draw():Left1: " << (end.tv_sec - start.tv_sec) + ((end.tv_usec - start.tv_usec)/ 100000.0) << std::endl;
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                gettimeofday(&end, NULL);
                osg::notify(osg::NOTICE) << "Time of SceneView:Draw():Left2: " << (end.tv_sec - start.tv_sec) + ((end.tv_usec - start.tv_usec)/ 100000.0) << std::endl;
                 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);
                }

                gettimeofday(&end, NULL);
                osg::notify(osg::NOTICE) << "Time of SceneView:Draw():Left: " << (end.tv_sec - start.tv_sec) + ((end.tv_usec - start.tv_usec)/ 100000.0) << std::endl;

    // 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);
                }

                gettimeofday(&end, NULL);
                osg::notify(osg::NOTICE) << "Time of SceneView:Draw():Right: " << (end.tv_sec - start.tv_sec) + ((end.tv_usec - start.tv_usec)/ 100000.0) << std::endl;

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

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

                glPopAttrib();
                gettimeofday(&end, NULL);
                osg::notify(osg::NOTICE) << "Time of SceneView:Draw(): " << (end.tv_sec - start.tv_sec) + ((end.tv_usec - start.tv_usec)/ 100000.0) 
                                         << " Context: " << contextid << " quad: " << quadrant <<  std::endl;
              }
            } // end varrier style
            break;


In SceneView::getStats(Statistics& stats) change the following block :

        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):
        {
            bool resultLeft = _renderStageLeft->getStats(stats);
            bool resultRight = _renderStageRight->getStats(stats);
            return resultLeft && resultRight;
        }
        case(osg::DisplaySettings::RIGHT_EYE):
        case(osg::DisplaySettings::LEFT_EYE):
        default:
            return _renderStage->getStats(stats);
        }

to the following:

        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):   // FOR VARRIER
        case(osg::DisplaySettings::ALIOSCOPY): // FOR ALIOSCOPY
        {
            bool resultLeft = _renderStageLeft->getStats(stats);
            bool resultRight = _renderStageRight->getStats(stats);
            return resultLeft && resultRight;
        }
        case(osg::DisplaySettings::RIGHT_EYE):
        case(osg::DisplaySettings::LEFT_EYE):
        default:
            return _renderStage->getStats(stats);
        }


Add the following functions at the end of the file:

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

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

void SceneView::toggleAlioscopyDebug()
{
	_alioscopyDebug = (_alioscopyDebug > 1.0) ? 1.0 : 50.0;
}

NOTE: osg needs to link against the varrier and alioscopy libraries (Varrier and coInterleaver), thus it needs to be added to the linking operation.

Linking Varrier and Alioscopy libraries with OpenSceneGraph

Compiling the OpenSceneGraph Package should work now.


OpenCover Files Modified

In covise/src/renderer/OpenCOVER/kernel, the following files are modified:


covise/src/renderer/OpenCOVER/kernel/coVRConfig

In coVRConfig.h, change

typedef struct
{
   float hsize;                                   // horizontal size in mm
   float vsize;                                   // vertical size in mm
   osg::Vec3 xyz;                                 // screen center in mm
   osg::Vec3 hpr;                                 // screen orientation in degree euler angles
   std::string name;
   osg::ref_ptr<osg::Camera> camera;
   osg::ref_ptr<osgUtil::SceneView> sceneView;
   osg::DisplaySettings *ds;
   int window;
   float viewportXMin;
   float viewportYMin;
   float viewportXMax;
   float viewportYMax;
   int stereoMode;
   osg::Matrixd leftView, rightView;
   osg::Matrixd leftProj, rightProj;
   bool render;
} screenStruct;

to this:

typedef struct
{
   float hsize;                                   // horizontal size in mm
   float vsize;                                   // vertical size in mm
   osg::Vec3 xyz;                                 // screen center in mm
   osg::Vec3 hpr;                                 // screen orientation in degree euler angles
   std::string name;
   osg::ref_ptr<osg::Camera> camera;
   osg::ref_ptr<osgUtil::SceneView> sceneView;
   osg::DisplaySettings *ds;
   int window;
   float viewportXMin;
   float viewportYMin;
   float viewportXMax;
   float viewportYMax;
   int stereoMode;
   osg::Matrixd leftView, rightView;
   osg::Matrixd leftProj, rightProj;
// IVL
   osg::Matrixd alioView[8];
   osg::Matrixd alioProj[8];
   bool render;
} screenStruct;


In coVRConfig.cpp, in function coVRConfig::parseStereoMode(const char *modeName), make the following changes to the if-block:

   if(modeName)
   {
      if(strcasecmp(modeName,"ANAGLYPHIC")==0)
         stereoMode = osg::DisplaySettings::ANAGLYPHIC;
      else if(strcasecmp(modeName,"QUAD_BUFFER")==0)
         stereoMode = osg::DisplaySettings::QUAD_BUFFER;
      else if(strcasecmp(modeName,"HORIZONTAL_SPLIT")==0)
         stereoMode = osg::DisplaySettings::HORIZONTAL_SPLIT;
      else if(strcasecmp(modeName,"VERTICAL_SPLIT")==0)
         stereoMode = osg::DisplaySettings::VERTICAL_SPLIT;
      else if(strcasecmp(modeName,"RIGHT_EYE")==0)
         stereoMode = osg::DisplaySettings::RIGHT_EYE;
      else if(strcasecmp(modeName,"RIGHT")==0)
         stereoMode = osg::DisplaySettings::RIGHT_EYE;
      else if(strcasecmp(modeName,"LEFT")==0)
         stereoMode = osg::DisplaySettings::LEFT_EYE;
      else if(strcasecmp(modeName,"LEFT_EYE")==0)
         stereoMode = osg::DisplaySettings::LEFT_EYE;
      else if(strcasecmp(modeName,"STIPPLE")==0)
         stereoMode = osg::DisplaySettings::VERTICAL_INTERLACE;
      else if(strcasecmp(modeName,"VERTICAL_INTERLACE")==0)
         stereoMode = osg::DisplaySettings::VERTICAL_INTERLACE;
      else if(strcasecmp(modeName,"HORIZONTAL_INTERLACE")==0)
         stereoMode = osg::DisplaySettings::HORIZONTAL_INTERLACE;
      
      else if(strcasecmp(modeName,"VARRIER")==0)
         stereoMode = osg::DisplaySettings::VARRIER;      //FOR VARRIER
      else if(strcasecmp(modeName,"ALIOSCOPY")==0)
         stereoMode = osg::DisplaySettings::ALIOSCOPY;    // FOR ALIOSCOPY
      else if(strcasecmp(modeName,"NONE")==0)
         stereoMode = osg::DisplaySettings::ANAGLYPHIC;
      else if(modeName[0]=='\0')
         stereoMode = osg::DisplaySettings::ANAGLYPHIC;
      else
         cerr << "Unknown stereo mode \"" << modeName << "\"" << endl;
   }


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

Make the following changes in drawImplementation(osg::RenderInfo &renderInfo):



void ARToolKitNode::drawImplementation(osg::RenderInfo &renderInfo) const
{
   static bool firstTime = true;
   static GLuint texHandle=0;
   if(firstTime)
      {
         glGenTextures(1, &texHandle);
         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texHandle);
         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
         firstTime = false;
      }
   bool rightVideo = false;
   if(osg::View *view = renderInfo.getView())
   {
      if(osg::State *state = renderInfo.getState())
      {
         if(const osg::DisplaySettings *ds = state->getDisplaySettings())
         {
            switch(ds->getStereoMode())
            {
               case osg::DisplaySettings::HORIZONTAL_INTERLACE:
               case osg::DisplaySettings::VERTICAL_INTERLACE:
               case osg::DisplaySettings::ANAGLYPHIC:
               case osg::DisplaySettings::VARRIER:         //FOR VARRIER
               case osg::DisplaySettings::ALIOSCOPY:       //FOR ALIOSCOPY
                  /* TODO */
                  break;
               case osg::DisplaySettings::HORIZONTAL_SPLIT:
               case osg::DisplaySettings::VERTICAL_SPLIT:

               ....


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

Make the following changes in setFrustumAndView(int i):

void
VRViewer::setFrustumAndView(int i)
{
   if (cover->debugLevel(5))
      fprintf(stderr,"VRViewer::setFrustum %d\n", i);

   osg::Vec3 xyz;                                 // center position of the screen
   osg::Vec3 hpr;                                 // orientation of the screen
   osg::Matrix mat, trans, euler;                 // xform screencenter - world origin
   osg::Matrixf offsetMat;
   osg::Vec3 leftEye, rightEye, middleEye;        // transformed eye position

   ///////////////////////////////////////////////////////////////////////////
// IVL
   float ac_dist, ac_left, ac_right, ac_bottom, ac_top;   //FOR ALIOSCOPY
   //////////////////////////////////////////////////////////////////////////

   float rc_dist, lc_dist, mc_dist;               // dist from eye to screen for left&right chan
   float rc_left, rc_right, rc_bottom, rc_top;    // parameter of right frustum
   float lc_left, lc_right, lc_bottom, lc_top;    // parameter of left frustum
   float mc_left, mc_right, mc_bottom, mc_top;    // parameter of middle frustum
   float n_over_d;                                // near over dist -> Strahlensatz
   float dx, dz;                                  // size of screen

   //, bothEyesDirOffset; == hpr
   osg::Vec3  rightEyePosOffset(0.0,0.0,0.0), leftEyePosOffset(0.0,0.0,0.0);

   osg::Matrixf offsetMatRight;
   osg::Matrixf offsetMatLeft;

   dx = coVRConfig::instance()->screens[i].hsize;
   dz = coVRConfig::instance()->screens[i].vsize;

   hpr=coVRConfig::instance()->screens[i].hpr;
   xyz=coVRConfig::instance()->screens[i].xyz;

   // first set pos and yaxis
   // next set separation and dir from covise.config
   // which I think workks only if 0 0 0 (dr)
   rightViewPos.set(separation / 2.0f, 0.0f, 0.0f);
   leftViewPos.set(-(separation / 2.0f), 0.0f, 0.0f);
   middleViewPos.set(0.0, 0.0, 0.0);


   //////////////////////////////////////////////////////////////////////////
   // IVL
   osg::Vec3 alioEye[8];
   osg::Vec3 alioPos[8];
   float alioSep = 63.3984;
   float offset = -((alioSep / 2.0f) + (3.0f * alioSep));
   for(int k = 0; k < 8; k++)
   {
      alioPos[k].set(offset, 0.0f, 0.0f);
      offset += alioSep;
   }
   //////////////////////////////////////////////////////////////////////////

   ////// IWR : get values of moving screen; change only if moved by >1%
   if(screen_angle && screen_angle[0].screen == i)
   {
      float new_angle;

      new_angle = ((*screen_angle[0].value - screen_angle[0].cmin) /
            (screen_angle[0].cmax - screen_angle[0].cmin)) *
         (screen_angle[0].maxangle - screen_angle[0].minangle) +
         screen_angle[0].minangle;

      // change angle only, when change is significant (> 1%)
      float change_delta = fabs(screen_angle[0].maxangle - screen_angle[0].minangle) * 0.01;

      if(fabs(coVRConfig::instance()->screens[i].hpr[screen_angle[0].hpr] - new_angle) > change_delta)
      {
         coVRConfig::instance()->screens[i].hpr[screen_angle[0].hpr] = new_angle;
         //		   cerr << "Cereal gives " << *screen_angle[0].value << endl;
         cerr << "Setting Screen angle " << screen_angle[0].hpr << " to " << new_angle << endl;
      }
   }

   if (coVRConfig::instance()->trackedHMD)                         // two frustums asymetric because of stereo
   {
      rightEye.set(separation / 2.0, 0.0, coVRConfig::instance()->HMDDistance);
      leftEye.set(-(separation / 2.0), 0.0, coVRConfig::instance()->HMDDistance);
      middleEye.set(0.0, 0.0, coVRConfig::instance()->HMDDistance);
      // first set pos and yaxis
      // next set separation and real viewing dir
      coVRConfig::instance()->screens[i].camera->setViewMatrix(viewMat);
      fprintf(stderr,"viewPos=[%f %f %f] viewDir=[%f %f %f]\n", viewPos[0], viewPos[1], viewPos[2], viewDir[0], viewDir[1], viewDir[2]);

      // for stereo use the pfChanViewOffset to position it correctly
      // and to set the viewing direction (normal of the screen)

      rightEyePosOffset=rightViewPos - viewPos;
      leftEyePosOffset=leftViewPos - viewPos;
      if (cover->debugLevel(5))
      {
         fprintf(stderr,"leftEyePosOffset=[%f %f %f]\n", leftEyePosOffset[0], leftEyePosOffset[1], leftEyePosOffset[2]);
         fprintf(stderr,"rightEyePosOffset=[%f %f %f]\n", rightEyePosOffset[0], rightEyePosOffset[1], rightEyePosOffset[2]);
      }

   }

   else if(coVRConfig::instance()->HMDMode)                        // das berechnet dasselbe frustum wie trackedHMD
      // wenn screen center und dir 000 sind
   {

      // dr: das funktioniert, wenn xyz und hpr Null ist
      //     kann man daher auch weglassen

      // transform the screen to fit the xz-plane

      trans.makeTranslate(xyz[0], xyz[1], xyz[2]);
      trans.invert(trans);

      MAKE_EULER_MAT(euler,hpr[0], hpr[1], hpr[2]);
      euler.invert(euler);

      mat.mult(trans, euler);

      euler.makeRotate(-coVRConfig::instance()->worldAngle(),osg::X_AXIS);
      //euler.invertN(euler);
      mat.mult(euler, mat);

      rightEye.set(separation / 2.0f, 0.0f, 0.0f);
      leftEye.set(-(separation / 2.0f), 0.0f, 0.0f);
      middleEye.set(0.0, 0.0, 0.0);
      rightEye += initialViewPos;
      leftEye += initialViewPos;
      middleEye += initialViewPos;

      // transform the left and right eye with this matrix
      rightEye = viewMat.preMult(rightEye);
      leftEye = viewMat.preMult(leftEye);
      middleEye = viewMat.preMult(middleEye);

      rightViewPos += initialViewPos;
      leftViewPos += initialViewPos;

      // add world angle
      osg::Matrixf rotAll,newDir;
      rotAll.makeRotate(-coVRConfig::instance()->worldAngle(),osg::X_AXIS);
      newDir.mult(viewMat,rotAll);

      // first set it if both channels were at the position of a mono channel
      // coVRConfig::instance()->screens[i].camera->setOffset(newDir.ptr(),0,0);

      viewPos = newDir.getTrans();

      // for stereo use the pfChanViewOffset to position it correctly
      // and to set the viewing direction (normal of the screen)

      rightEyePosOffset=rightViewPos - viewPos;
      leftEyePosOffset=leftViewPos - viewPos;
   }

   else                                           // fixed screens, viewing frustums asymetric through tracking and stereo
   {

      // transform the screen to fit the xz-plane
      trans.makeTranslate(-xyz[0], -xyz[1], -xyz[2]);

      //euler.makeRotate(hpr[0],osg::Y_AXIS, hpr[1],osg::X_AXIS, hpr[2],osg::Z_AXIS);
      MAKE_EULER_MAT_VEC(euler,hpr);
      euler.invert(euler);

      mat.mult(trans, euler);

      euler.makeRotate(-coVRConfig::instance()->worldAngle(),osg::X_AXIS);
      //euler.invertN(euler);
      mat.mult(euler, mat);
      //cerr << "test" << endl;

      // transform the left and right eye with this matrix
      rightEye = viewMat.preMult(rightViewPos);
      leftEye = viewMat.preMult(leftViewPos);
      middleEye = viewMat.preMult(middleViewPos);

      rightEye = mat.preMult(rightEye);
      leftEye = mat.preMult(leftEye);
      middleEye = mat.preMult(middleEye);

   //////////////////////////////////////////////////////////////////////////
   // IVL
      for(int k = 0; k < 8; k++)
      {
         alioEye[k] = viewMat.preMult(alioPos[k]);
         alioEye[k] =  mat.preMult(alioEye[k]);
      }
   //////////////////////////////////////////////////////////////////////////
   }

   offsetMat = mat;

   // compute right frustum

   // dist of right channel eye to screen (absolute)
   rc_dist = -rightEye[1];
   lc_dist = -leftEye[1];
   mc_dist = -middleEye[1];

   // relation near plane to screen plane
   n_over_d = coVRConfig::instance()->nearClip()/rc_dist;

   // parameter of right channel
   rc_right  = n_over_d * (dx/2.0 - rightEye[0]);
   rc_left   = -n_over_d * (dx/2.0 + rightEye[0]);
   rc_top    = n_over_d* (dz/2.0 - rightEye[2]);
   rc_bottom = -n_over_d* (dz/2.0 + rightEye[2]);

   // compute left frustum
   n_over_d = coVRConfig::instance()->nearClip()/lc_dist;
   lc_right  = n_over_d * (dx/2.0 - leftEye[0]);
   lc_left   = -n_over_d * (dx/2.0 + leftEye[0]);
   lc_top    = n_over_d* (dz/2.0 - leftEye[2]);
   lc_bottom = -n_over_d* (dz/2.0 + leftEye[2]);

   // compute left frustum
   n_over_d = coVRConfig::instance()->nearClip()/mc_dist;
   mc_right  = n_over_d * (dx/2.0 - middleEye[0]);
   mc_left   = -n_over_d * (dx/2.0 + middleEye[0]);
   mc_top    = n_over_d* (dz/2.0 - middleEye[2]);
   mc_bottom = -n_over_d* (dz/2.0 + middleEye[2]);

   coVRConfig::instance()->screens[i].rightProj.makeFrustum(rc_left, rc_right, rc_bottom, rc_top, coVRConfig::instance()->nearClip(), coVRConfig::instance()->farClip());
   coVRConfig::instance()->screens[i].leftProj.makeFrustum(lc_left, lc_right, lc_bottom, lc_top,coVRConfig::instance()->nearClip(), coVRConfig::instance()->farClip());
   coVRConfig::instance()->screens[i].camera->setProjectionMatrixAsFrustum(mc_left, mc_right, mc_bottom, mc_top,coVRConfig::instance()->nearClip(), coVRConfig::instance()->farClip());

   coVRConfig::instance()->screens[i].rightView.makeLookAt(osg::Vec3(rightEye[0],rightEye[1],rightEye[2]),
         osg::Vec3(rightEye[0],rightEye[1]+1,rightEye[2]),
         osg::Vec3(0,0,1));
   coVRConfig::instance()->screens[i].rightView.preMult(offsetMat);

   coVRConfig::instance()->screens[i].leftView.makeLookAt(osg::Vec3(leftEye[0],leftEye[1],leftEye[2]),
         osg::Vec3(leftEye[0],leftEye[1]+1,leftEye[2]),
         osg::Vec3(0,0,1));
   coVRConfig::instance()->screens[i].leftView.preMult(offsetMat);

   coVRConfig::instance()->screens[i].camera->setViewMatrix(offsetMat*osg::Matrix::lookAt(osg::Vec3(middleEye[0],middleEye[1],middleEye[2]),
            osg::Vec3(middleEye[0],middleEye[1]+1,middleEye[2]),
            osg::Vec3(0,0,1)));

   //////////////////////////////////////////////////////////////////////////
   // IVL
   for(int k = 0; k < 8; k++)
   {
      ac_dist = -alioEye[k][1];
      n_over_d = coVRConfig::instance()->nearClip()/ac_dist;

      ac_right  = n_over_d * (dx/2.0 - alioEye[k][0]);
      ac_left   = -n_over_d * (dx/2.0 + alioEye[k][0]);
      ac_top    = n_over_d* (dz/2.0 - alioEye[k][2]);
      ac_bottom = -n_over_d* (dz/2.0 + alioEye[k][2]);

      coVRConfig::instance()->screens[i].alioProj[k].makeFrustum(ac_left, ac_right, ac_bottom, ac_top, coVRConfig::instance()->nearClip(), coVRConfig::instance()->farClip());
      coVRConfig::instance()->screens[i].alioView[k].makeLookAt(osg::Vec3(alioEye[k][0],alioEye[k][1],alioEye[k][2]),
         osg::Vec3(alioEye[k][0],alioEye[k][1]+1,alioEye[k][2]),
         osg::Vec3(0,0,1));
      coVRConfig::instance()->screens[i].alioView[k].preMult(offsetMat);
   }
   //////////////////////////////////////////////////////////////////////////
}