Difference between revisions of "Modifications for Varrier and Alioscopy"
(→ccovise/src/renderer/OpenCOVER/kernel/coVRConfig) |
|||
(One intermediate revision by one user not shown) | |||
Line 1,168: | Line 1,168: | ||
} | } | ||
+ | </PRE> | ||
+ | |||
+ | |||
+ | ===covise/src/renderer/OpenCOVER/kernel/ARToolkit.cpp=== | ||
+ | |||
+ | Make the following changes in drawImplementation(osg::RenderInfo &renderInfo): | ||
+ | |||
+ | <PRE> | ||
+ | |||
+ | |||
+ | 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: | ||
+ | |||
+ | .... | ||
+ | </PRE> | ||
+ | |||
+ | |||
+ | |||
+ | ===covise/src/renderer/OpenCOVER/kernel/VRViewer.cpp=== | ||
+ | |||
+ | Make the following changes in setFrustumAndView(int i): | ||
+ | |||
+ | <PRE> | ||
+ | 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); | ||
+ | } | ||
+ | ////////////////////////////////////////////////////////////////////////// | ||
+ | } | ||
</PRE> | </PRE> |
Latest revision as of 15:21, 16 April 2009
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
- Step-1: Get the Varrier library (File:VarrierCombiner.tar), and the alioscopy library (File:CoInterleaver.tar), and compile them.
- Step-2: Add the corresponding CMake modules under the CMakeModules directory of OpenSceneGraph
- Step-3 : Replace OpenSceneGraph/CMakeLists.txt with file: File:CMakeLists.txt
- Step-4: Replace OpenSceneGraph/src/osgViewer/CMkakeLists.txt file with: File:OsgViewer-CMakeLists.txt
- Step-5: Define environment variables $VARRIER_LIBRARY and $INTERLEAVER_LIBRARY to point to where the corresponding libraries are.
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); } ////////////////////////////////////////////////////////////////////////// }