From 4700b8902c327f5d0a1526ab2614d5cadace176d Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 1 Oct 2003 15:56:52 +0000 Subject: [PATCH] Introduced new DisplaySettings::set/getDisplayType() and environemtal variables to and command line arguments to set it. Added support for using the DisplaySettings::getDisplayType() to detect use of a Head Mounted Display when doing stereo so that the asymtric frustum can be switched off. --- include/osg/DisplaySettings | 14 ++ include/osgUtil/SceneView | 75 ++++++-- src/osg/DisplaySettings.cpp | 59 ++++-- src/osgUtil/SceneView.cpp | 351 +++++++++++++++++++----------------- 4 files changed, 307 insertions(+), 192 deletions(-) diff --git a/include/osg/DisplaySettings b/include/osg/DisplaySettings index 0801ad817..348a486a2 100644 --- a/include/osg/DisplaySettings +++ b/include/osg/DisplaySettings @@ -64,6 +64,19 @@ class SG_EXPORT DisplaySettings : public osg::Referenced /** read the commandline arguments.*/ void readCommandLine(ArgumentParser& arguments); + + enum DisplayType + { + MONITOR, + POWERWALL, + REALITY_CENTER, + HEAD_MOUNTED_DISPLAY + }; + + void setDisplayType(DisplayType type) { _displayType = type; } + + DisplayType getDisplayType() const { return _displayType; } + void setStereo(bool on) { _stereo = on; } bool getStereo() const { return _stereo; } @@ -151,6 +164,7 @@ class SG_EXPORT DisplaySettings : public osg::Referenced void copy(const DisplaySettings& vs); + DisplayType _displayType; bool _stereo; StereoMode _stereoMode; float _eyeSeparation; diff --git a/include/osgUtil/SceneView b/include/osgUtil/SceneView index f930b6925..a10c11755 100644 --- a/include/osgUtil/SceneView +++ b/include/osgUtil/SceneView @@ -130,7 +130,10 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced /** Set the projection matrix. Can be thought of as setting the lens of a camera. */ - void setProjectionMatrix(const osg::Matrix& matrix); + inline void setProjectionMatrix(const osg::Matrixf& matrix) { _projectionMatrix.set(matrix); } + + /** Set the projection matrix. Can be thought of as setting the lens of a camera. */ + inline void setProjectionMatrix(const osg::Matrixd& matrix) { _projectionMatrix.set(matrix); } /** Set to a orthographic projection. See OpenGL glOrtho for documentation further details.*/ void setProjectionMatrixAsOrtho(double left, double right, @@ -152,10 +155,10 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced double zNear, double zFar); /** Get the projection matrix.*/ - osg::Matrix& getProjectionMatrix() { return *_projectionMatrix; } + osg::Matrixd& getProjectionMatrix() { return _projectionMatrix; } /** Get the const projection matrix.*/ - const osg::Matrix& getProjectionMatrix() const { return *_projectionMatrix; } + const osg::Matrixd& getProjectionMatrix() const { return _projectionMatrix; } /** Get the othorgraphic settings of the orthographic projection matrix. * Returns false if matrix is not an orthographic matrix, where parameter values are undefined.*/ @@ -179,17 +182,20 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced /** Set the view matrix. Can be thought of as setting the position of the world relative to the camera in camera coordinates. */ - void setViewMatrix(const osg::Matrix& matrix); + inline void setViewMatrix(const osg::Matrixf& matrix) { _viewMatrix.set(matrix); } + + /** Set the view matrix. Can be thought of as setting the position of the world relative to the camera in camera coordinates. */ + inline void setViewMatrix(const osg::Matrixd& matrix) { _viewMatrix.set(matrix); } /** Set to the position and orientation of view matrix, using the same convention as gluLookAt. */ void setViewMatrixAsLookAt(const osg::Vec3& eye,const osg::Vec3& center,const osg::Vec3& up); /** Get the view matrix. */ - osg::Matrix& getViewMatrix() { return *_viewMatrix; } + osg::Matrixd& getViewMatrix() { return _viewMatrix; } /** Get the const view matrix. */ - const osg::Matrix& getViewMatrix() const { return *_viewMatrix; } + const osg::Matrixd& getViewMatrix() const { return _viewMatrix; } /** Get to the position and orientation of a modelview matrix, using the same convention as gluLookAt. */ void getViewMatrixAsLookAt(osg::Vec3& eye,osg::Vec3& center,osg::Vec3& up,float lookDistance=1.0f); @@ -344,6 +350,52 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced inline const osg::FrameStamp* getFrameStamp() const { return _frameStamp.get(); } + + /** callback for overidding the default method for compute the offset projection and view matrices.*/ + struct ComputeStereoMatricesCallback : public osg::Referenced + { + virtual osg::Matrixd computeLeftEyeProjection(const osg::Matrixd& projection) const = 0; + virtual osg::Matrixd computeLeftEyeView(const osg::Matrixd& view) const = 0; + + virtual osg::Matrixd computeRightEyeProjection(const osg::Matrixd& projection) const = 0; + virtual osg::Matrixd computeRightEyeView(const osg::Matrixd& view) const = 0; + }; + + void setComputeStereoMatricesCallback(ComputeStereoMatricesCallback* callback) { _computeStereoMatricesCallback=callback; } + ComputeStereoMatricesCallback* getComputeStereoMatricesCallback(ComputeStereoMatricesCallback* callback) { return _computeStereoMatricesCallback.get(); } + const ComputeStereoMatricesCallback* getComputeStereoMatricesCallback() const { return _computeStereoMatricesCallback.get(); } + + inline osg::Matrixd computeLeftEyeProjection(const osg::Matrixd& projection) const + { + if (_computeStereoMatricesCallback.valid()) return _computeStereoMatricesCallback->computeLeftEyeProjection(projection); + else return computeLeftEyeProjectionImplementation(projection); + } + + inline osg::Matrixd computeLeftEyeView(const osg::Matrixd& view) const + { + if (_computeStereoMatricesCallback.valid()) return _computeStereoMatricesCallback->computeLeftEyeView(view); + else return computeLeftEyeViewImplementation(view); + } + + inline osg::Matrixd computeRightEyeProjection(const osg::Matrixd& projection) const + { + if (_computeStereoMatricesCallback.valid()) return _computeStereoMatricesCallback->computeRightEyeProjection(projection); + else return computeRightEyeProjectionImplementation(projection); + } + + inline osg::Matrixd computeRightEyeView(const osg::Matrixd& view) const + { + if (_computeStereoMatricesCallback.valid()) return _computeStereoMatricesCallback->computeRightEyeView(view); + else return computeRightEyeViewImplementation(view); + } + + virtual osg::Matrixd computeLeftEyeProjectionImplementation(const osg::Matrixd& projection) const; + virtual osg::Matrixd computeLeftEyeViewImplementation(const osg::Matrixd& view) const; + + virtual osg::Matrixd computeRightEyeProjectionImplementation(const osg::Matrixd& projection) const; + virtual osg::Matrixd computeRightEyeViewImplementation(const osg::Matrixd& view) const; + + /** Do init traversal of attached scene graph using Init NodeVisitor. * The init traversal is called once for each SceneView, and should * be used to compile display list, texture objects intialize data @@ -355,9 +407,6 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced /** Do app traversal of attached scene graph using App NodeVisitor.*/ virtual void update(); -#ifdef USE_DEPREACTED_API - virtual void app() { update(); } -#endif /** Do cull traversal of attached scene graph using Cull NodeVisitor.*/ virtual void cull(); @@ -370,7 +419,7 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced virtual ~SceneView(); /** Do cull traversal of attached scene graph using Cull NodeVisitor.*/ - virtual void cullStage(osg::RefMatrix* projection,osg::RefMatrix* modelview,osgUtil::CullVisitor* cullVisitor, osgUtil::RenderGraph* rendergraph, osgUtil::RenderStage* renderStage); + virtual void cullStage(const osg::Matrixd& projection,const osg::Matrixd& modelview,osgUtil::CullVisitor* cullVisitor, osgUtil::RenderGraph* rendergraph, osgUtil::RenderStage* renderStage); const osg::Matrix computeMVPW() const; @@ -380,8 +429,8 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced osg::ref_ptr _globalStateSet; osg::ref_ptr _localStateSet; osg::ref_ptr _light; - osg::ref_ptr _projectionMatrix; - osg::ref_ptr _viewMatrix; + osg::Matrixd _projectionMatrix; + osg::Matrixd _viewMatrix; osg::ref_ptr _displaySettings; osg::ref_ptr _state; @@ -393,6 +442,8 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced osg::ref_ptr _rendergraph; osg::ref_ptr _renderStage; + osg::ref_ptr _computeStereoMatricesCallback; + osg::Node::NodeMask _cullMaskLeft; osg::ref_ptr _cullVisitorLeft; osg::ref_ptr _rendergraphLeft; diff --git a/src/osg/DisplaySettings.cpp b/src/osg/DisplaySettings.cpp index c23408e8b..4c993c1c0 100644 --- a/src/osg/DisplaySettings.cpp +++ b/src/osg/DisplaySettings.cpp @@ -45,6 +45,7 @@ DisplaySettings::~DisplaySettings() void DisplaySettings::copy(const DisplaySettings& vs) { + _displayType = vs._displayType; _stereoMode = vs._stereoMode; _eyeSeparation = vs._eyeSeparation; _screenDistance = vs._screenDistance; @@ -83,6 +84,8 @@ void DisplaySettings::merge(const DisplaySettings& vs) void DisplaySettings::setDefaults() { + _displayType = MONITOR; + _stereo = false; _stereoMode = ANAGLYPHIC; _eyeSeparation = 0.05f; @@ -106,21 +109,46 @@ void DisplaySettings::setDefaults() _maxNumOfGraphicsContexts = 3; } -static ApplicationUsageProxy DisplaySetting_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO_MODE ","QUAD_BUFFER | ANAGLYPHIC | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE"); -static ApplicationUsageProxy DisplaySetting_e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO ","OFF | ON"); -static ApplicationUsageProxy DisplaySetting_e2(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EYE_SEPARATION ","physical distance between eyes"); -static ApplicationUsageProxy DisplaySetting_e3(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_DISTANCE ","physical distance between eyes and screen"); -static ApplicationUsageProxy DisplaySetting_e4(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_HEIGHT ","physical screen height"); -static ApplicationUsageProxy DisplaySetting_e5(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING ","LEFT_EYE_LEFT_VIEWPORT | LEFT_EYE_RIGHT_VIEWPORT"); -static ApplicationUsageProxy DisplaySetting_e8(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION ","number of pixels between viewports"); -static ApplicationUsageProxy DisplaySetting_e9(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING ","LEFT_EYE_TOP_VIEWPORT | LEFT_EYE_BOTTOM_VIEWPORT"); -static ApplicationUsageProxy DisplaySetting_e10(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_AUTO_ADJUST_ASPECT_RATIO ","OFF | ON Default to ON to compenstate for the compression of the aspect ratio when viewing in split screen stereo. Note, if you are setting fovx and fovy explicityly OFF should be used."); -static ApplicationUsageProxy DisplaySetting_e11(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_SEPARATION ","number of pixels between viewports"); -static ApplicationUsageProxy DisplaySetting_e12(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS ","maximum number of graphics contexts to be used with applications."); +static ApplicationUsageProxy DisplaySetting_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DISPLAY_TYPE ","MONITOR | POWERWALL | REALITY_CENTER | HEAD_MOUNTED_DISPLAY"); +static ApplicationUsageProxy DisplaySetting_e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO_MODE ","QUAD_BUFFER | ANAGLYPHIC | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE"); +static ApplicationUsageProxy DisplaySetting_e2(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO ","OFF | ON"); +static ApplicationUsageProxy DisplaySetting_e3(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EYE_SEPARATION ","physical distance between eyes"); +static ApplicationUsageProxy DisplaySetting_e4(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_DISTANCE ","physical distance between eyes and screen"); +static ApplicationUsageProxy DisplaySetting_e5(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_HEIGHT ","physical screen height"); +static ApplicationUsageProxy DisplaySetting_e6(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING ","LEFT_EYE_LEFT_VIEWPORT | LEFT_EYE_RIGHT_VIEWPORT"); +static ApplicationUsageProxy DisplaySetting_e7(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION ","number of pixels between viewports"); +static ApplicationUsageProxy DisplaySetting_e8(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING ","LEFT_EYE_TOP_VIEWPORT | LEFT_EYE_BOTTOM_VIEWPORT"); +static ApplicationUsageProxy DisplaySetting_e9(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_AUTO_ADJUST_ASPECT_RATIO ","OFF | ON Default to ON to compenstate for the compression of the aspect ratio when viewing in split screen stereo. Note, if you are setting fovx and fovy explicityly OFF should be used."); +static ApplicationUsageProxy DisplaySetting_e10(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_SEPARATION ","number of pixels between viewports"); +static ApplicationUsageProxy DisplaySetting_e11(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS ","maximum number of graphics contexts to be used with applications."); void DisplaySettings::readEnvironmentalVariables() { char *ptr; + + if ((ptr = getenv("OSG_DISPLAY_TYPE")) != 0) + { + if (strcmp(ptr,"MONITOR")==0) + { + _displayType = MONITOR; + } + else + if (strcmp(ptr,"POWERWALL")==0) + { + _displayType = POWERWALL; + } + else + if (strcmp(ptr,"REALITY_CENTER")==0) + { + _displayType = REALITY_CENTER; + } + else + if (strcmp(ptr,"HEAD_MOUNTED_DISPLAY")==0) + { + _displayType = HEAD_MOUNTED_DISPLAY; + } + } + if( (ptr = getenv("OSG_STEREO_MODE")) != 0) { if (strcmp(ptr,"QUAD_BUFFER")==0) @@ -244,12 +272,21 @@ void DisplaySettings::readCommandLine(ArgumentParser& arguments) // report the usage options. if (arguments.getApplicationUsage()) { + arguments.getApplicationUsage()->addCommandLineOption("--display ","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 ","ANAGLYPHIC | QUAD_BUFFER | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE | ON | OFF "); arguments.getApplicationUsage()->addCommandLineOption("--rgba","Request a RGBA color buffer visual"); arguments.getApplicationUsage()->addCommandLineOption("--stencil","Request a stencil buffer visual"); } + std::string str; + while(arguments.read("--display",str)) + { + if (str=="MONITOR") _displayType = MONITOR; + else if (str=="POWERWALL") _displayType = POWERWALL; + else if (str=="REALITY_CENTER") _displayType = REALITY_CENTER; + else if (str=="HEAD_MOUNTED_DISPLAY") _displayType = HEAD_MOUNTED_DISPLAY; + } int pos; while ((pos=arguments.find("--stereo"))!=0) diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index d3cc9bda2..25e041aba 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -67,15 +67,8 @@ SceneView::~SceneView() void SceneView::setDefaults() { - if (!_projectionMatrix) - { - _projectionMatrix = new RefMatrix(); - _projectionMatrix->makePerspective(50.0f,1.4f,1.0f,10000.0f); - } - if (!_viewMatrix) - { - _viewMatrix = new RefMatrix(); - } + _projectionMatrix.makePerspective(50.0f,1.4f,1.0f,10000.0f); + _viewMatrix.makeIdentity(); _globalStateSet = new osg::StateSet; @@ -193,6 +186,158 @@ void SceneView::update() } +osg::Matrixd SceneView::computeLeftEyeProjectionImplementation(const osg::Matrixd& projection) const +{ + double fusionDistance = _displaySettings->getScreenDistance(); + switch(_fusionDistanceMode) + { + case(USE_FUSION_DISTANCE_VALUE): + fusionDistance = _fusionDistanceValue; + break; + case(PROPORTIONAL_TO_SCREEN_DISTANCE): + fusionDistance *= _fusionDistanceValue; + break; + } + + double iod = _displaySettings->getEyeSeparation(); + double sd = _displaySettings->getScreenDistance(); + double scale_x = 1.0; + double scale_y = 1.0; + + if (_displaySettings->getSplitStereoAutoAjustAspectRatio()) + { + switch(_displaySettings->getStereoMode()) + { + case(osg::DisplaySettings::HORIZONTAL_SPLIT): + scale_x = 2.0; + break; + case(osg::DisplaySettings::VERTICAL_SPLIT): + scale_y = 2.0; + break; + default: + break; + } + } + + if (_displaySettings->getDisplayType()==osg::DisplaySettings::HEAD_MOUNTED_DISPLAY) + { + // head mounted display has the same projection matrix for left and right eyes. + return osg::Matrixd::scale(scale_x,scale_y,1.0) * + projection; + } + else + { + // all other display types assume working like a projected power wall + // need to shjear projection matrix to account for asymetric frustum due to eye offset. + return osg::Matrixd(1.0,0.0,0.0,0.0, + 0.0,1.0,0.0,0.0, + iod/(2.0*sd),0.0,1.0,0.0, + 0.0,0.0,0.0,1.0) * + osg::Matrixd::scale(scale_x,scale_y,1.0) * + projection; + } +} + +osg::Matrixd SceneView::computeLeftEyeViewImplementation(const osg::Matrixd& view) const +{ + double fusionDistance = _displaySettings->getScreenDistance(); + switch(_fusionDistanceMode) + { + case(USE_FUSION_DISTANCE_VALUE): + fusionDistance = _fusionDistanceValue; + break; + case(PROPORTIONAL_TO_SCREEN_DISTANCE): + fusionDistance *= _fusionDistanceValue; + break; + } + + double iod = _displaySettings->getEyeSeparation(); + double sd = _displaySettings->getScreenDistance(); + double es = 0.5f*iod*(fusionDistance/sd); + + return view * + osg::Matrixd(1.0,0.0,0.0,0.0, + 0.0,1.0,0.0,0.0, + 0.0,0.0,1.0,0.0, + es,0.0,0.0,1.0); +} + +osg::Matrixd SceneView::computeRightEyeProjectionImplementation(const osg::Matrixd& projection) const +{ + double fusionDistance = _displaySettings->getScreenDistance(); + switch(_fusionDistanceMode) + { + case(USE_FUSION_DISTANCE_VALUE): + fusionDistance = _fusionDistanceValue; + break; + case(PROPORTIONAL_TO_SCREEN_DISTANCE): + fusionDistance *= _fusionDistanceValue; + break; + } + + double iod = _displaySettings->getEyeSeparation(); + double sd = _displaySettings->getScreenDistance(); + double scale_x = 1.0; + double scale_y = 1.0; + + if (_displaySettings->getSplitStereoAutoAjustAspectRatio()) + { + switch(_displaySettings->getStereoMode()) + { + case(osg::DisplaySettings::HORIZONTAL_SPLIT): + scale_x = 2.0; + break; + case(osg::DisplaySettings::VERTICAL_SPLIT): + scale_y = 2.0; + break; + default: + break; + } + } + + if (_displaySettings->getDisplayType()==osg::DisplaySettings::HEAD_MOUNTED_DISPLAY) + { + // head mounted display has the same projection matrix for left and right eyes. + return osg::Matrixd::scale(scale_x,scale_y,1.0) * + projection; + } + else + { + // all other display types assume working like a projected power wall + // need to shjear projection matrix to account for asymetric frustum due to eye offset. + return osg::Matrixd(1.0,0.0,0.0,0.0, + 0.0,1.0,0.0,0.0, + -iod/(2.0*sd),0.0,1.0,0.0, + 0.0,0.0,0.0,1.0) * + osg::Matrixd::scale(scale_x,scale_y,1.0) * + projection; + } +} + +osg::Matrixd SceneView::computeRightEyeViewImplementation(const osg::Matrixd& view) const +{ + float fusionDistance = _displaySettings->getScreenDistance(); + switch(_fusionDistanceMode) + { + case(USE_FUSION_DISTANCE_VALUE): + fusionDistance = _fusionDistanceValue; + break; + case(PROPORTIONAL_TO_SCREEN_DISTANCE): + fusionDistance *= _fusionDistanceValue; + break; + } + + double iod = _displaySettings->getEyeSeparation(); + double sd = _displaySettings->getScreenDistance(); + double es = 0.5*iod*(fusionDistance/sd); + + return view * + osg::Matrixd(1.0,0.0,0.0,0.0, + 0.0,1.0,0.0,0.0, + 0.0,0.0,1.0,0.0, + -es,0.0,0.0,1.0); +} + void SceneView::cull() { @@ -217,12 +362,6 @@ void SceneView::cull() _state->setDisplaySettings(_displaySettings.get()); - osg::ref_ptr projection = _projectionMatrix.get(); - osg::ref_ptr modelview = _viewMatrix.get(); - - if (!projection) projection = new osg::RefMatrix(); - if (!modelview) modelview = new osg::RefMatrix(); - if (!_cullVisitor) { osg::notify(osg::INFO) << "Warning: no valid osgUtil::SceneView:: attached, creating a default CullVisitor automatically."<< std::endl; @@ -242,60 +381,18 @@ void SceneView::cull() if (_displaySettings.valid() && _displaySettings->getStereo()) { - float fusionDistance = _displaySettings->getScreenDistance(); - switch(_fusionDistanceMode) - { - case(USE_FUSION_DISTANCE_VALUE): - fusionDistance = _fusionDistanceValue; - break; - case(PROPORTIONAL_TO_SCREEN_DISTANCE): - fusionDistance *= _fusionDistanceValue; - break; - } - - float iod = _displaySettings->getEyeSeparation(); - float sd = _displaySettings->getScreenDistance(); - float es = 0.5f*iod*(fusionDistance/sd); - if (_displaySettings->getStereoMode()==osg::DisplaySettings::LEFT_EYE) { // set up the left eye. - osg::ref_ptr projectionLeft = new osg::RefMatrix(osg::Matrix(1.0f,0.0f,0.0f,0.0f, - 0.0f,1.0f,0.0f,0.0f, - iod/(2.0f*sd),0.0f,1.0f,0.0f, - 0.0f,0.0f,0.0f,1.0f)* - (*projection)); - - - osg::ref_ptr modelviewLeft = new osg::RefMatrix( (*modelview) * - osg::Matrix(1.0f,0.0f,0.0f,0.0f, - 0.0f,1.0f,0.0f,0.0f, - 0.0f,0.0f,1.0f,0.0f, - es,0.0f,0.0f,1.0f)); - _cullVisitor->setTraversalMask(_cullMaskLeft); - cullStage(projectionLeft.get(),modelviewLeft.get(),_cullVisitor.get(),_rendergraph.get(),_renderStage.get()); + cullStage(computeLeftEyeProjection(_projectionMatrix),computeLeftEyeView(_viewMatrix),_cullVisitor.get(),_rendergraph.get(),_renderStage.get()); } else if (_displaySettings->getStereoMode()==osg::DisplaySettings::RIGHT_EYE) { // set up the right eye. - osg::ref_ptr projectionRight = new osg::RefMatrix(osg::Matrix(1.0f,0.0f,0.0f,0.0f, - 0.0f,1.0f,0.0f,0.0f, - -iod/(2.0f*sd),0.0f,1.0f,0.0f, - 0.0f,0.0f,0.0f,1.0f)* - (*projection)); - - osg::ref_ptr modelviewRight = new osg::RefMatrix( (*modelview) * - osg::Matrix(1.0f,0.0f,0.0f,0.0f, - 0.0f,1.0f,0.0f,0.0f, - 0.0f,0.0f,1.0f,0.0f, - -es,0.0f,0.0f,1.0f)); - _cullVisitor->setTraversalMask(_cullMaskRight); - cullStage(projectionRight.get(),modelviewRight.get(),_cullVisitor.get(),_rendergraph.get(),_renderStage.get()); - - + cullStage(computeRightEyeProjection(_projectionMatrix),computeRightEyeView(_viewMatrix),_cullVisitor.get(),_rendergraph.get(),_renderStage.get()); } else { @@ -309,65 +406,13 @@ void SceneView::cull() if (!_renderStageRight.valid()) _renderStageRight = dynamic_cast(_renderStage->clone(osg::CopyOp::DEEP_COPY_ALL)); - - - osg::Matrix projection_scale; - - - if (_displaySettings->getSplitStereoAutoAjustAspectRatio()) - { - - switch(_displaySettings->getStereoMode()) - { - case(osg::DisplaySettings::HORIZONTAL_SPLIT): - projection_scale.makeScale(2.0f,1.0f,1.0f); - break; - case(osg::DisplaySettings::VERTICAL_SPLIT): - projection_scale.makeScale(1.0f,2.0f,1.0f); - break; - default: - break; - } - } - - // set up the left eye. - osg::ref_ptr projectionLeft = new osg::RefMatrix(osg::Matrix(1.0f,0.0f,0.0f,0.0f, - 0.0f,1.0f,0.0f,0.0f, - iod/(2.0f*sd),0.0f,1.0f,0.0f, - 0.0f,0.0f,0.0f,1.0f)* - projection_scale* - (*projection)); - - - - osg::ref_ptr modelviewLeft = new osg::RefMatrix( (*modelview) * - osg::Matrix(1.0f,0.0f,0.0f,0.0f, - 0.0f,1.0f,0.0f,0.0f, - 0.0f,0.0f,1.0f,0.0f, - es,0.0f,0.0f,1.0f)); - _cullVisitorLeft->setTraversalMask(_cullMaskLeft); - cullStage(projectionLeft.get(),modelviewLeft.get(),_cullVisitorLeft.get(),_rendergraphLeft.get(),_renderStageLeft.get()); + cullStage(computeLeftEyeProjection(_projectionMatrix),computeLeftEyeView(_viewMatrix),_cullVisitorLeft.get(),_rendergraphLeft.get(),_renderStageLeft.get()); // set up the right eye. - osg::ref_ptr projectionRight = new osg::RefMatrix(osg::Matrix(1.0f,0.0f,0.0f,0.0f, - 0.0f,1.0f,0.0f,0.0f, - -iod/(2.0f*sd),0.0f,1.0f,0.0f, - 0.0f,0.0f,0.0f,1.0f)* - projection_scale* - (*projection)); - - osg::ref_ptr modelviewRight = new osg::RefMatrix( (*modelview) * - osg::Matrix(1.0f,0.0f,0.0f,0.0f, - 0.0f,1.0f,0.0f,0.0f, - 0.0f,0.0f,1.0f,0.0f, - -es,0.0f,0.0f,1.0f)); - - - _cullVisitorRight->setTraversalMask(_cullMaskRight); - cullStage(projectionRight.get(),modelviewRight.get(),_cullVisitorRight.get(),_rendergraphRight.get(),_renderStageRight.get()); + cullStage(computeRightEyeProjection(_projectionMatrix),computeRightEyeView(_viewMatrix),_cullVisitorRight.get(),_rendergraphRight.get(),_renderStageRight.get()); } @@ -376,14 +421,14 @@ void SceneView::cull() { _cullVisitor->setTraversalMask(_cullMask); - cullStage(projection.get(),modelview.get(),_cullVisitor.get(),_rendergraph.get(),_renderStage.get()); + cullStage(_projectionMatrix,_viewMatrix,_cullVisitor.get(),_rendergraph.get(),_renderStage.get()); } } -void SceneView::cullStage(osg::RefMatrix* projection,osg::RefMatrix* modelview,osgUtil::CullVisitor* cullVisitor, osgUtil::RenderGraph* rendergraph, osgUtil::RenderStage* renderStage) +void SceneView::cullStage(const osg::Matrixd& projection,const osg::Matrixd& modelview,osgUtil::CullVisitor* cullVisitor, osgUtil::RenderGraph* rendergraph, osgUtil::RenderStage* renderStage) { if (!_sceneData || !_viewport->valid()) return; @@ -391,6 +436,8 @@ void SceneView::cullStage(osg::RefMatrix* projection,osg::RefMatrix* modelview,o if (!_initCalled) init(); + osg::ref_ptr proj = new osg::RefMatrix(projection); + osg::ref_ptr mv = new osg::RefMatrix(modelview); // collect any occluder in the view frustum. if (_sceneData->containsOccluderNodes()) @@ -408,8 +455,8 @@ void SceneView::cullStage(osg::RefMatrix* projection,osg::RefMatrix* modelview,o } cov.pushViewport(_viewport.get()); - cov.pushProjectionMatrix(projection); - cov.pushModelViewMatrix(modelview); + cov.pushProjectionMatrix(proj.get()); + cov.pushModelViewMatrix(mv.get()); // traverse the scene graph to search for occluder in there new positions. _sceneData->accept(cov); @@ -473,7 +520,7 @@ void SceneView::cullStage(osg::RefMatrix* projection,osg::RefMatrix* modelview,o else osg::notify(osg::WARN)<<"Warning: no osg::Light attached to ogUtil::SceneView to provide head light.*/"<addPositionedAttribute(modelview,_light.get()); + if (_light.valid()) renderStage->addPositionedAttribute(mv.get(),_light.get()); else osg::notify(osg::WARN)<<"Warning: no osg::Light attached to ogUtil::SceneView to provide sky light.*/"<pushViewport(_viewport.get()); - cullVisitor->pushProjectionMatrix(projection); - cullVisitor->pushModelViewMatrix(modelview); + cullVisitor->pushProjectionMatrix(proj.get()); + cullVisitor->pushModelViewMatrix(mv.get()); // traverse the scene graph to generate the rendergraph. @@ -553,7 +600,7 @@ void SceneView::draw() //osg::Timer_t tend = timer.tick(); //std::cout<<"time to flush rendering objects"<setInitialViewMatrix(_viewMatrix.get()); + _state->setInitialViewMatrix(new osg::RefMatrix(_viewMatrix)); RenderLeaf* previous = NULL; if (_displaySettings.valid() && _displaySettings->getStereo()) @@ -862,13 +909,7 @@ bool SceneView::projectObjectIntoWindow(const osg::Vec3& object,osg::Vec3& windo const osg::Matrix SceneView::computeMVPW() const { - osg::Matrix matrix; - - if (_viewMatrix.valid()) - matrix = (*_viewMatrix); - - if (_projectionMatrix.valid()) - matrix.postMult(*_projectionMatrix); + osg::Matrix matrix( _viewMatrix * _projectionMatrix); if (_viewport.valid()) matrix.postMult(_viewport->computeWindowMatrix()); @@ -893,18 +934,11 @@ void SceneView::clearArea(int x,int y,int width,int height,const osg::Vec4& colo glDisable( GL_SCISSOR_TEST ); } -void SceneView::setProjectionMatrix(const osg::Matrix& matrix) -{ - if (!_projectionMatrix) _projectionMatrix = new osg::RefMatrix(matrix); - else _projectionMatrix->set(matrix); -} - - void SceneView::setProjectionMatrixAsOrtho(double left, double right, double bottom, double top, double zNear, double zFar) { - setProjectionMatrix(osg::Matrix::ortho(left, right, + setProjectionMatrix(osg::Matrixd::ortho(left, right, bottom, top, zNear, zFar)); } @@ -912,7 +946,7 @@ void SceneView::setProjectionMatrixAsOrtho(double left, double right, void SceneView::setProjectionMatrixAsOrtho2D(double left, double right, double bottom, double top) { - setProjectionMatrix(osg::Matrix::ortho2D(left, right, + setProjectionMatrix(osg::Matrixd::ortho2D(left, right, bottom, top)); } @@ -920,7 +954,7 @@ void SceneView::setProjectionMatrixAsFrustum(double left, double right, double bottom, double top, double zNear, double zFar) { - setProjectionMatrix(osg::Matrix::frustum(left, right, + setProjectionMatrix(osg::Matrixd::frustum(left, right, bottom, top, zNear, zFar)); } @@ -928,7 +962,7 @@ void SceneView::setProjectionMatrixAsFrustum(double left, double right, void SceneView::setProjectionMatrixAsPerspective(double fovy,double aspectRatio, double zNear, double zFar) { - setProjectionMatrix(osg::Matrix::perspective(fovy,aspectRatio, + setProjectionMatrix(osg::Matrixd::perspective(fovy,aspectRatio, zNear, zFar)); } @@ -936,53 +970,32 @@ bool SceneView::getProjectionMatrixAsOrtho(double& left, double& right, double& bottom, double& top, double& zNear, double& zFar) { - if (_projectionMatrix.valid()) - { - return _projectionMatrix->getOrtho(left, right, - bottom, top, - zNear, zFar); - } - return false; + return _projectionMatrix.getOrtho(left, right, + bottom, top, + zNear, zFar); } bool SceneView::getProjectionMatrixAsFrustum(double& left, double& right, double& bottom, double& top, double& zNear, double& zFar) { - if (_projectionMatrix.valid()) - { - return _projectionMatrix->getFrustum(left, right, - bottom, top, - zNear, zFar); - } - return false; + return _projectionMatrix.getFrustum(left, right, + bottom, top, + zNear, zFar); } bool SceneView::getProjectionMatrixAsPerspective(double& fovy,double& aspectRatio, double& zNear, double& zFar) { - if (_projectionMatrix.valid()) - { - return _projectionMatrix->getPerspective(fovy, aspectRatio, zNear, zFar); - } - return false; + return _projectionMatrix.getPerspective(fovy, aspectRatio, zNear, zFar); } -void SceneView::setViewMatrix(const osg::Matrix& matrix) -{ - if (!_viewMatrix) _viewMatrix = new osg::RefMatrix(matrix); - else _viewMatrix->set(matrix); -} - void SceneView::setViewMatrixAsLookAt(const Vec3& eye,const Vec3& center,const Vec3& up) { - setViewMatrix(osg::Matrix::lookAt(eye,center,up)); + setViewMatrix(osg::Matrixd::lookAt(eye,center,up)); } void SceneView::getViewMatrixAsLookAt(Vec3& eye,Vec3& center,Vec3& up,float lookDistance) { - if (_viewMatrix.valid()) - { - _viewMatrix->getLookAt(eye,center,up,lookDistance); - } + _viewMatrix.getLookAt(eye,center,up,lookDistance); }