From ccfac57f20b0716fb0faf853e68f8d851abeacc8 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 8 Jun 2011 09:24:29 +0000 Subject: [PATCH] Simplified the osgdepthpartion example to use the osgView::View::setUpDepthPartition(..) feature --- examples/osgdepthpartition/CMakeLists.txt | 5 +- .../osgdepthpartition/DepthPartitionNode.cpp | 272 ------------ .../osgdepthpartition/DepthPartitionNode.h | 105 ----- .../osgdepthpartition/DistanceAccumulator.cpp | 402 ------------------ .../osgdepthpartition/DistanceAccumulator.h | 115 ----- .../osgdepthpartition/osgdepthpartition.cpp | 39 +- 6 files changed, 28 insertions(+), 910 deletions(-) delete mode 100644 examples/osgdepthpartition/DepthPartitionNode.cpp delete mode 100644 examples/osgdepthpartition/DepthPartitionNode.h delete mode 100644 examples/osgdepthpartition/DistanceAccumulator.cpp delete mode 100644 examples/osgdepthpartition/DistanceAccumulator.h diff --git a/examples/osgdepthpartition/CMakeLists.txt b/examples/osgdepthpartition/CMakeLists.txt index 4f523146a..ea0cb1bb3 100644 --- a/examples/osgdepthpartition/CMakeLists.txt +++ b/examples/osgdepthpartition/CMakeLists.txt @@ -1,7 +1,4 @@ -#this file is automatically generated +SET(TARGET_SRC osgdepthpartition.cpp ) - -SET(TARGET_SRC DepthPartitionNode.cpp DistanceAccumulator.cpp osgdepthpartition.cpp ) -SET(TARGET_H DepthPartitionNode.h DistanceAccumulator.h ) #### end var setup ### SETUP_EXAMPLE(osgdepthpartition) diff --git a/examples/osgdepthpartition/DepthPartitionNode.cpp b/examples/osgdepthpartition/DepthPartitionNode.cpp deleted file mode 100644 index 9480cfd06..000000000 --- a/examples/osgdepthpartition/DepthPartitionNode.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/* OpenSceneGraph example, osgdepthpartion. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ - -#include "DepthPartitionNode.h" -#include - -using namespace osg; - -#define CURRENT_CLASS DepthPartitionNode - -CURRENT_CLASS::CURRENT_CLASS() -{ - _distAccumulator = new DistanceAccumulator; - init(); -} - -CURRENT_CLASS::CURRENT_CLASS(const CURRENT_CLASS& dpn, const osg::CopyOp& copyop) - : osg::Group(dpn, copyop), - _active(dpn._active), - _renderOrder(dpn._renderOrder), - _clearColorBuffer(dpn._clearColorBuffer) -{ - _distAccumulator = new DistanceAccumulator; - _numCameras = 0; -} - -CURRENT_CLASS::~CURRENT_CLASS() {} - -void CURRENT_CLASS::init() -{ - _active = true; - _numCameras = 0; - setCullingActive(false); - _renderOrder = osg::Camera::POST_RENDER; - _clearColorBuffer = true; -} - -void CURRENT_CLASS::setActive(bool active) -{ - if(_active == active) return; - _active = active; -} - -void CURRENT_CLASS::setClearColorBuffer(bool clear) -{ - _clearColorBuffer = clear; - - // Update the render order for the first Camera if it exists - if(!_cameraList.empty()) - { - if(clear) - _cameraList[0]->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else - _cameraList[0]->setClearMask(GL_DEPTH_BUFFER_BIT); - } -} - -void CURRENT_CLASS::setRenderOrder(osg::Camera::RenderOrder order) -{ - _renderOrder = order; - - // Update the render order for existing Cameras - unsigned int numCameras = _cameraList.size(); - for(unsigned int i = 0; i < numCameras; i++) - { - _cameraList[i]->setRenderOrder(_renderOrder); - } -} - -void CURRENT_CLASS::traverse(osg::NodeVisitor &nv) -{ - // If the scene hasn't been defined then don't do anything - unsigned int numChildren = _children.size(); - if(numChildren == 0) return; - - // If the node is not active then don't analyze it - if(!_active) - { - // Traverse the graph as usual - Group::traverse(nv); - return; - } - - // If the visitor is not a cull visitor, pass it directly onto the scene. - osgUtil::CullVisitor* cv = dynamic_cast(&nv); - if(!cv) - { - Group::traverse(nv); - return; - } - - // We are in the cull traversal, so first collect information on the - // current modelview and projection matrices and viewport. - osg::RefMatrix& modelview = *(cv->getModelViewMatrix()); - osg::RefMatrix& projection = *(cv->getProjectionMatrix()); - osg::Viewport* viewport = cv->getViewport(); - - // Prepare for scene traversal. - _distAccumulator->setMatrices(modelview, projection); - _distAccumulator->setNearFarRatio(cv->getNearFarRatio()); - _distAccumulator->reset(); - - // Step 1: Traverse the children, collecting the near/far distances. - unsigned int i; - for(i = 0; i < numChildren; i++) - { - _children[i]->accept(*(_distAccumulator.get())); - } - - // Step 2: Compute the near and far distances for every Camera that - // should be used to render the scene. - _distAccumulator->computeCameraPairs(); - - // Step 3: Create the Cameras, and add them as children. - DistanceAccumulator::PairList& camPairs = _distAccumulator->getCameraPairs(); - _numCameras = camPairs.size(); // Get the number of cameras - - // Create the Cameras, and add them as children. - if(_numCameras > 0) - { - osg::Camera *currCam; - DistanceAccumulator::DistancePair currPair; - - for(i = 0; i < _numCameras; i++) - { - // Create the camera, and clamp it's projection matrix - currPair = camPairs[i]; // (near,far) pair for current camera - currCam = createOrReuseCamera(projection, currPair.first, - currPair.second, i); - - // Set the modelview matrix and viewport of the camera - currCam->setViewMatrix(modelview); - currCam->setViewport(viewport); - - // Redirect the CullVisitor to the current camera - currCam->accept(nv); - } - - // Set the clear color for the first camera - _cameraList[0]->setClearColor(cv->getRenderStage()->getClearColor()); - } -} - -bool CURRENT_CLASS::addChild(osg::Node *child) -{ - return insertChild(_children.size(), child); -} - -bool CURRENT_CLASS::insertChild(unsigned int index, osg::Node *child) -{ - if(!Group::insertChild(index, child)) return false; // Insert child - - // Insert child into each Camera - unsigned int totalCameras = _cameraList.size(); - for(unsigned int i = 0; i < totalCameras; i++) - { - _cameraList[i]->insertChild(index, child); - } - return true; -} - - -bool CURRENT_CLASS::removeChildren(unsigned int pos, unsigned int numRemove) -{ - if(!Group::removeChildren(pos, numRemove)) return false; // Remove child - - // Remove child from each Camera - unsigned int totalCameras = _cameraList.size(); - for(unsigned int i = 0; i < totalCameras; i++) - { - _cameraList[i]->removeChildren(pos, numRemove); - } - return true; -} - -bool CURRENT_CLASS::setChild(unsigned int i, osg::Node *node) -{ - if(!Group::setChild(i, node)) return false; // Set child - - // Set child for each Camera - unsigned int totalCameras = _cameraList.size(); - for(unsigned int j = 0; j < totalCameras; j++) - { - _cameraList[j]->setChild(i, node); - } - return true; -} - -osg::Camera* CURRENT_CLASS::createOrReuseCamera(const osg::Matrix& proj, - double znear, double zfar, - const unsigned int &camNum) -{ - if(_cameraList.size() <= camNum) _cameraList.resize(camNum+1); - osg::Camera *camera = _cameraList[camNum].get(); - - if(!camera) // Create a new Camera - { - camera = new osg::Camera; - camera->setCullingActive(false); - camera->setRenderOrder(_renderOrder); - camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); - - // We will compute the near/far planes ourselves - camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); - camera->setCullingMode(osg::CullSettings::ENABLE_ALL_CULLING); - - if(camNum == 0 && _clearColorBuffer) - camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else - camera->setClearMask(GL_DEPTH_BUFFER_BIT); - - // Add our children to the new Camera's children - unsigned int numChildren = _children.size(); - for(unsigned int i = 0; i < numChildren; i++) - { - camera->addChild(_children[i].get()); - } - - _cameraList[camNum] = camera; - } - - osg::Matrixd &projection = camera->getProjectionMatrix(); - projection = proj; - - // Slightly inflate the near & far planes to avoid objects at the - // extremes being clipped out. - znear *= 0.999; - zfar *= 1.001; - - // Clamp the projection matrix z values to the range (near, far) - double epsilon = 1.0e-6; - if(fabs(projection(0,3)) < epsilon && - fabs(projection(1,3)) < epsilon && - fabs(projection(2,3)) < epsilon ) // Projection is Orthographic - { - epsilon = -1.0/(zfar - znear); // Used as a temp variable - projection(2,2) = 2.0*epsilon; - projection(3,2) = (zfar + znear)*epsilon; - } - else // Projection is Perspective - { - double trans_near = (-znear*projection(2,2) + projection(3,2)) / - (-znear*projection(2,3) + projection(3,3)); - double trans_far = (-zfar*projection(2,2) + projection(3,2)) / - (-zfar*projection(2,3) + projection(3,3)); - double ratio = fabs(2.0/(trans_near - trans_far)); - double center = -0.5*(trans_near + trans_far); - - projection.postMult(osg::Matrixd(1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, ratio, 0.0, - 0.0, 0.0, center*ratio, 1.0)); - } - - return camera; -} -#undef CURRENT_CLASS diff --git a/examples/osgdepthpartition/DepthPartitionNode.h b/examples/osgdepthpartition/DepthPartitionNode.h deleted file mode 100644 index bf1e6da75..000000000 --- a/examples/osgdepthpartition/DepthPartitionNode.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -*-c++-*- -* -* OpenSceneGraph example, osgdepthpartion. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ - -#ifndef _OF_DEPTHPARTITIONNODE_ -#define _OF_DEPTHPARTITIONNODE_ - -#include "DistanceAccumulator.h" -#include - -#define CURRENT_CLASS DepthPartitionNode -/********************************************************** - * Ravi Mathur - * OpenFrames API, class DepthPartitionNode - * A type of osg::Group that analyzes a scene, then partitions it into - * several segments that can be rendered separately. Each segment - * is small enough in the z-direction to avoid depth buffer problems - * for very large scenes. -**********************************************************/ -class CURRENT_CLASS : public osg::Group -{ - public: - CURRENT_CLASS(); - CURRENT_CLASS(const CURRENT_CLASS& dpn, - const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY); - - META_Node( OpenFrames, CURRENT_CLASS ); // Common Node functions - - /** Set the active state. If not active, this node will simply add the - specified scene as it's child, without analyzing it at all. */ - void setActive(bool active); - inline bool getActive() const { return _active; } - - /** Specify whether the color buffer should be cleared before the first - Camera draws it's scene. */ - void setClearColorBuffer(bool clear); - inline bool getClearColorBuffer() const { return _clearColorBuffer; } - - /** Specify the render order for each Camera */ - void setRenderOrder(osg::Camera::RenderOrder order); - inline osg::Camera::RenderOrder getRenderOrder() const - { return _renderOrder; } - - /** Set/get the maximum depth that the scene will be traversed to. - Defaults to UINT_MAX. */ - void setMaxTraversalDepth(unsigned int depth) - { _distAccumulator->setMaxDepth(depth); } - - inline unsigned int getMaxTraversalDepth() const - { return _distAccumulator->getMaxDepth(); } - - /** Override update and cull traversals */ - virtual void traverse(osg::NodeVisitor &nv); - - /** Catch child management functions so the Cameras can be informed - of added or removed children. */ - virtual bool addChild(osg::Node *child); - virtual bool insertChild(unsigned int index, osg::Node *child); - virtual bool removeChildren(unsigned int pos, unsigned int numRemove = 1); - virtual bool setChild(unsigned int i, osg::Node *node); - - protected: - typedef std::vector< osg::ref_ptr > CameraList; - - ~CURRENT_CLASS(); - - void init(); - - // Creates a new Camera object with default settings - osg::Camera* createOrReuseCamera(const osg::Matrix& proj, - double znear, double zfar, - const unsigned int &camNum); - - bool _active; // Whether partitioning is active on the scene - - // The NodeVisitor that computes cameras for the scene - osg::ref_ptr _distAccumulator; - - osg::Camera::RenderOrder _renderOrder; - bool _clearColorBuffer; - - // Cameras that should be used to draw the scene. These cameras - // will be reused on every frame in order to save time and memory. - CameraList _cameraList; - unsigned int _numCameras; // Number of Cameras actually being used -}; -#undef CURRENT_CLASS - -#endif diff --git a/examples/osgdepthpartition/DistanceAccumulator.cpp b/examples/osgdepthpartition/DistanceAccumulator.cpp deleted file mode 100644 index 04beea12b..000000000 --- a/examples/osgdepthpartition/DistanceAccumulator.cpp +++ /dev/null @@ -1,402 +0,0 @@ -/* OpenSceneGraph example, osgdepthpartion. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ - -#include "DistanceAccumulator.h" -#include -#include -#include -#include -#include -#include - -/** Function that sees whether one DistancePair should come before another in - an sorted list. Used to sort the vector of DistancePairs. */ -bool precedes(const DistanceAccumulator::DistancePair &a, - const DistanceAccumulator::DistancePair &b) -{ - // This results in sorting in order of descending far distances - if(a.second > b.second) return true; - else return false; -} - -/** Computes distance (in z direction) betwen a point and the viewer's eye, - given by a view matrix */ -double distance(const osg::Vec3 &coord, const osg::Matrix& matrix) -{ - // Here we are taking only the z coordinate of the point transformed - // by the matrix, ie coord*matrix. The negative sign is because we - // want to consider into the screen as INCREASING distance. - return -( coord[0]*matrix(0,2) + coord[1]*matrix(1,2) + - coord[2]*matrix(2,2) + matrix(3,2) ); -} - -#define CURRENT_CLASS DistanceAccumulator -CURRENT_CLASS::CURRENT_CLASS() - : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), - _nearFarRatio(0.0005), _maxDepth(UINT_MAX) -{ - setMatrices(osg::Matrix::identity(), osg::Matrix::identity()); - reset(); -} - -CURRENT_CLASS::~CURRENT_CLASS() {} - -void CURRENT_CLASS::pushLocalFrustum() -{ - osg::Matrix& currMatrix = _viewMatrices.back(); - - // Compute the frustum in local space - osg::Polytope localFrustum; - localFrustum.setToUnitFrustum(false, false); - localFrustum.transformProvidingInverse(currMatrix*_projectionMatrices.back()); - _localFrusta.push_back(localFrustum); - - // Compute new bounding box corners - bbCornerPair corner; - corner.second = (currMatrix(0,2)<=0?1:0) | - (currMatrix(1,2)<=0?2:0) | - (currMatrix(2,2)<=0?4:0); - corner.first = (~corner.second)&7; - _bbCorners.push_back(corner); -} - -void CURRENT_CLASS::pushDistancePair(double zNear, double zFar) -{ - if(zFar > 0.0) // Make sure some of drawable is visible - { - // Make sure near plane is in front of viewpoint. - if(zNear <= 0.0) - { - zNear = zFar*_nearFarRatio; - if(zNear >= 1.0) zNear = 1.0; // 1.0 limit chosen arbitrarily! - } - - // Add distance pair for current drawable - _distancePairs.push_back(DistancePair(zNear, zFar)); - - // Override the current nearest/farthest planes if necessary - if(zNear < _limits.first) _limits.first = zNear; - if(zFar > _limits.second) _limits.second = zFar; - } -} - -/** Return true if the node should be traversed, and false if the bounding sphere - of the node is small enough to be rendered by one Camera. If the latter - is true, then store the node's near & far plane distances. */ -bool CURRENT_CLASS::shouldContinueTraversal(osg::Node &node) -{ - // Allow traversal to continue if we haven't reached maximum depth. - bool keepTraversing = (_currentDepth < _maxDepth); - - osg::BoundingSphere bs = node.getBound(); - double zNear = 0.0, zFar = 0.0; - - // Make sure bounding sphere is valid - if(bs.valid()) - { - // Make sure bounding sphere is within the viewing volume - if(!_localFrusta.back().contains(bs)) keepTraversing = false; - - else // Compute near and far planes for this node - { - // Since the view matrix could involve complex transformations, - // we need to determine a new BoundingSphere that would encompass - // the transformed BoundingSphere. - const osg::Matrix &l2w = _viewMatrices.back(); - - // Get the transformed x-axis of the BoundingSphere - osg::Vec3d newX = bs._center; - newX.x() += bs._radius; // Get X-edge of bounding sphere - newX = newX * l2w; - - // Get the transformed y-axis of the BoundingSphere - osg::Vec3d newY = bs._center; - newY.y() += bs._radius; // Get Y-edge of bounding sphere - newY = newY * l2w; - - // Get the transformed z-axis of the BoundingSphere - osg::Vec3d newZ = bs._center; - newZ.z() += bs._radius; // Get Z-edge of bounding sphere - newZ = newZ * l2w; - - // Get the transformed center of the BoundingSphere - bs._center = bs._center * l2w; - - // Compute lengths of transformed x, y, and z axes - double newXLen = (newX - bs._center).length(); - double newYLen = (newY - bs._center).length(); - double newZLen = (newZ - bs._center).length(); - - // The encompassing radius is the max of the transformed lengths - bs._radius = newXLen; - if(newYLen > bs._radius) bs._radius = newYLen; - if(newZLen > bs._radius) bs._radius = newZLen; - - // Now we can compute the near & far planes, noting that for - // complex view transformations (ie. involving scales) the new - // BoundingSphere may be bigger than the original one. - // Note that the negative sign on the bounding sphere center is - // because we want distance to increase INTO the screen. - zNear = -bs._center.z() - bs._radius; - zFar = -bs._center.z() + bs._radius; - - // If near/far ratio is big enough, then we don't need to keep - // traversing children of this node. - if(zNear >= zFar*_nearFarRatio) keepTraversing = false; - } - } - - // If traversal should stop, then store this node's (near,far) pair - if(!keepTraversing) pushDistancePair(zNear, zFar); - - return keepTraversing; -} - -void CURRENT_CLASS::apply(osg::Node &node) -{ - if(shouldContinueTraversal(node)) - { - // Traverse this node - ++_currentDepth; - traverse(node); - --_currentDepth; - } -} - -void CURRENT_CLASS::apply(osg::Projection &proj) -{ - if(shouldContinueTraversal(proj)) - { - // Push the new projection matrix view frustum - _projectionMatrices.push_back(proj.getMatrix()); - pushLocalFrustum(); - - // Traverse the group - ++_currentDepth; - traverse(proj); - --_currentDepth; - - // Reload original matrix and frustum - _localFrusta.pop_back(); - _bbCorners.pop_back(); - _projectionMatrices.pop_back(); - } -} - -void CURRENT_CLASS::apply(osg::Transform &transform) -{ - if(shouldContinueTraversal(transform)) - { - // Compute transform for current node - osg::Matrix currMatrix = _viewMatrices.back(); - bool pushMatrix = transform.computeLocalToWorldMatrix(currMatrix, this); - - if(pushMatrix) - { - // Store the new modelview matrix and view frustum - _viewMatrices.push_back(currMatrix); - pushLocalFrustum(); - } - - ++_currentDepth; - traverse(transform); - --_currentDepth; - - if(pushMatrix) - { - // Restore the old modelview matrix and view frustum - _localFrusta.pop_back(); - _bbCorners.pop_back(); - _viewMatrices.pop_back(); - } - } -} - -void CURRENT_CLASS::apply(osg::Geode &geode) -{ - // Contained drawables will only be individually considered if we are - // allowed to continue traversing. - if(shouldContinueTraversal(geode)) - { - osg::Drawable *drawable; - double zNear, zFar; - - // Handle each drawable in this geode - for(unsigned int i = 0; i < geode.getNumDrawables(); ++i) - { - drawable = geode.getDrawable(i); - - const osg::BoundingBox &bb = drawable->getBound(); - if(bb.valid()) - { - // Make sure drawable will be visible in the scene - if(!_localFrusta.back().contains(bb)) continue; - - // Compute near/far distances for current drawable - zNear = distance(bb.corner(_bbCorners.back().first), - _viewMatrices.back()); - zFar = distance(bb.corner(_bbCorners.back().second), - _viewMatrices.back()); - if(zNear > zFar) std::swap(zNear, zFar); - pushDistancePair(zNear, zFar); - } - } - } -} - -void CURRENT_CLASS::setMatrices(const osg::Matrix &modelview, - const osg::Matrix &projection) -{ - _modelview = modelview; - _projection = projection; -} - -void CURRENT_CLASS::reset() -{ - // Clear vectors & values - _distancePairs.clear(); - _cameraPairs.clear(); - _limits.first = DBL_MAX; - _limits.second = 0.0; - _currentDepth = 0; - - // Initial transform matrix is the modelview matrix - _viewMatrices.clear(); - _viewMatrices.push_back(_modelview); - - // Set the initial projection matrix - _projectionMatrices.clear(); - _projectionMatrices.push_back(_projection); - - // Create a frustum without near/far planes, for cull computations - _localFrusta.clear(); - _bbCorners.clear(); - pushLocalFrustum(); -} - -void CURRENT_CLASS::computeCameraPairs() -{ - // Nothing in the scene, so no cameras needed - if(_distancePairs.empty()) return; - - // Entire scene can be handled by just one camera - if(_limits.first >= _limits.second*_nearFarRatio) - { - _cameraPairs.push_back(_limits); - return; - } - - PairList::iterator i,j; - - // Sort the list of distance pairs by descending far distance - std::sort(_distancePairs.begin(), _distancePairs.end(), precedes); - - // Combine overlapping distance pairs. The resulting set of distance - // pairs (called combined pairs) will not overlap. - PairList combinedPairs; - DistancePair currPair = _distancePairs.front(); - for(i = _distancePairs.begin(); i != _distancePairs.end(); ++i) - { - // Current distance pair does not overlap current combined pair, so - // save the current combined pair and start a new one. - if(i->second < 0.99*currPair.first) - { - combinedPairs.push_back(currPair); - currPair = *i; - } - - // Current distance pair overlaps current combined pair, so expand - // current combined pair to encompass distance pair. - else - currPair.first = std::min(i->first, currPair.first); - } - combinedPairs.push_back(currPair); // Add last pair - - // Compute the (near,far) distance pairs for each camera. - // Each of these distance pairs is called a "view segment". - double currNearLimit, numSegs, new_ratio; - double ratio_invlog = 1.0/log(_nearFarRatio); - unsigned int temp; - for(i = combinedPairs.begin(); i != combinedPairs.end(); ++i) - { - currPair = *i; // Save current view segment - - // Compute the fractional number of view segments needed to span - // the current combined distance pair. - currNearLimit = currPair.second*_nearFarRatio; - if(currPair.first >= currNearLimit) numSegs = 1.0; - else - { - numSegs = log(currPair.first/currPair.second)*ratio_invlog; - - // Compute the near plane of the last view segment - //currNearLimit *= pow(_nearFarRatio, -floor(-numSegs) - 1); - for(temp = (unsigned int)(-floor(-numSegs)); temp > 1; temp--) - { - currNearLimit *= _nearFarRatio; - } - } - - // See if the closest view segment can absorb other combined pairs - for(j = i+1; j != combinedPairs.end(); ++j) - { - // No other distance pairs can be included - if(j->first < currNearLimit) break; - } - - // If we did absorb another combined distance pair, recompute the - // number of required view segments. - if(i != j-1) - { - i = j-1; - currPair.first = i->first; - if(currPair.first >= currPair.second*_nearFarRatio) numSegs = 1.0; - else numSegs = log(currPair.first/currPair.second)*ratio_invlog; - } - - /* Compute an integer number of segments by rounding the fractional - number of segments according to how many segments there are. - In general, the more segments there are, the more likely that the - integer number of segments will be rounded down. - The purpose of this is to try to minimize the number of view segments - that are used to render any section of the scene without violating - the specified _nearFarRatio by too much. */ - if(numSegs < 10.0) numSegs = floor(numSegs + 1.0 - 0.1*floor(numSegs)); - else numSegs = floor(numSegs); - - - // Compute the near/far ratio that will be used for each view segment - // in this section of the scene. - new_ratio = pow(currPair.first/currPair.second, 1.0/numSegs); - - // Add numSegs new view segments to the camera pairs list - for(temp = (unsigned int)numSegs; temp > 0; temp--) - { - currPair.first = currPair.second*new_ratio; - _cameraPairs.push_back(currPair); - currPair.second = currPair.first; - } - } -} - -void CURRENT_CLASS::setNearFarRatio(double ratio) -{ - if(ratio <= 0.0 || ratio >= 1.0) return; - _nearFarRatio = ratio; -} -#undef CURRENT_CLASS diff --git a/examples/osgdepthpartition/DistanceAccumulator.h b/examples/osgdepthpartition/DistanceAccumulator.h deleted file mode 100644 index 33ca443d1..000000000 --- a/examples/osgdepthpartition/DistanceAccumulator.h +++ /dev/null @@ -1,115 +0,0 @@ -/* -*-c++-*- -* -* OpenSceneGraph example, osgdepthpartion. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ - -#ifndef _OF_DISTANCEACCUMULATOR_ -#define _OF_DISTANCEACCUMULATOR_ - -#include -#include -#include -#include - -#define CURRENT_CLASS DistanceAccumulator -/********************************************************** - * Ravi Mathur - * OpenFrames API, class DistanceAccumulator - * Class that traverses the scene and computes the distance to each - * visible drawable, and splits up the scene if the drawables are - * too far away (in the z direction) from each other. -**********************************************************/ -class CURRENT_CLASS : public osg::NodeVisitor -{ - public: - typedef std::pair DistancePair; - typedef std::vector PairList; - - CURRENT_CLASS(); - - virtual void apply(osg::Node &node); - virtual void apply(osg::Projection &proj); - virtual void apply(osg::Transform &transform); - virtual void apply(osg::Geode &geode); - - // Specify the modelview & projection matrices - void setMatrices(const osg::Matrix &modelview, - const osg::Matrix &projection); - - // Reset visitor before a new traversal - virtual void reset(); - - // Create a (near,far) distance pair for each camera of the specified - // distance pair list and distance limits. - void computeCameraPairs(); - - // Get info on the cameras that should be used for scene rendering - PairList& getCameraPairs() { return _cameraPairs; } - - // Get info on the computed distance pairs - PairList& getDistancePairs() { return _distancePairs; } - - // Get info on the computed nearest/farthest distances - DistancePair& getLimits() { return _limits; } - - // Set/get the desired near/far ratio - void setNearFarRatio(double ratio); - inline double getNearFarRatio() const { return _nearFarRatio; } - - inline void setMaxDepth(unsigned int depth) { _maxDepth = depth; } - inline unsigned int getMaxDepth() const { return _maxDepth; } - - protected: - virtual ~CURRENT_CLASS(); - - void pushLocalFrustum(); - void pushDistancePair(double zNear, double zFar); - bool shouldContinueTraversal(osg::Node &node); - - // Stack of matrices accumulated during traversal - osg::fast_back_stack _viewMatrices; - osg::fast_back_stack _projectionMatrices; - - // Main modelview/projection matrices - osg::Matrix _modelview, _projection; - - // The view frusta in local coordinate space - osg::fast_back_stack _localFrusta; - - // Bounding box corners that should be used for cull computation - typedef std::pair bbCornerPair; - osg::fast_back_stack _bbCorners; - - // Nar/far planes that should be used for each camera - PairList _cameraPairs; - - // Accumulated pairs of min/max distances - PairList _distancePairs; - - // The closest & farthest distances found while traversing - DistancePair _limits; - - // Ratio of nearest/farthest clip plane for each section of the scene - double _nearFarRatio; - - // Maximum depth to traverse to - unsigned int _maxDepth, _currentDepth; -}; -#undef CURRENT_CLASS - -#endif diff --git a/examples/osgdepthpartition/osgdepthpartition.cpp b/examples/osgdepthpartition/osgdepthpartition.cpp index 96641a295..3d18ed944 100644 --- a/examples/osgdepthpartition/osgdepthpartition.cpp +++ b/examples/osgdepthpartition/osgdepthpartition.cpp @@ -24,10 +24,10 @@ #include #include +#include #include - -#include "DepthPartitionNode.h" +#include const double r_earth = 6378.137; const double r_sun = 695990.0; @@ -132,6 +132,12 @@ int main( int argc, char **argv ) // construct the viewer. osgViewer::Viewer viewer; + // add the state manipulator + viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); + + // add stats + viewer.addEventHandler( new osgViewer::StatsHandler() ); + bool needToSetHomePosition = false; // read the scene from the list of file specified commandline args. @@ -143,24 +149,33 @@ int main( int argc, char **argv ) scene = createScene(); needToSetHomePosition = true; } - - // Create a DepthPartitionNode to manage partitioning of the scene - osg::ref_ptr dpn = new DepthPartitionNode; - dpn->addChild(scene.get()); - dpn->setActive(true); // Control whether the node analyzes the scene - // pass the loaded scene graph to the viewer. - viewer.setSceneData(dpn.get()); + viewer.setSceneData(scene.get()); viewer.setCameraManipulator(new osgGA::TrackballManipulator); if (needToSetHomePosition) { - viewer.getCameraManipulator()->setHomePosition(osg::Vec3d(0.0,-5.0*r_earth,0.0),osg::Vec3d(0.0,0.0,0.0),osg::Vec3d(0.0,0.0,1.0)); + viewer.getCameraManipulator()->setHomePosition(osg::Vec3d(0.0,-5.0*r_earth,0.0),osg::Vec3d(0.0,0.0,0.0),osg::Vec3d(0.0,0.0,1.0)); + } + + 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 osgViewer::DepthPartitionSettings; + dps->_mode = osgViewer::DepthPartitionSettings::FIXED_RANGE; + dps->_zNear = zNear; + dps->_zMid = zMid; + dps->_zFar = zFar; + viewer.setUpDepthPartition(dps.get()); + } + else + { + // set up depth partitioning with default settings + viewer.setUpDepthPartition(); } - // depth partion node is only supports single window/single threaded at present. - viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded); return viewer.run(); }