From Ravi Mathur, "New functionality is the ability to automatically determine the

maximum traversal depth necessary to obtain an accurate estimate of
the minimum number of required cameras.  In addition, the user can
specify an absolute maximum traversal depth that will not be exceeded."
This commit is contained in:
Robert Osfield 2005-10-27 09:38:06 +00:00
parent 0906851eeb
commit 601ac461a2
4 changed files with 145 additions and 81 deletions

View File

@ -1,6 +1,5 @@
#include "DepthPartitionNode.h"
#include <osgUtil/CullVisitor>
#include <iostream>
#define CURRENT_CLASS DepthPartitionNode
CURRENT_CLASS::CURRENT_CLASS()
@ -10,8 +9,7 @@ CURRENT_CLASS::CURRENT_CLASS()
}
CURRENT_CLASS::CURRENT_CLASS(const CURRENT_CLASS& dpn, const osg::CopyOp& copyop)
: osg::Group(dpn,copyop),
_active(dpn._active),
: _active(dpn._active),
_renderOrder(dpn._renderOrder),
_clearColorBuffer(dpn._clearColorBuffer)
{
@ -116,26 +114,17 @@ void CURRENT_CLASS::traverse(osg::NodeVisitor &nv)
osg::CameraNode *currCam;
DistanceAccumulator::DistancePair currPair;
for(unsigned int j = 0; j < _numCameras; j++)
for(i = 0; i < _numCameras; i++)
{
// Create the camera, and clamp it's projection matrix
currPair = camPairs[j]; // (near,far) pair for current camera
currPair = camPairs[i]; // (near,far) pair for current camera
currCam = createOrReuseCamera(projection, currPair.first,
currPair.second, j);
currPair.second, i);
// Set the modelview matrix and viewport of the camera
currCam->setViewMatrix(modelview);
currCam->setViewport(viewport);
/*
// Set our children as the camera's children
currCam->removeChild(0, currCam->getNumChildren());
for(i = 0; i < numChildren; i++)
{
currCam->addChild(_children[i].get());
}
*/
// Redirect the CullVisitor to the current camera
currCam->accept(nv);
}

View File

@ -37,11 +37,19 @@ class CURRENT_CLASS : public osg::Group
inline osg::CameraNode::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 CameraNodes can be informed
of new/removed children */
of added or removed children. */
virtual bool addChild(osg::Node *child);
virtual bool insertChild(unsigned int index, osg::Node *child);
virtual bool removeChild(osg::Node *child);

View File

