diff --git a/include/osg/Camera b/include/osg/Camera index dea1dd2a2..a32fc5356 100644 --- a/include/osg/Camera +++ b/include/osg/Camera @@ -25,6 +25,8 @@ class SG_EXPORT Camera: public osg::Referenced public: Camera(); + Camera(const Camera&); + Camera& operator=(const Camera&); virtual ~Camera(); /** Range of projection types. @@ -254,11 +256,15 @@ class SG_EXPORT Camera: public osg::Referenced const bool unproject(const Vec3& win,const Viewport& viewport,Vec3& obj) const; + /** Convinience method for adjusting the project and model view to account for + * and eye offset, as used in stereo work, assumes that the users will use + * a seperate camera for each eye, adjustEyePointForStereo(..) being used to + * specialize the camera for each eye view.*/ + void adjustEyeOffsetForStereo(const osg::Vec3& offset,float screenDistance); + protected: - - // Disallow copy construction & assignment (for now) - Camera(const Camera&); - Camera& operator=(const Camera&); + + void copy(const Camera&); // projection details. ProjectionType _projectionType; @@ -306,7 +312,10 @@ class SG_EXPORT Camera: public osg::Referenced void calculateMatricesAndClippingVolume() const; - + // values to offset + bool _useEyeOffset; + osg::Vec3 _eyeOffset; + float _screenDistance; }; diff --git a/include/osgUtil/RenderStage b/include/osgUtil/RenderStage index a5f148b5a..8cbe10ada 100644 --- a/include/osgUtil/RenderStage +++ b/include/osgUtil/RenderStage @@ -6,6 +6,7 @@ #define OSGUTIL_RENDERSTAGE 1 #include +#include #include #include @@ -53,6 +54,11 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin const GLbitfield getClearMask() const { return _clearMask; } + void setColorMask(osg::ColorMask* cm) { _colorMask = cm; } + osg::ColorMask* getColorMask() { return _colorMask.get(); } + const osg::ColorMask* getColorMask() const { return _colorMask.get(); } + + /** Set the clear color used in glClearColor(..). * glClearColor is only called if mask & GL_COLOR_BUFFER_BIT is true*/ void setClearColor(const osg::Vec4& color) { _clearColor=color; } @@ -131,6 +137,7 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin osg::ref_ptr _viewport; GLbitfield _clearMask; + osg::ref_ptr _colorMask; osg::Vec4 _clearColor; osg::Vec4 _clearAccum; double _clearDepth; diff --git a/include/osgUtil/SceneView b/include/osgUtil/SceneView index 7c1fd57ee..4fdaabb50 100644 --- a/include/osgUtil/SceneView +++ b/include/osgUtil/SceneView @@ -101,14 +101,32 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced osg::Light* getLight() { return _light.get(); } const osg::Light* getLight() const { return _light.get(); } - void setCamera(osg::Camera* camera) { _camera = camera; } - osg::Camera* getCamera() { return _camera.get(); } - const osg::Camera* getCamera() const { return _camera.get(); } - void setState(osg::State* state) { _state = state; } osg::State* getState() { return _state.get(); } const osg::State* getState() const { return _state.get(); } + + enum StereoMode + { + MONO, + QUAD_BUFFER_STEREO, + RED_GREEN_STEREO, + HORIZONTAL_SPLIT_STEREO, + VERTICAL_SPLIT_STEREO + }; + void setStereoMode(const StereoMode mode) { _stereoMode = mode; } + const StereoMode getStereoMode() const { return _stereoMode; } + + void setLeftEyeOffset(const osg::Vec3& pos) { _leftEye = pos; } + void setRightEyeOffset(const osg::Vec3& pos) { _rightEye = pos; } + + void setFocalLength(float length) { _focalLength = length; } + void setScreenDistance(float distance) { _screenDistance = distance; } + + void setCamera(osg::Camera* camera) { _camera = camera; } + osg::Camera* getCamera() { return _camera.get(); } + const osg::Camera* getCamera() const { return _camera.get(); } + void setInitVisitor(osg::NodeVisitor* av) { _initVisitor = av; } osg::NodeVisitor* getInitVisitor() { return _initVisitor.get(); } @@ -212,6 +230,14 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced osg::ref_ptr _light; osg::ref_ptr _camera; osg::ref_ptr _state; + + StereoMode _stereoMode; + + osg::Vec3 _leftEye; + osg::Vec3 _rightEye; + + float _focalLength; + float _screenDistance; bool _initCalled; osg::ref_ptr _initVisitor; diff --git a/src/osg/Camera.cpp b/src/osg/Camera.cpp index b00039f9c..63e30f367 100644 --- a/src/osg/Camera.cpp +++ b/src/osg/Camera.cpp @@ -14,7 +14,7 @@ Camera::Camera() _adjustAspectRatioMode = ADJUST_HORIZONTAL; // projection details. - setPerspective(60,1.0,1.0,1000.0); + setPerspective(30,1.0,1.0,1000.0); // look at details. _lookAtType =USE_HOME_POSITON; @@ -28,8 +28,70 @@ Camera::Camera() _useNearClippingPlane = false; _useFarClippingPlane = false; + _useEyeOffset = false; + _eyeOffset.set(0.0f,0.0f,0.0f); + _screenDistance = 1.0f; } +Camera::Camera(const Camera& camera) +{ + copy(camera); +} + +Camera& Camera::operator=(const Camera& camera) +{ + if (&camera==this) return *this; + + copy(camera); + + return *this; +} + +void Camera::copy(const Camera& camera) +{ + _projectionType = camera._projectionType; + + // how the window dimensions should be altered during a window resize. + _adjustAspectRatioMode = camera._adjustAspectRatioMode; + + // note, in Frustum/Perspective mode these values are scaled + // by the zNear from when they were initialised to ensure that + // subsequent changes in zNear do not affect them. + _left = camera._left; + _right = camera._right; + _bottom = camera._bottom; + _top = camera._top; + + _zNear = camera._zNear; + _zFar = camera._zFar; + + + // look at details. + _lookAtType = camera._lookAtType; + + _eye = camera._eye; + _center = camera._center; + _up = camera._up; + + _focalLength = camera._focalLength; + + _attachedTransformMode = camera._attachedTransformMode; + _eyeToModelTransform = camera._eyeToModelTransform; + _modelToEyeTransform = camera._modelToEyeTransform; + + // flags to determine if near and far clipping planes are required. + _useNearClippingPlane = camera._useNearClippingPlane; + _useFarClippingPlane = camera._useFarClippingPlane; + + // cached matrix and clipping volume derived from above settings. + _dirty = camera._dirty; + _projectionMatrix = camera._projectionMatrix; + _modelViewMatrix = camera._modelViewMatrix; + _clippingVolume = camera._clippingVolume; + + _mp = camera._mp; + _inversemp = camera._inversemp; +} Camera::~Camera() { @@ -324,6 +386,10 @@ void Camera::transformLookAt(const Matrix& matrix) _center = _center*matrix; _up -= _eye; _up.normalize(); + + _focalLength = (_center-_eye).length(); + + _dirty = true; } const Vec3 Camera::getLookVector() const @@ -520,17 +586,31 @@ const ClippingVolume& Camera::getClippingVolume() const void Camera::calculateMatricesAndClippingVolume() const { + + float left = _left; + float right = _right; + float top = _top; + float bottom = _bottom; + + if (_useEyeOffset) + { + float dx = -_eyeOffset.x()*(1.0f/_screenDistance); + left += dx; + right += dx; + cout << "dx="<getStereoMode()==osgUtil::SceneView::QUAD_BUFFER_STEREO) needQuadBufferStereo = true; + } //glutInit( &argc, argv ); // I moved this into main to avoid passing @@ -238,6 +244,7 @@ bool Viewer::open() if (vrv.requiresDepthBuffer()) displayMode |= GLUT_DEPTH; if (vrv.requiresAlphaBuffer()) displayMode |= GLUT_ALPHA; if (vrv.requiresStencilBuffer()) displayMode |= GLUT_STENCIL; + if (needQuadBufferStereo) displayMode |= GLUT_STEREO; // and we'll add in multisample so that on systems like Onyx's can // go ahead and use there loverly anti-aliasing. This is ignored @@ -245,14 +252,15 @@ bool Viewer::open() displayMode |= GLUT_MULTISAMPLE; - osg::notify(osg::INFO) <<"osgGLUT::Viewer::open() requesting displayMode = "< TextList; + typedef std::vector TextList; TextList formatedText; createFormatedText(_maxCharsPerLine,_text,formatedText); diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index 01e1bc440..6ceaf7cf0 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -73,6 +73,10 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous) // glEnable( GL_DEPTH_TEST ); + // set which color planes to operate on. + if (_colorMask.valid()) _colorMask->apply(state); + else glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + if (_clearMask & GL_COLOR_BUFFER_BIT) glClearColor( _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]); @@ -85,8 +89,6 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous) if (_clearMask & GL_ACCUM_BUFFER_BIT) glClearAccum( _clearAccum[0], _clearAccum[1], _clearAccum[2], _clearAccum[3]); - // clear a color bit planes - osg::ColorMask could also be used here. - glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); glClear( _clearMask ); diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index 8298bbb49..57eeb7006 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -45,14 +45,23 @@ void SceneView::setDefaults() _lightingMode=HEADLIGHT; _light = new osg::Light; - _light->setAmbient(Vec4(0.05f,0.05f,0.05f,1.0f)); + _light->setAmbient(Vec4(0.00f,0.0f,0.00f,1.0f)); _light->setDiffuse(Vec4(0.8f,0.8f,0.8f,1.0f)); - _light->setSpecular(Vec4(0.1f,0.1f,0.1f,1.0f)); + _light->setSpecular(Vec4(1.0f,1.0f,1.0f,1.0f)); - _camera = new Camera; - _state = new State; + _camera = new Camera; + + _stereoMode = MONO; + + _leftEye.set(-0.03f,0.0f,0.0f); + _rightEye.set(0.03f,0.0f,0.0f); + + _focalLength = 1.0f; + _screenDistance = 1.0f; + + _rendergraph = new RenderGraph; _renderStage = new RenderStage; @@ -281,7 +290,60 @@ void SceneView::draw() osg::Texture::flushDeletedTextureObjects(_state->getContextID()); RenderLeaf* previous = NULL; - _renderStage->draw(*_state,previous); + + switch(getStereoMode()) + { + case(MONO): + { + _renderStage->draw(*_state,previous); + } + break; + case(QUAD_BUFFER_STEREO): + { + osg::ref_ptr left_camera = new osg::Camera(*_camera); + osg::ref_ptr right_camera = new osg::Camera(*_camera); + float screenDistance = 3.5f; + float iod = 0.05; + + left_camera->adjustEyeOffsetForStereo(osg::Vec3(-iod*0.5,0.0f,0.0f),screenDistance); + right_camera->adjustEyeOffsetForStereo(osg::Vec3(iod*0.5,0.0f,0.0f),screenDistance); + + cout << "draw"<setCamera(left_camera.get()); + _renderStage->draw(*_state,previous); + + + cout << " back right"<setCamera(right_camera.get()); + _renderStage->_stageDrawnThisFrame = false; + _renderStage->draw(*_state,previous); + } + break; + case(RED_GREEN_STEREO): + { + osg::ColorMask* red = new osg::ColorMask; + osg::ColorMask* green = new osg::ColorMask; + + red->setMask(true,false,false,true); + _renderStage->setColorMask(red); + _renderStage->draw(*_state,previous); + + green->setMask(false,true,false,true); + _renderStage->setColorMask(green); + _renderStage->_stageDrawnThisFrame = false; + _renderStage->draw(*_state,previous); + + } + break; + default: + { + _renderStage->draw(*_state,previous); + } + break; + } GLenum errorNo = glGetError(); if (errorNo!=GL_NO_ERROR)