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 "DepthPartitionNode.h"
#include <osgUtil/CullVisitor> #include <osgUtil/CullVisitor>
#include <iostream>
#define CURRENT_CLASS DepthPartitionNode #define CURRENT_CLASS DepthPartitionNode
CURRENT_CLASS::CURRENT_CLASS() CURRENT_CLASS::CURRENT_CLASS()
@ -10,8 +9,7 @@ CURRENT_CLASS::CURRENT_CLASS()
} }
CURRENT_CLASS::CURRENT_CLASS(const CURRENT_CLASS& dpn, const osg::CopyOp& copyop) 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), _renderOrder(dpn._renderOrder),
_clearColorBuffer(dpn._clearColorBuffer) _clearColorBuffer(dpn._clearColorBuffer)
{ {
@ -116,26 +114,17 @@ void CURRENT_CLASS::traverse(osg::NodeVisitor &nv)
osg::CameraNode *currCam; osg::CameraNode *currCam;
DistanceAccumulator::DistancePair currPair; 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 // 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, currCam = createOrReuseCamera(projection, currPair.first,
currPair.second, j); currPair.second, i);
// Set the modelview matrix and viewport of the camera // Set the modelview matrix and viewport of the camera
currCam->setViewMatrix(modelview); currCam->setViewMatrix(modelview);
currCam->setViewport(viewport); 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 // Redirect the CullVisitor to the current camera
currCam->accept(nv); currCam->accept(nv);
} }

View File

