From afecdbb46bb268167299d5aadf1b0272b536cd25 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 3 Mar 2011 15:52:19 +0000 Subject: [PATCH] Moved intial cut of depth partition support into osgViewer::View via two new methods: /** Convenience method for setting up multiple slave cameras that depth partition the specified camera.*/ bool setUpDepthPartitionForCamera(osg::Camera* cameraToPartition, DepthPartitionSettings* dps=0); /** Convenience method for setting up multiple slave cameras that depth partition each of the view's active cameras.*/ bool setUpDepthPartition(DepthPartitionSettings* dsp=0); --- examples/osgshadow/osgshadow.cpp | 313 ++----------------------------- include/osgViewer/View | 27 +++ src/osgViewer/View.cpp | 284 ++++++++++++++++++++++++++++ 3 files changed, 325 insertions(+), 299 deletions(-) diff --git a/examples/osgshadow/osgshadow.cpp b/examples/osgshadow/osgshadow.cpp index 8e61b0c47..41b2721a9 100644 --- a/examples/osgshadow/osgshadow.cpp +++ b/examples/osgshadow/osgshadow.cpp @@ -569,297 +569,6 @@ osg::Node* createTestModel(osg::ArgumentParser& arguments) } -struct DepthPartitionSettings : public osg::Referenced -{ - DepthPartitionSettings() {} - - enum DepthMode - { - FIXED_RANGE, - BOUNDING_VOLUME - }; - - bool getDepthRange(osg::View& view, unsigned int partition, double& zNear, double& zFar) - { - switch(_mode) - { - case(FIXED_RANGE): - { - if (partition==0) - { - zNear = _zNear; - zFar = _zMid; - return true; - } - else if (partition==1) - { - zNear = _zMid; - zFar = _zFar; - return true; - } - return false; - } - case(BOUNDING_VOLUME): - { - osgViewer::View* view_withSceneData = dynamic_cast(&view); - const osg::Node* node = view_withSceneData ? view_withSceneData->getSceneData() : 0; - if (!node) return false; - - const osg::Camera* masterCamera = view.getCamera(); - if (!masterCamera) return false; - - osg::BoundingSphere bs = node->getBound(); - const osg::Matrixd& viewMatrix = masterCamera->getViewMatrix(); - //osg::Matrixd& projectionMatrix = masterCamera->getProjectionMatrix(); - - osg::Vec3d lookVectorInWorldCoords = osg::Matrixd::transform3x3(viewMatrix,osg::Vec3d(0.0,0.0,-1.0)); - lookVectorInWorldCoords.normalize(); - - osg::Vec3d nearPointInWorldCoords = bs.center() - lookVectorInWorldCoords*bs.radius(); - osg::Vec3d farPointInWorldCoords = bs.center() + lookVectorInWorldCoords*bs.radius(); - - osg::Vec3d nearPointInEyeCoords = nearPointInWorldCoords * viewMatrix; - osg::Vec3d farPointInEyeCoords = farPointInWorldCoords * viewMatrix; - -#if 0 - OSG_NOTICE<setNodeMask(0x0); - return; - } - else - { - camera->setNodeMask(0xffffff); - } - - if (camera->getProjectionMatrix()(0,3)==0.0 && - camera->getProjectionMatrix()(1,3)==0.0 && - camera->getProjectionMatrix()(2,3)==0.0) - { - double left, right, bottom, top, zNear, zFar; - camera->getProjectionMatrixAsOrtho(left, right, bottom, top, zNear, zFar); - camera->setProjectionMatrixAsOrtho(left, right, bottom, top, computed_zNear, computed_zFar); - } - else - { - double left, right, bottom, top, zNear, zFar; - camera->getProjectionMatrixAsFrustum(left, right, bottom, top, zNear, zFar); - - double nr = computed_zNear / zNear; - camera->setProjectionMatrixAsFrustum(left * nr, right * nr, bottom * nr, top * nr, computed_zNear, computed_zFar); - } - } - - osg::ref_ptr _dps; - unsigned int _partition; -}; - - -bool setUpDepthPartitionForCamera(osg::View& view, osg::Camera* cameraToPartition, DepthPartitionSettings* dps) -{ - osg::ref_ptr context = cameraToPartition->getGraphicsContext(); - if (!context) return false; - - osg::ref_ptr viewport = cameraToPartition->getViewport(); - if (!viewport) return false; - - cameraToPartition->setGraphicsContext(0); - cameraToPartition->setViewport(0); - - bool useMastersSceneData = true; - osg::Matrixd projectionOffset; - osg::Matrixd viewOffset; - - if (view.getCamera()==cameraToPartition) - { - // replace main camera with depth partition cameras - OSG_NOTICE<<"Replacing main Camera"<=view.getNumSlaves()) return false; - - osg::View::Slave& slave = view.getSlave(i); - - useMastersSceneData = slave._useMastersSceneData; - projectionOffset = slave._projectionOffset; - viewOffset = slave._viewOffset; - - OSG_NOTICE<<"Replacing slave Camera"< camera = new osg::Camera; - camera->setGraphicsContext(context.get()); - camera->setViewport(viewport.get()); - - camera->setDrawBuffer(cameraToPartition->getDrawBuffer()); - camera->setReadBuffer(cameraToPartition->getReadBuffer()); - - camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); - camera->setCullingMode(osg::Camera::ENABLE_ALL_CULLING); - - view.addSlave(camera.get()); - - osg::View::Slave& slave = view.getSlave(view.getNumSlaves()-1); - - slave._useMastersSceneData = useMastersSceneData; - slave._projectionOffset = projectionOffset; - slave._viewOffset = viewOffset; - slave._updateSlaveCallback = new MyUpdateSlaveCallback(dps, 1); - } - - // near camera - { - osg::ref_ptr camera = new osg::Camera; - camera->setGraphicsContext(context.get()); - camera->setViewport(viewport.get()); - - camera->setDrawBuffer(cameraToPartition->getDrawBuffer()); - camera->setReadBuffer(cameraToPartition->getReadBuffer()); - - camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); - camera->setCullingMode(osg::Camera::ENABLE_ALL_CULLING); - camera->setClearMask(GL_DEPTH_BUFFER_BIT); - - view.addSlave(camera.get()); - - osg::View::Slave& slave = view.getSlave(view.getNumSlaves()-1); - slave._useMastersSceneData = useMastersSceneData; - slave._projectionOffset = projectionOffset; - slave._viewOffset = viewOffset; - slave._updateSlaveCallback = new MyUpdateSlaveCallback(dps, 0); - } - - return true; -} - - -typedef std::list< osg::ref_ptr > Cameras; - -Cameras getActiveCameras(osg::View& view) -{ - Cameras activeCameras; - - if (view.getCamera() && view.getCamera()->getGraphicsContext()) - { - activeCameras.push_back(view.getCamera()); - } - - for(unsigned int i=0; igetGraphicsContext()) - { - activeCameras.push_back(slave._camera.get()); - } - } - return activeCameras; -} - - -bool setUpDepthPartition(osgViewer::View& view, DepthPartitionSettings* dsp) -{ - OSG_NOTICE<<"setUpDepthPartition(View,..)"<areThreadsRunning(); - if (threadsWereRunning) view.getViewerBase()->stopThreading(); - - for(Cameras::iterator itr = originalCameras.begin(); - itr != originalCameras.end(); - ++itr) - { - setUpDepthPartitionForCamera(view, itr->get(), dsp); - } - - if (threadsWereRunning) view.getViewerBase()->startThreading(); - - return true; -} - int main(int argc, char** argv) { @@ -919,16 +628,22 @@ int main(int argc, char** argv) return 1; } - double partitionPosition = 5.0; - if (arguments.read("--depth-partition",partitionPosition) || arguments.read("--dp")) + double zNear=1.0, zMid=10.0, zFar=1000.0; + if (arguments.read("--depth-partition",zNear, zMid, zFar)) { // set up depth partitioning - osg::ref_ptr dps = new DepthPartitionSettings; - dps->_mode = DepthPartitionSettings::BOUNDING_VOLUME; - dps->_zNear = 0.5; - dps->_zMid = partitionPosition; - dps->_zFar = 1000.0; - setUpDepthPartition(viewer, dps.get()); + osg::ref_ptr dps = new osgViewer::DepthPartitionSettings; + dps->_mode = osgViewer::DepthPartitionSettings::FIXED_RANGE; + dps->_zNear = zNear; + dps->_zMid = zMid; + dps->_zFar = zFar; + viewer.setUpDepthPartition(dps.get()); + } + + if (arguments.read("--dp")) + { + // set up depth partitioning + viewer.setUpDepthPartition(); } float fov = 0.0; diff --git a/include/osgViewer/View b/include/osgViewer/View index 5fdf5bfe2..0f29cecc5 100644 --- a/include/osgViewer/View +++ b/include/osgViewer/View @@ -30,6 +30,26 @@ namespace osgViewer { + +struct OSGVIEWER_EXPORT DepthPartitionSettings : public osg::Referenced +{ + enum DepthMode + { + FIXED_RANGE, + BOUNDING_VOLUME + }; + + DepthPartitionSettings(DepthMode mode=BOUNDING_VOLUME); + + virtual bool getDepthRange(osg::View& view, unsigned int partition, double& zNear, double& zFar); + + DepthMode _mode; + double _zNear; + double _zMid; + double _zFar; +}; + + /** View holds a single view on a scene, this view may be composed of one or more slave cameras.*/ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter { @@ -183,6 +203,13 @@ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter void setUpViewForWoWVxDisplay(unsigned int screenNum, unsigned char wow_content, unsigned char wow_factor, unsigned char wow_offset, float wow_disparity_Zd, float wow_disparity_vz, float wow_disparity_M, float wow_disparity_C); + /** Convenience method for setting up multiple slave cameras that depth partition the specified camera.*/ + bool setUpDepthPartitionForCamera(osg::Camera* cameraToPartition, DepthPartitionSettings* dps=0); + + /** Convenience method for setting up multiple slave cameras that depth partition each of the view's active cameras.*/ + bool setUpDepthPartition(DepthPartitionSettings* dsp=0); + + /** Return true if this view contains a specified camera.*/ bool containsCamera(const osg::Camera* camera) const; diff --git a/src/osgViewer/View.cpp b/src/osgViewer/View.cpp index 8573050a7..98072a966 100644 --- a/src/osgViewer/View.cpp +++ b/src/osgViewer/View.cpp @@ -1595,6 +1595,290 @@ void View::setUpViewForWoWVxDisplay(unsigned int screenNum, unsigned char wow_co } } +DepthPartitionSettings::DepthPartitionSettings(DepthMode mode): + _mode(mode), + _zNear(1.0), _zMid(5.0), _zFar(1000.0) +{} + +bool DepthPartitionSettings::getDepthRange(osg::View& view, unsigned int partition, double& zNear, double& zFar) +{ + switch(_mode) + { + case(FIXED_RANGE): + { + if (partition==0) + { + zNear = _zNear; + zFar = _zMid; + return true; + } + else if (partition==1) + { + zNear = _zMid; + zFar = _zFar; + return true; + } + return false; + } + case(BOUNDING_VOLUME): + { + osgViewer::View* view_withSceneData = dynamic_cast(&view); + const osg::Node* node = view_withSceneData ? view_withSceneData->getSceneData() : 0; + if (!node) return false; + + const osg::Camera* masterCamera = view.getCamera(); + if (!masterCamera) return false; + + osg::BoundingSphere bs = node->getBound(); + const osg::Matrixd& viewMatrix = masterCamera->getViewMatrix(); + //osg::Matrixd& projectionMatrix = masterCamera->getProjectionMatrix(); + + osg::Vec3d lookVectorInWorldCoords = osg::Matrixd::transform3x3(viewMatrix,osg::Vec3d(0.0,0.0,-1.0)); + lookVectorInWorldCoords.normalize(); + + osg::Vec3d nearPointInWorldCoords = bs.center() - lookVectorInWorldCoords*bs.radius(); + osg::Vec3d farPointInWorldCoords = bs.center() + lookVectorInWorldCoords*bs.radius(); + + osg::Vec3d nearPointInEyeCoords = nearPointInWorldCoords * viewMatrix; + osg::Vec3d farPointInEyeCoords = farPointInWorldCoords * viewMatrix; + +#if 0 + OSG_NOTICE<setNodeMask(0x0); + return; + } + else + { + camera->setNodeMask(0xffffff); + } + + if (camera->getProjectionMatrix()(0,3)==0.0 && + camera->getProjectionMatrix()(1,3)==0.0 && + camera->getProjectionMatrix()(2,3)==0.0) + { + double left, right, bottom, top, zNear, zFar; + camera->getProjectionMatrixAsOrtho(left, right, bottom, top, zNear, zFar); + camera->setProjectionMatrixAsOrtho(left, right, bottom, top, computed_zNear, computed_zFar); + } + else + { + double left, right, bottom, top, zNear, zFar; + camera->getProjectionMatrixAsFrustum(left, right, bottom, top, zNear, zFar); + + double nr = computed_zNear / zNear; + camera->setProjectionMatrixAsFrustum(left * nr, right * nr, bottom * nr, top * nr, computed_zNear, computed_zFar); + } + } + + osg::ref_ptr _dps; + unsigned int _partition; +}; + + +typedef std::list< osg::ref_ptr > Cameras; + +Cameras getActiveCameras(osg::View& view) +{ + Cameras activeCameras; + + if (view.getCamera() && view.getCamera()->getGraphicsContext()) + { + activeCameras.push_back(view.getCamera()); + } + + for(unsigned int i=0; igetGraphicsContext()) + { + activeCameras.push_back(slave._camera.get()); + } + } + return activeCameras; +} + +} + +bool View::setUpDepthPartitionForCamera(osg::Camera* cameraToPartition, DepthPartitionSettings* incomming_dps) +{ + osg::ref_ptr context = cameraToPartition->getGraphicsContext(); + if (!context) return false; + + osg::ref_ptr viewport = cameraToPartition->getViewport(); + if (!viewport) return false; + + osg::ref_ptr dps = incomming_dps; + if (!dps) dps = new DepthPartitionSettings; + + bool useMastersSceneData = true; + osg::Matrixd projectionOffset; + osg::Matrixd viewOffset; + + if (getCamera()==cameraToPartition) + { + // replace main camera with depth partition cameras + OSG_INFO<<"View::setUpDepthPartitionForCamera(..) Replacing main Camera"<=getNumSlaves()) return false; + + osg::View::Slave& slave = getSlave(i); + + useMastersSceneData = slave._useMastersSceneData; + projectionOffset = slave._projectionOffset; + viewOffset = slave._viewOffset; + + OSG_NOTICE<<"View::setUpDepthPartitionForCamera(..) Replacing slave Camera"<setGraphicsContext(0); + cameraToPartition->setViewport(0); + + // far camera + { + osg::ref_ptr camera = new osg::Camera; + camera->setGraphicsContext(context.get()); + camera->setViewport(viewport.get()); + + camera->setDrawBuffer(cameraToPartition->getDrawBuffer()); + camera->setReadBuffer(cameraToPartition->getReadBuffer()); + + camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); + camera->setCullingMode(osg::Camera::ENABLE_ALL_CULLING); + + addSlave(camera.get()); + + osg::View::Slave& slave = getSlave(getNumSlaves()-1); + + slave._useMastersSceneData = useMastersSceneData; + slave._projectionOffset = projectionOffset; + slave._viewOffset = viewOffset; + slave._updateSlaveCallback = new osgDepthPartition::MyUpdateSlaveCallback(dps.get(), 1); + } + + // near camera + { + osg::ref_ptr camera = new osg::Camera; + camera->setGraphicsContext(context.get()); + camera->setViewport(viewport.get()); + + camera->setDrawBuffer(cameraToPartition->getDrawBuffer()); + camera->setReadBuffer(cameraToPartition->getReadBuffer()); + + camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); + camera->setCullingMode(osg::Camera::ENABLE_ALL_CULLING); + camera->setClearMask(GL_DEPTH_BUFFER_BIT); + + addSlave(camera.get()); + + osg::View::Slave& slave = getSlave(getNumSlaves()-1); + slave._useMastersSceneData = useMastersSceneData; + slave._projectionOffset = projectionOffset; + slave._viewOffset = viewOffset; + slave._updateSlaveCallback = new osgDepthPartition::MyUpdateSlaveCallback(dps.get(), 0); + } + + return true; +} + + + +bool View::setUpDepthPartition(DepthPartitionSettings* dsp) +{ + osgDepthPartition::Cameras originalCameras = osgDepthPartition::getActiveCameras(*this); + if (originalCameras.empty()) + { + OSG_INFO<<"osgView::View::setUpDepthPartition(,..), no windows assigned, doing view.setUpViewAcrossAllScreens()"<areThreadsRunning(); + if (threadsWereRunning) getViewerBase()->stopThreading(); + + for(osgDepthPartition::Cameras::iterator itr = originalCameras.begin(); + itr != originalCameras.end(); + ++itr) + { + setUpDepthPartitionForCamera(itr->get(), dsp); + } + + if (threadsWereRunning) getViewerBase()->startThreading(); + + return true; +} void View::assignSceneDataToCameras()