Modifications for Varrier and Alioscopy
Changes made for the implementation of varrier and alioscopy under covise on kaustalio:
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/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