@ -37,11 +37,19 @@ class CURRENT_CLASS : public osg::Group
inline osg::CameraNode::RenderOrder getRenderOrder() const inline osg::CameraNode::RenderOrder getRenderOrder() const
{ return _renderOrder; } { 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 */ /** Override update and cull traversals */
virtual void traverse(osg::NodeVisitor &nv); virtual void traverse(osg::NodeVisitor &nv);
/** Catch child management functions so the CameraNodes can be informed /** 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 addChild(osg::Node *child);
virtual bool insertChild(unsigned int index, osg::Node *child); virtual bool insertChild(unsigned int index, osg::Node *child);
virtual bool removeChild(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 #define CURRENT_CLASS DistanceAccumulator
CURRENT_CLASS::CURRENT_CLASS() 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()); setMatrices(osg::Matrix::identity(), osg::Matrix::identity());
reset(); reset();
setNearFarRatio(0.0005);
} }
CURRENT_CLASS::~CURRENT_CLASS() {} CURRENT_CLASS::~CURRENT_CLASS() {}
@ -44,97 +44,155 @@ void CURRENT_CLASS::pushLocalFrustum()
_localFrusta.push_back(localFrustum); _localFrusta.push_back(localFrustum);
// Compute new bounding box corners // Compute new bounding box corners
osg::Vec3d lookVector(-currMatrix(0,2), -currMatrix(1,2), -currMatrix(2,2));
bbCornerPair corner; bbCornerPair corner;
corner.second = (lookVector.x()>=0?1:0) | corner.second = (currMatrix(0,2)<=0?1:0) |
(lookVector.y()>=0?2:0) | (currMatrix(1,2)<=0?2:0) |
(lookVector.z()>=0?4:0); (currMatrix(2,2)<=0?4:0);
corner.first = (~corner.second)&7; corner.first = (~corner.second)&7;
_bbCorners.push_back(corner); _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 if(zFar > 0.0) // Make sure some of drawable is visible
return; {
// 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) void CURRENT_CLASS::apply(osg::Projection &proj)
{ {
// Push the new projection matrix view frustum if(shouldContinueTraversal(proj))
_projectionMatrices.push_back(proj.getMatrix()); {
pushLocalFrustum(); // 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 // Reload original matrix and frustum
_localFrusta.pop_back(); _localFrusta.pop_back();
_bbCorners.pop_back(); _bbCorners.pop_back();
_projectionMatrices.pop_back(); _projectionMatrices.pop_back();
}
} }
void CURRENT_CLASS::apply(osg::Transform &transform) void CURRENT_CLASS::apply(osg::Transform &transform)
{ {
// Compute transform for current node if(shouldContinueTraversal(transform))
osg::Matrix currMatrix = _viewMatrices.back();
bool pushMatrix = transform.computeLocalToWorldMatrix(currMatrix, this);
if(pushMatrix)
{ {
// Store the new modelview matrix and view frustum // Compute transform for current node
_viewMatrices.push_back(currMatrix); osg::Matrix currMatrix = _viewMatrices.back();
pushLocalFrustum(); 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) _currentDepth++;
{ traverse(transform);
// Restore the old modelview matrix and view frustum _currentDepth--;
_localFrusta.pop_back();
_bbCorners.pop_back(); if(pushMatrix)
_viewMatrices.pop_back(); {
// Restore the old modelview matrix and view frustum
_localFrusta.pop_back();
_bbCorners.pop_back();
_viewMatrices.pop_back();
}
} }
} }
void CURRENT_CLASS::apply(osg::Geode &geode) void CURRENT_CLASS::apply(osg::Geode &geode)
{ {
osg::Drawable *drawable; // Contained drawables will only be individually considered if we are
double zNear, zFar; // allowed to continue traversing.
if(shouldContinueTraversal(geode))
// Handle each drawable in this geode
for(unsigned int i = 0; i < geode.getNumDrawables(); i++)
{ {
drawable = geode.getDrawable(i); osg::Drawable *drawable;
double zNear, zFar;
const osg::BoundingBox &bb = drawable->getBound(); // Handle each drawable in this geode
if(bb.valid()) for(unsigned int i = 0; i < geode.getNumDrawables(); i++)
{ {
// Make sure drawable will be visible in the scene drawable = geode.getDrawable(i);
if(!_localFrusta.back().contains(bb)) continue;
// Compute near/far distances for current drawable const osg::BoundingBox &bb = drawable->getBound();
zNear = distance(bb.corner(_bbCorners.back().first), if(bb.valid())
_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
{ {
// Make sure near plane is in front of viewpoint. // Make sure drawable will be visible in the scene
if(zNear <= 0.0) if(!_localFrusta.back().contains(bb)) continue;
{
zNear = zFar*_nearFarRatio;
if(zNear >= 1.0) zNear = 1.0; // 1.0 limit chosen arbitrarily!
}
// Add distance pair for current drawable and current rendering mode // Compute near/far distances for current drawable
_distancePairs.push_back(DistancePair(zNear, zFar)); zNear = distance(bb.corner(_bbCorners.back().first),
_viewMatrices.back());
// Override the current nearest/farthest planes if necessary zFar = distance(bb.corner(_bbCorners.back().second),
if(zNear < _limits.first) _limits.first = zNear; _viewMatrices.back());
if(zFar > _limits.second) _limits.second = zFar; if(zNear > zFar) std::swap(zNear, zFar);
pushDistancePair(zNear, zFar);
} }
} }
} }
@ -154,6 +212,7 @@ void CURRENT_CLASS::reset()
_cameraPairs.clear(); _cameraPairs.clear();
_limits.first = DBL_MAX; _limits.first = DBL_MAX;
_limits.second = 0.0; _limits.second = 0.0;
_currentDepth = 0;
// Initial transform matrix is the modelview matrix // Initial transform matrix is the modelview matrix
_viewMatrices.clear(); _viewMatrices.clear();
@ -276,7 +335,7 @@ void CURRENT_CLASS::computeCameraPairs()
void CURRENT_CLASS::setNearFarRatio(double ratio) 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; _nearFarRatio = ratio;
} }
#undef CURRENT_CLASS #undef CURRENT_CLASS

View File

@ -22,7 +22,7 @@ class CURRENT_CLASS : public osg::NodeVisitor
CURRENT_CLASS(); CURRENT_CLASS();
virtual void apply(osg::CameraNode &camera); virtual void apply(osg::Node &node);
virtual void apply(osg::Projection &proj); virtual void apply(osg::Projection &proj);
virtual void apply(osg::Transform &transform); virtual void apply(osg::Transform &transform);
virtual void apply(osg::Geode &geode); virtual void apply(osg::Geode &geode);
@ -51,10 +51,15 @@ class CURRENT_CLASS : public osg::NodeVisitor
void setNearFarRatio(double ratio); void setNearFarRatio(double ratio);
inline double getNearFarRatio() const { return _nearFarRatio; } inline double getNearFarRatio() const { return _nearFarRatio; }
inline void setMaxDepth(unsigned int depth) { _maxDepth = depth; }
inline unsigned int getMaxDepth() const { return _maxDepth; }
protected: protected:
virtual ~CURRENT_CLASS(); virtual ~CURRENT_CLASS();
void pushLocalFrustum(); void pushLocalFrustum();
void pushDistancePair(double zNear, double zFar);
bool shouldContinueTraversal(osg::Node &node);
// Stack of matrices accumulated during traversal // Stack of matrices accumulated during traversal
osg::fast_back_stack<osg::Matrix> _viewMatrices; 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 // Ratio of nearest/farthest clip plane for each section of the scene
double _nearFarRatio; double _nearFarRatio;
// Maximum depth to traverse to
unsigned int _maxDepth, _currentDepth;
}; };
#undef CURRENT_CLASS #undef CURRENT_CLASS