Simplified the osgdepthpartion example to use the osgView::View::setUpDepthPartition(..) feature
This commit is contained in:
parent
9aa7010ded
commit
ccfac57f20
@ -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)
|
||||
|
@ -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 <osgUtil/CullVisitor>
|
||||
|
||||
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<osgUtil::CullVisitor*>(&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
|
@ -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 <osg/Camera>
|
||||
|
||||
#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<osg::Camera> > 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<DistanceAccumulator> _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
|
@ -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 <osg/Geode>
|
||||
#include <osg/Transform>
|
||||
#include <osg/Projection>
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
/** 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
|
@ -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 <osg/Group>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/Polytope>
|
||||
#include <osg/fast_back_stack>
|
||||
|
||||
#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<double, double> DistancePair;
|
||||
typedef std::vector<DistancePair> 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<osg::Matrix> _viewMatrices;
|
||||
osg::fast_back_stack<osg::Matrix> _projectionMatrices;
|
||||
|
||||
// Main modelview/projection matrices
|
||||
osg::Matrix _modelview, _projection;
|
||||
|
||||
// The view frusta in local coordinate space
|
||||
osg::fast_back_stack<osg::Polytope> _localFrusta;
|
||||
|
||||
// Bounding box corners that should be used for cull computation
|
||||
typedef std::pair<unsigned int, unsigned int> bbCornerPair;
|
||||
osg::fast_back_stack<bbCornerPair> _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
|
@ -24,10 +24,10 @@
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osgGA/StateSetManipulator>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
#include "DepthPartitionNode.h"
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
|
||||
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<DepthPartitionNode> 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<osgViewer::DepthPartitionSettings> 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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user