@ -24,11 +24,11 @@ double distance(const osg::Vec3 &coord, const osg::Matrix& matrix)
#define CURRENT_CLASS DistanceAccumulator
CURRENT_CLASS::CURRENT_CLASS()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), _nearFarRatio(0.0)
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
_nearFarRatio(0.0005), _maxDepth(UINT_MAX)
{
setMatrices(osg::Matrix::identity(), osg::Matrix::identity());
reset();
setNearFarRatio(0.0005);
}
CURRENT_CLASS::~CURRENT_CLASS() {}
@ -44,97 +44,155 @@ void CURRENT_CLASS::pushLocalFrustum()
_localFrusta.push_back(localFrustum);
// Compute new bounding box corners
osg::Vec3d lookVector(-currMatrix(0,2), -currMatrix(1,2), -currMatrix(2,2));
bbCornerPair corner;
corner.second = (lookVector.x()>=0?1:0) |
(lookVector.y()>=0?2:0) |
(lookVector.z()>=0?4:0);
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::apply(osg::CameraNode& /*camera*/)
void CURRENT_CLASS::pushDistancePair(double zNear, double zFar)
{
// We don't support scenes with CameraNodes in them
return;
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 CameraNode. 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);
const osg::BoundingSphere &bs = node.getBound();
double zNear = 0.0, zFar = 0.0;
// Make sure bounding sphere is valid and within viewing volume
if(bs.valid())
{
if(!_localFrusta.back().contains(bs)) keepTraversing = false;
else
{
// Compute near and far planes for this node
zNear = distance(bs._center, _viewMatrices.back());
zFar = zNear + bs._radius;
zNear -= 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)
{
// Push the new projection matrix view frustum
_projectionMatrices.push_back(proj.getMatrix());
pushLocalFrustum();
if(shouldContinueTraversal(proj))
{
// Push the new projection matrix view frustum
_projectionMatrices.push_back(proj.getMatrix());
pushLocalFrustum();
traverse(proj); // Traverse the rest of the scene graph
// Traverse the group
_currentDepth++;
traverse(proj);
_currentDepth--;
// Reload original matrix and frustum
_localFrusta.pop_back();
_bbCorners.pop_back();
_projectionMatrices.pop_back();
// Reload original matrix and frustum
_localFrusta.pop_back();
_bbCorners.pop_back();
_projectionMatrices.pop_back();
}
}
void CURRENT_CLASS::apply(osg::Transform &transform)
{
// Compute transform for current node
osg::Matrix currMatrix = _viewMatrices.back();
bool pushMatrix = transform.computeLocalToWorldMatrix(currMatrix, this);
if(pushMatrix)
if(shouldContinueTraversal(transform))
{
// Store the new modelview matrix and view frustum
_viewMatrices.push_back(currMatrix);
pushLocalFrustum();
}
// Compute transform for current node
osg::Matrix currMatrix = _viewMatrices.back();
bool pushMatrix = transform.computeLocalToWorldMatrix(currMatrix, this);
traverse(transform); // Traverse the rest of the scene graph
if(pushMatrix)
{
// Store the new modelview matrix and view frustum
_viewMatrices.push_back(currMatrix);
pushLocalFrustum();
}
if(pushMatrix)
{
// Restore the old modelview matrix and view frustum
_localFrusta.pop_back();
_bbCorners.pop_back();
_viewMatrices.pop_back();
_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)
{
osg::Drawable *drawable;
double zNear, zFar;
// Handle each drawable in this geode
for(unsigned int i = 0; i < geode.getNumDrawables(); i++)
// Contained drawables will only be individually considered if we are
// allowed to continue traversing.
if(shouldContinueTraversal(geode))
{
drawable = geode.getDrawable(i);
osg::Drawable *drawable;
double zNear, zFar;
const osg::BoundingBox &bb = drawable->getBound();
if(bb.valid())
// Handle each drawable in this geode
for(unsigned int i = 0; i < geode.getNumDrawables(); i++)
{
// Make sure drawable will be visible in the scene
if(!_localFrusta.back().contains(bb)) continue;
drawable = geode.getDrawable(i);
// 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);
if(zFar > 0.0) // Make sure some of drawable is visible
const osg::BoundingBox &bb = drawable->getBound();
if(bb.valid())
{
// 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!
}
// Make sure drawable will be visible in the scene
if(!_localFrusta.back().contains(bb)) continue;
// Add distance pair for current drawable and current rendering mode
_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;
// 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);
}
}
}
@ -154,6 +212,7 @@ void CURRENT_CLASS::reset()
_cameraPairs.clear();
_limits.first = DBL_MAX;
_limits.second = 0.0;
_currentDepth = 0;
// Initial transform matrix is the modelview matrix
_viewMatrices.clear();
@ -276,7 +335,7 @@ void CURRENT_CLASS::computeCameraPairs()
void CURRENT_CLASS::setNearFarRatio(double ratio)
{
if(_nearFarRatio == ratio || ratio <= 0.0 || ratio >= 1.0) return;
if(ratio <= 0.0 || ratio >= 1.0) return;
_nearFarRatio = ratio;
}
#undef CURRENT_CLASS

View File

@ -22,7 +22,7 @@ class CURRENT_CLASS : public osg::NodeVisitor
CURRENT_CLASS();
virtual void apply(osg::CameraNode &camera);
virtual void apply(osg::Node &node);
virtual void apply(osg::Projection &proj);
virtual void apply(osg::Transform &transform);
virtual void apply(osg::Geode &geode);
@ -51,10 +51,15 @@ class CURRENT_CLASS : public osg::NodeVisitor
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<osg::Matrix> _viewMatrices;
@ -81,6 +86,9 @@ class CURRENT_CLASS : public osg::NodeVisitor
// 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