From 734be184715396921aa26d7be8258f1361b87a33 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 21 Dec 2001 13:07:35 +0000 Subject: [PATCH] Updates to the support for stereo in osg::Camera, osgUtil::SceneView and the CameraManipulators. --- include/osg/Camera | 60 +++++++++++++++++++++------- src/osg/Camera.cpp | 35 +++++++++++----- src/osgUtil/DriveManipulator.cpp | 2 + src/osgUtil/FlightManipulator.cpp | 2 + src/osgUtil/SceneView.cpp | 13 +++--- src/osgUtil/TrackballManipulator.cpp | 3 ++ 6 files changed, 83 insertions(+), 32 deletions(-) diff --git a/include/osg/Camera b/include/osg/Camera index 5fca849ff..4787c0dd0 100644 --- a/include/osg/Camera +++ b/include/osg/Camera @@ -125,15 +125,8 @@ class SG_EXPORT Camera: public osg::Referenced const Matrix& getProjectionMatrix() const; - - /** set the fusion distance, the distance in model coords, when viewing stereo, that the - * left and right eye images converge. This value is dual of the screen distance, - * which is distance between viewers eyes and display device, while the fusion distance is - * this equivilant distance but in the virtual world (model coords.)*/ - inline const double setFusionDistance() const { return _fusionDistance; } - /** get fusion distance.*/ - inline const double getFusionDistance() const { return _fusionDistance; } + enum LookAtType @@ -195,7 +188,8 @@ class SG_EXPORT Camera: public osg::Referenced /** calculate side vector.*/ const Vec3 getSideVector() const; - + /** calculate the look distance which is the distance between the eye and the center.*/ + inline float getLookDistance() const { return (_center-_eye).length(); } enum TransformMode { @@ -274,11 +268,46 @@ class SG_EXPORT Camera: public osg::Referenced const bool unproject(const Vec3& win,const Viewport& viewport,Vec3& obj) const; + + enum FusionDistanceMode + { + PROPORTIONAL_TO_LOOK_DISTANCE, + PROPORTIONAL_TO_SCREEN_DISTANCE + }; + + /** Set the fusion distance function which in use to calculate the + * fusion distance used in stereo rendering. Default value is + * PROPORTIONAL_TO_LOOK_DISTANCE, 1.0f.*/ + void setFusionDistanceFunction(FusionDistanceMode mode, float ratio=1.0f) + { + _fusionDistanceMode = mode; + _fusionDistanceRatio = ratio; + _dirty = true; + } + + /** Get the fusion distance function.*/ + void getFusionDistanceFunction(FusionDistanceMode& mode, float& ratio) + { + mode = _fusionDistanceMode; + ratio = _fusionDistanceRatio; + } + + /** Calculate and return the fusion distance, using the FusionDistanceFunction.*/ + const float getFusionDistance() const; + + /** Set the physical distance between the viewers eyes and the display system. + * Note, only used when rendering in stereo.*/ + void setScreenDistance(float screenDistance) { _screenDistance = screenDistance; _dirty = true; } + + /** Get the physical distance between the viewers eyes and the display system.*/ + const float getScreenDistance() const { return _screenDistance; } + /** 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); + void adjustEyeOffsetForStereo(const osg::Vec3& offset); + /** Set up the OpenGL projection and model view matrices.*/ virtual void apply(State& state); @@ -312,8 +341,6 @@ class SG_EXPORT Camera: public osg::Referenced Vec3 _center; Vec3 _up; - double _fusionDistance; - TransformMode _attachedTransformMode; ref_ptr _eyeToModelTransform; ref_ptr _modelToEyeTransform; @@ -334,9 +361,12 @@ class SG_EXPORT Camera: public osg::Referenced void calculateMatricesAndClippingVolume() const; // used for offsetting camera to ajust for left and right stereo views. - bool _useEyeOffset; - osg::Vec3 _eyeOffset; - float _screenDistance; + bool _useEyeOffset; + osg::Vec3 _eyeOffset; + float _screenDistance; + + FusionDistanceMode _fusionDistanceMode; + float _fusionDistanceRatio; }; diff --git a/src/osg/Camera.cpp b/src/osg/Camera.cpp index a044bf8ff..fcb625202 100644 --- a/src/osg/Camera.cpp +++ b/src/osg/Camera.cpp @@ -24,14 +24,15 @@ Camera::Camera() _center.set(0.0f,0.0f,-1.0f); _up.set(0.0f,1.0f,0.0f); - _fusionDistance = 1.0f; - _useNearClippingPlane = false; _useFarClippingPlane = false; _useEyeOffset = false; _eyeOffset.set(0.0f,0.0f,0.0f); + _screenDistance = 1.0f; + _fusionDistanceMode = PROPORTIONAL_TO_LOOK_DISTANCE; + _fusionDistanceRatio = 1.0f; } Camera::Camera(const Camera& camera):Referenced() @@ -74,8 +75,6 @@ void Camera::copy(const Camera& camera) _center = camera._center; _up = camera._up; - _fusionDistance = camera._fusionDistance; - _attachedTransformMode = camera._attachedTransformMode; _eyeToModelTransform = camera._eyeToModelTransform; _modelToEyeTransform = camera._modelToEyeTransform; @@ -92,6 +91,14 @@ void Camera::copy(const Camera& camera) _mp = camera._mp; _inversemp = camera._inversemp; + + _useEyeOffset = camera._useEyeOffset; + _eyeOffset = camera._eyeOffset; + + _screenDistance = camera._screenDistance; + _fusionDistanceMode = camera._fusionDistanceMode; + _fusionDistanceRatio = camera._fusionDistanceRatio; + } Camera::~Camera() @@ -333,10 +340,7 @@ void Camera::home() _eye.set(0.0f,0.0f,0.0f); _center.set(0.0f,0.0f,-1.0f); _up.set(0.0f,1.0f,0.0f); - - // need to set to appropriate values.. - _fusionDistance = 1.0f; - + _dirty = true; } @@ -582,6 +586,16 @@ const ClippingVolume& Camera::getClippingVolume() const return _clippingVolume; } +const float Camera::getFusionDistance() const +{ + switch(_fusionDistanceMode) + { + case(PROPORTIONAL_TO_SCREEN_DISTANCE): return _screenDistance*_fusionDistanceRatio; + case(PROPORTIONAL_TO_LOOK_DISTANCE): + default: return getLookDistance()*_fusionDistanceRatio; + } +} + void Camera::calculateMatricesAndClippingVolume() const { @@ -695,7 +709,7 @@ void Camera::calculateMatricesAndClippingVolume() const if (_useEyeOffset) { - (*_modelViewMatrix) = (*_modelViewMatrix) * Matrix::translate(-_eyeOffset*_fusionDistance/_screenDistance); + (*_modelViewMatrix) = (*_modelViewMatrix) * Matrix::translate(-_eyeOffset*(getFusionDistance()/_screenDistance)); } @@ -804,11 +818,10 @@ const bool Camera::unproject(const Vec3& win,const Viewport& viewport,Vec3& obj) return false; } -void Camera::adjustEyeOffsetForStereo(const osg::Vec3& offset,float screenDistance) +void Camera::adjustEyeOffsetForStereo(const osg::Vec3& offset) { _useEyeOffset = true; _eyeOffset = offset; - _screenDistance = screenDistance; _dirty = true; } diff --git a/src/osgUtil/DriveManipulator.cpp b/src/osgUtil/DriveManipulator.cpp index 7e4a05bc9..5990824e2 100644 --- a/src/osgUtil/DriveManipulator.cpp +++ b/src/osgUtil/DriveManipulator.cpp @@ -353,6 +353,8 @@ bool DriveManipulator::calcMovement() // return if less then two events have been added. if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false; + _camera->setFusionDistanceFunction(osg::Camera::PROPORTIONAL_TO_SCREEN_DISTANCE,1.0f); + float dt = _ga_t0->time()-_ga_t1->time(); if (dt<0.0f) diff --git a/src/osgUtil/FlightManipulator.cpp b/src/osgUtil/FlightManipulator.cpp index 4a86755a8..014be6d19 100644 --- a/src/osgUtil/FlightManipulator.cpp +++ b/src/osgUtil/FlightManipulator.cpp @@ -161,6 +161,8 @@ bool FlightManipulator::calcMovement() // return if less then two events have been added. if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false; + _camera->setFusionDistanceFunction(osg::Camera::PROPORTIONAL_TO_SCREEN_DISTANCE,1.0f); + float dt = _ga_t0->time()-_ga_t1->time(); if (dt<0.0f) diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index 6415ef858..867fd7987 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -293,9 +293,12 @@ void SceneView::draw() RenderLeaf* previous = NULL; + if (_visualsSettings.valid() && _visualsSettings->getStereo()) { + _camera->setScreenDistance(_visualsSettings->getScreenDistance()); + switch(_visualsSettings->getStereoMode()) { case(osg::VisualsSettings::QUAD_BUFFER): @@ -304,10 +307,9 @@ void SceneView::draw() osg::ref_ptr right_camera = new osg::Camera(*_camera); float iod = _visualsSettings->getEyeSeperation(); - float screenDistance = _visualsSettings->getEyeSeperation(); - 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); + left_camera->adjustEyeOffsetForStereo(osg::Vec3(-iod*0.5,0.0f,0.0f)); + right_camera->adjustEyeOffsetForStereo(osg::Vec3(iod*0.5,0.0f,0.0f)); glDrawBuffer(GL_BACK_LEFT); _renderStage->setCamera(left_camera.get()); @@ -326,10 +328,9 @@ void SceneView::draw() osg::ref_ptr right_camera = new osg::Camera(*_camera); float iod = _visualsSettings->getEyeSeperation(); - float screenDistance = _visualsSettings->getScreenDistance(); - 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); + left_camera->adjustEyeOffsetForStereo(osg::Vec3(-iod*0.5,0.0f,0.0f)); + right_camera->adjustEyeOffsetForStereo(osg::Vec3(iod*0.5,0.0f,0.0f)); osg::ColorMask* red = new osg::ColorMask; osg::ColorMask* green = new osg::ColorMask; diff --git a/src/osgUtil/TrackballManipulator.cpp b/src/osgUtil/TrackballManipulator.cpp index 95769701f..7cd848884 100644 --- a/src/osgUtil/TrackballManipulator.cpp +++ b/src/osgUtil/TrackballManipulator.cpp @@ -175,12 +175,15 @@ void TrackballManipulator::addMouseEvent(const GUIEventAdapter& ea) bool TrackballManipulator::calcMovement() { + _camera->setFusionDistanceFunction(osg::Camera::PROPORTIONAL_TO_LOOK_DISTANCE,1.0f); + // return if less then two events have been added. if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false; float dx = _ga_t0->getX()-_ga_t1->getX(); float dy = _ga_t0->getY()-_ga_t1->getY(); + // return if there is no movement. if (dx==0 && dy==0) return false;