From 341ffb2361e6fbebbf4ec5f450286c37b8d1e684 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 12 Apr 2002 18:06:13 +0000 Subject: [PATCH] Further work on cleaning up SceneView and Camera, in particular moving strereo support out of Camera and into SceneView. Also enabled the option to set the projection and modelview matrices directly on SceneView thereby removing the dependance on osg::Camrea to control the view of the scene. --- include/osg/Camera | 25 +------- include/osg/ImpostorSprite | 1 - include/osg/State | 2 +- include/osgUtil/SceneView | 12 +++- src/osg/Camera.cpp | 118 ++----------------------------------- src/osgUtil/SceneView.cpp | 81 +++++++++++++++++++------ 6 files changed, 77 insertions(+), 162 deletions(-) diff --git a/include/osg/Camera b/include/osg/Camera index 333fd7981..424908f4b 100644 --- a/include/osg/Camera +++ b/include/osg/Camera @@ -242,17 +242,6 @@ class SG_EXPORT Camera: public osg::Referenced * equivalent to using gluLookAt.*/ const Matrix& getModelViewMatrix() const; - - /** Switch on/off the use of the near and far clipping plane which creating the - * getClippingVolume(), uses the camera _zfar value for the position - * of the far clipping plane. By default this value is off.*/ - void setUseNearAndFarClippingPlanes(const bool use); - /** Get whether the ClippingVolume uses a near and far clipping planes.*/ - const bool getUseNearAndFarClippingPlanes() const { return _useNearAndFarClippingPlanes; } - - /** get the view frustum clipping in model coordinates */ - const ClippingVolume& getClippingVolume() const; - /** Map object coordinates into windows coordinates. * Equivalent to gluProject(...). */ @@ -297,15 +286,6 @@ class SG_EXPORT Camera: public osg::Referenced /** 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); - - - /** Set up the OpenGL projection and model view matrices.*/ - virtual void apply(State& state); protected: @@ -352,11 +332,8 @@ class SG_EXPORT Camera: public osg::Referenced mutable ref_ptr _mp; mutable ref_ptr _inversemp; - void calculateMatricesAndClippingVolume() const; + void computeMatrices() const; - // used for offsetting camera to ajust for left and right stereo views. - bool _useEyeOffset; - osg::Vec3 _eyeOffset; float _screenDistance; FusionDistanceMode _fusionDistanceMode; diff --git a/include/osg/ImpostorSprite b/include/osg/ImpostorSprite index 1fb42e9e1..dc604dc94 100644 --- a/include/osg/ImpostorSprite +++ b/include/osg/ImpostorSprite @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/include/osg/State b/include/osg/State index 61acebfef..426f4a213 100644 --- a/include/osg/State +++ b/include/osg/State @@ -10,8 +10,8 @@ #include #include -#include #include +#include #include #include diff --git a/include/osgUtil/SceneView b/include/osgUtil/SceneView index 39597a842..f22fbc3d1 100644 --- a/include/osgUtil/SceneView +++ b/include/osgUtil/SceneView @@ -115,14 +115,22 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced osg::State* getState() { return _state.get(); } const osg::State* getState() const { return _state.get(); } + + /** set an osg::Camera for the scene view to use for setting projection and modelview matrices internaly. + * However, the projection matrix from the camera will be overriden by a projection matrix which is set explicitly + * via setProjectionMatrix(..), see below. + * Also, the model matrix from the camera will be overriden by a modelview matrix which is set explicitly + * via setModelViewMatrix(..), see below.*/ void setCamera(osg::Camera* camera) { _camera = camera; } osg::Camera* getCamera() { return _camera.get(); } const osg::Camera* getCamera() const { return _camera.get(); } + /** set an projection matrix. Note, this will override a camera's projection matrix if it is not NULL.*/ void setProjectionMatrix(osg::Matrix* matrix) { _projectionMatrix = matrix; } osg::Matrix* getProjectionMatrix() { return _projectionMatrix.get(); } const osg::Matrix* getProjectionMatrix() const { return _projectionMatrix.get(); } + /** set an modelview matrix. Note, this will override a camera's modelview matrix if it is not NULL.*/ void setModelViewMatrix(osg::Matrix* matrix) { _modelviewMatrix = matrix; } osg::Matrix* getModelViewMatrix() { return _modelviewMatrix.get(); } const osg::Matrix* getModelViewMatrix() const { return _modelviewMatrix.get(); } @@ -237,7 +245,7 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced virtual ~SceneView(); /** Do cull traversal of attached scene graph using Cull NodeVisitor.*/ - virtual void cullStage(osg::Camera* camera,osgUtil::CullVisitor* cullVisitor, osgUtil::RenderGraph* rendergraph, osgUtil::RenderStage* renderStage); + virtual void cullStage(osg::Matrix* projection,osg::Matrix* modelview,osgUtil::CullVisitor* cullVisitor, osgUtil::RenderGraph* rendergraph, osgUtil::RenderStage* renderStage); virtual void drawStage(osgUtil::RenderStage* renderStage); osg::ref_ptr _sceneData; @@ -258,13 +266,11 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced osg::ref_ptr _renderStage; osg::Node::NodeMask _cullMaskLeft; - osg::ref_ptr _cameraLeft; osg::ref_ptr _cullVisitorLeft; osg::ref_ptr _rendergraphLeft; osg::ref_ptr _renderStageLeft; osg::Node::NodeMask _cullMaskRight; - osg::ref_ptr _cameraRight; osg::ref_ptr _cullVisitorRight; osg::ref_ptr _rendergraphRight; osg::ref_ptr _renderStageRight; diff --git a/src/osg/Camera.cpp b/src/osg/Camera.cpp index e2d89454d..d876546c9 100644 --- a/src/osg/Camera.cpp +++ b/src/osg/Camera.cpp @@ -30,9 +30,6 @@ Camera::Camera(DisplaySettings* ds) _useNearAndFarClippingPlanes = false; - _useEyeOffset = false; - _eyeOffset.set(0.0f,0.0f,0.0f); - _attachedTransformMode = NO_ATTACHED_TRANSFORM; if (ds) _screenDistance = ds->getScreenDistance(); @@ -86,21 +83,14 @@ void Camera::copy(const Camera& camera) _eyeToModelTransform = camera._eyeToModelTransform; _modelToEyeTransform = camera._modelToEyeTransform; - // flags to determine if near and far clipping planes are required. - _useNearAndFarClippingPlanes = camera._useNearAndFarClippingPlanes; - // cached matrix and clipping volume derived from above settings. _dirty = false;// camera._dirty; _projectionMatrix = NULL; //camera._projectionMatrix; _modelViewMatrix = NULL; //camera._modelViewMatrix; - _clippingVolume = camera._clippingVolume; _mp = NULL; _inversemp = NULL; - _useEyeOffset = camera._useEyeOffset; - _eyeOffset = camera._eyeOffset; - _screenDistance = camera._screenDistance; _fusionDistanceMode = camera._fusionDistanceMode; _fusionDistanceRatio = camera._fusionDistanceRatio; @@ -337,7 +327,7 @@ const double Camera::calc_aspectRatio() const const Matrix& Camera::getProjectionMatrix() const { - if (_dirty) calculateMatricesAndClippingVolume(); + if (_dirty) computeMatrices(); return *_projectionMatrix; } @@ -582,25 +572,10 @@ const Vec3 Camera::getSideVector_Model() const const Matrix& Camera::getModelViewMatrix() const { - if (_dirty) calculateMatricesAndClippingVolume(); + if (_dirty) computeMatrices(); return *_modelViewMatrix; } -void Camera::setUseNearAndFarClippingPlanes(const bool use) -{ - if (_useNearAndFarClippingPlanes != use) - { - _useNearAndFarClippingPlanes = use; - _dirty = true; - } -} - -const ClippingVolume& Camera::getClippingVolume() const -{ - if (_dirty) calculateMatricesAndClippingVolume(); - return _clippingVolume; -} - const float Camera::getFusionDistance() const { switch(_fusionDistanceMode) @@ -611,7 +586,7 @@ const float Camera::getFusionDistance() const } } -void Camera::calculateMatricesAndClippingVolume() const +void Camera::computeMatrices() const { @@ -620,13 +595,6 @@ void Camera::calculateMatricesAndClippingVolume() const float top = _top; float bottom = _bottom; - if (_useEyeOffset) - { - float dx = -_eyeOffset.x()*(1.0f/_screenDistance); - left += dx; - right += dx; - } - // set up the projection matrix. switch(_projectionType) { @@ -722,62 +690,8 @@ void Camera::calculateMatricesAndClippingVolume() const break; } - if (_useEyeOffset) - { - (*_modelViewMatrix) = (*_modelViewMatrix) * Matrix::translate(-_eyeOffset*(getFusionDistance()/_screenDistance)); - } -// _clippingVolume.clear(); -// -// // set the clipping volume. -// switch(_projectionType) -// { -// case(ORTHO): -// case(ORTHO2D): -// { -// } -// break; -// case(FRUSTUM): -// case(PERSPECTIVE): -// { -// // calculate the frustum normals, postive pointing inwards. -// // left clipping plane -// // note, _left,_right,_top and _bottom are already devided -// // by _zNear so no need to take into account for normal -// // calculations. -// Vec3 leftNormal (1.0f,0.0f,left); -// leftNormal.normalize(); -// _clippingVolume.add(Plane(leftNormal,0.0f)); -// -// -// Vec3 rightNormal (-1.0f,0.0f,-right); -// rightNormal.normalize(); -// _clippingVolume.add(Plane(rightNormal,0.0f)); -// -// Vec3 bottomNormal(0.0f,1.0f,bottom); -// bottomNormal.normalize(); -// _clippingVolume.add(Plane(bottomNormal,0.0f)); -// -// Vec3 topNormal(0.0f,-1.0f,-top); -// topNormal.normalize(); -// _clippingVolume.add(Plane(topNormal,0.0f)); -// -// if (_useNearClippingPlane) -// { -// _clippingVolume.add(Plane(0.0f,0.0f,-1.0f,-_zNear)); -// } -// -// if (_useFarClippingPlane) -// { -// _clippingVolume.add(Plane(0.0f,0.0f,1.0f,_zFar)); -// } -// -// } -// break; -// -// } - if (!_mp.valid()) _mp = osgNew Matrix; _mp->mult(*_modelViewMatrix,*_projectionMatrix); @@ -785,20 +699,9 @@ void Camera::calculateMatricesAndClippingVolume() const if (!_inversemp.valid()) _inversemp = osgNew Matrix; if (!_inversemp->invert(*_mp)) { - notify(WARN)<<"Warning: Camera::calculateMatricesAndClippingVolume() failed to invert _mp"<reset(); + + osg::ref_ptr projection = _projectionMatrix.get(); + osg::ref_ptr modelview = _modelviewMatrix.get(); + if (_camera.valid()) + { + _camera->adjustAspectRatio(_viewport->aspectRatio()); + _camera->setScreenDistance(_displaySettings->getScreenDistance()); + + if (!projection) projection = osgNew osg::Matrix(_camera->getProjectionMatrix()); + if (!modelview) modelview = osgNew osg::Matrix(_camera->getModelViewMatrix()); + } + + if (!projection) projection = osgNew osg::Matrix(); + if (!modelview) modelview = osgNew osg::Matrix(); if (_displaySettings.valid() && _displaySettings->getStereo()) { - - _camera->setScreenDistance(_displaySettings->getScreenDistance()); - _cameraLeft = osgNew osg::Camera(*_camera); - _cameraRight = osgNew osg::Camera(*_camera); + float fusionDistance = _displaySettings->getScreenDistance(); + if (_camera.valid()) + { + fusionDistance = _camera->getFusionDistance(); + } + float iod = _displaySettings->getEyeSeperation(); - - _cameraLeft->adjustEyeOffsetForStereo(osg::Vec3(-iod*0.5,0.0f,0.0f)); - _cameraRight->adjustEyeOffsetForStereo(osg::Vec3(iod*0.5,0.0f,0.0f)); + float sd = _displaySettings->getScreenDistance(); + float es = 0.5f*iod*(fusionDistance/sd); if (!_cullVisitorLeft.valid()) _cullVisitorLeft = dynamic_cast(_cullVisitor->cloneType()); if (!_rendergraphLeft.valid()) _rendergraphLeft = dynamic_cast(_rendergraph->cloneType()); @@ -182,22 +197,57 @@ void SceneView::cull() if (!_rendergraphRight.valid()) _rendergraphRight = dynamic_cast(_rendergraph->cloneType()); if (!_renderStageRight.valid()) _renderStageRight = dynamic_cast(_renderStage->cloneType()); + + // set up the left eye. + osg::ref_ptr projectionLeft = osgNew osg::Matrix(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 = osgNew osg::Matrix( (*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(_cameraLeft.get(),_cullVisitorLeft.get(),_rendergraphLeft.get(),_renderStageLeft.get()); + cullStage(projectionLeft.get(),modelviewLeft.get(),_cullVisitorLeft.get(),_rendergraphLeft.get(),_renderStageLeft.get()); + + + // set up the right eye. + osg::ref_ptr projectionRight = osgNew osg::Matrix(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 = osgNew osg::Matrix( (*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(_cameraRight.get(),_cullVisitorRight.get(),_rendergraphRight.get(),_renderStageRight.get()); + cullStage(projectionRight.get(),modelviewRight.get(),_cullVisitorRight.get(),_rendergraphRight.get(),_renderStageRight.get()); + } else { _cullVisitor->setTraversalMask(_cullMask); - cullStage(_camera.get(),_cullVisitor.get(),_rendergraph.get(),_renderStage.get()); + cullStage(projection.get(),modelview.get(),_cullVisitor.get(),_rendergraph.get(),_renderStage.get()); } + if (_camera.valid()) + { + _camera->setNearFar(_near_plane,_far_plane); + } + } -void SceneView::cullStage(osg::Camera* camera, osgUtil::CullVisitor* cullVisitor, osgUtil::RenderGraph* rendergraph, osgUtil::RenderStage* renderStage) +void SceneView::cullStage(osg::Matrix* projection,osg::Matrix* modelview,osgUtil::CullVisitor* cullVisitor, osgUtil::RenderGraph* rendergraph, osgUtil::RenderStage* renderStage) { if (!_sceneData || !_viewport->valid()) return; @@ -220,7 +270,6 @@ void SceneView::cullStage(osg::Camera* camera, osgUtil::CullVisitor* cullVisitor _state->setDisplaySettings(_displaySettings.get()); - camera->adjustAspectRatio(_viewport->aspectRatio()); cullVisitor->reset(); @@ -232,10 +281,6 @@ void SceneView::cullStage(osg::Camera* camera, osgUtil::CullVisitor* cullVisitor cullVisitor->setTraversalNumber(_frameStamp->getFrameNumber()); } - // get the camera's modelview - osg::Matrix* projection = osgNew osg::Matrix(camera->getProjectionMatrix()); - osg::Matrix* modelview = osgNew osg::Matrix(camera->getModelViewMatrix()); - cullVisitor->setLODBias(_lodBias); cullVisitor->setEarthSky(NULL); // reset earth sky on each frame. @@ -340,7 +385,6 @@ void SceneView::cullStage(osg::Camera* camera, osgUtil::CullVisitor* cullVisitor _far_plane = 1000.0f; } - camera->setNearFar(_near_plane,_far_plane); } // prune out any empty RenderGraph children. @@ -352,14 +396,13 @@ void SceneView::cullStage(osg::Camera* camera, osgUtil::CullVisitor* cullVisitor } + void SceneView::draw() { if (_displaySettings.valid() && _displaySettings->getStereo()) { - _camera->setScreenDistance(_displaySettings->getScreenDistance()); - switch(_displaySettings->getStereoMode()) { case(osg::DisplaySettings::QUAD_BUFFER):