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.
This commit is contained in:
Robert Osfield 2003-10-01 15:56:52 +00:00
parent facbdcf43b
commit 4700b8902c
4 changed files with 307 additions and 192 deletions

View File

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

View File

@ -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<osg::StateSet> _globalStateSet;
osg::ref_ptr<osg::StateSet> _localStateSet;
osg::ref_ptr<osg::Light> _light;
osg::ref_ptr<osg::RefMatrix> _projectionMatrix;
osg::ref_ptr<osg::RefMatrix> _viewMatrix;
osg::Matrixd _projectionMatrix;
osg::Matrixd _viewMatrix;
osg::ref_ptr<osg::DisplaySettings> _displaySettings;
osg::ref_ptr<osg::State> _state;
@ -393,6 +442,8 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced
osg::ref_ptr<osgUtil::RenderGraph> _rendergraph;
osg::ref_ptr<osgUtil::RenderStage> _renderStage;
osg::ref_ptr<ComputeStereoMatricesCallback> _computeStereoMatricesCallback;
osg::Node::NodeMask _cullMaskLeft;
osg::ref_ptr<osgUtil::CullVisitor> _cullVisitorLeft;
osg::ref_ptr<osgUtil::RenderGraph> _rendergraphLeft;

View File

@ -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 <mode>","QUAD_BUFFER | ANAGLYPHIC | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE");
static ApplicationUsageProxy DisplaySetting_e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO <mode>","OFF | ON");
static ApplicationUsageProxy DisplaySetting_e2(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EYE_SEPARATION <float>","physical distance between eyes");
static ApplicationUsageProxy DisplaySetting_e3(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_DISTANCE <float>","physical distance between eyes and screen");
static ApplicationUsageProxy DisplaySetting_e4(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_HEIGHT <float>","physical screen height");
static ApplicationUsageProxy DisplaySetting_e5(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING <mode>","LEFT_EYE_LEFT_VIEWPORT | LEFT_EYE_RIGHT_VIEWPORT");
static ApplicationUsageProxy DisplaySetting_e8(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION <float>","number of pixels between viewports");
static ApplicationUsageProxy DisplaySetting_e9(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING <mode>","LEFT_EYE_TOP_VIEWPORT | LEFT_EYE_BOTTOM_VIEWPORT");
static ApplicationUsageProxy DisplaySetting_e10(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_AUTO_ADJUST_ASPECT_RATIO <mode>","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 <float>","number of pixels between viewports");
static ApplicationUsageProxy DisplaySetting_e12(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS <int>","maximum number of graphics contexts to be used with applications.");
static ApplicationUsageProxy DisplaySetting_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_DISPLAY_TYPE <type>","MONITOR | POWERWALL | REALITY_CENTER | HEAD_MOUNTED_DISPLAY");
static ApplicationUsageProxy DisplaySetting_e1(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO_MODE <mode>","QUAD_BUFFER | ANAGLYPHIC | HORIZONTAL_SPLIT | VERTICAL_SPLIT | LEFT_EYE | RIGHT_EYE");
static ApplicationUsageProxy DisplaySetting_e2(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_STEREO <mode>","OFF | ON");
static ApplicationUsageProxy DisplaySetting_e3(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_EYE_SEPARATION <float>","physical distance between eyes");
static ApplicationUsageProxy DisplaySetting_e4(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_DISTANCE <float>","physical distance between eyes and screen");
static ApplicationUsageProxy DisplaySetting_e5(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN_HEIGHT <float>","physical screen height");
static ApplicationUsageProxy DisplaySetting_e6(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_EYE_MAPPING <mode>","LEFT_EYE_LEFT_VIEWPORT | LEFT_EYE_RIGHT_VIEWPORT");
static ApplicationUsageProxy DisplaySetting_e7(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_HORIZONTAL_SEPARATION <float>","number of pixels between viewports");
static ApplicationUsageProxy DisplaySetting_e8(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_VERTICAL_EYE_MAPPING <mode>","LEFT_EYE_TOP_VIEWPORT | LEFT_EYE_BOTTOM_VIEWPORT");
static ApplicationUsageProxy DisplaySetting_e9(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SPLIT_STEREO_AUTO_ADJUST_ASPECT_RATIO <mode>","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 <float>","number of pixels between viewports");
static ApplicationUsageProxy DisplaySetting_e11(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_MAX_NUMBER_OF_GRAPHICS_CONTEXTS <int>","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 <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 | 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)

View File

@ -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<osg::RefMatrix> projection = _projectionMatrix.get();
osg::ref_ptr<osg::RefMatrix> 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<osg::RefMatrix> 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<osg::RefMatrix> 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<osg::RefMatrix> 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<osg::RefMatrix> 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*>(_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<osg::RefMatrix> 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<osg::RefMatrix> 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<osg::RefMatrix> 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<osg::RefMatrix> 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<RefMatrix> proj = new osg::RefMatrix(projection);
osg::ref_ptr<RefMatrix> 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.*/"<<std::endl;
break;
case(SKY_LIGHT):
if (_light.valid()) renderStage->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.*/"<<std::endl;
break;
case(NO_SCENEVIEW_LIGHT):
@ -485,8 +532,8 @@ void SceneView::cullStage(osg::RefMatrix* projection,osg::RefMatrix* modelview,o
cullVisitor->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"<<timer.delta_m(tstart,tend)<<std::endl;
if (_viewMatrix.valid()) _state->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);
}