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:
parent
0906851eeb
commit
601ac461a2
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user