OpenSceneGraph/include/osgUtil/CullVisitor

375 lines
13 KiB
Plaintext
Raw Normal View History

//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
2001-09-22 10:42:08 +08:00
#ifndef OSGUTIL_CULLVISITOR
#define OSGUTIL_CULLVISITOR 1
2001-09-20 05:19:47 +08:00
#include <osg/NodeVisitor>
#include <osg/BoundingSphere>
#include <osg/BoundingBox>
#include <osg/Matrix>
#include <osg/Drawable>
#include <osg/StateSet>
#include <osg/State>
#include <osg/Camera>
#include <osg/Impostor>
#include <osg/EarthSky>
2001-09-20 05:19:47 +08:00
#include <osg/Notify>
#include <osgUtil/RenderGraph>
#include <osgUtil/RenderStage>
#include <osgUtil/CullViewState>
#include <map>
#include <vector>
namespace osgUtil {
/**
* Basic NodeVisitor implementation for rendering a scene.
* This visitor traverses the scene graph, collecting transparent and
* opaque osg::Drawables into a depth sorted transparent bin and a state
* sorted opaque bin. The opaque bin is rendered first, and then the
* transparent bin in rendered in order from the furthest osg::Drawable
* from the eye to the one nearest the eye.
*/
class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor
{
public:
CullVisitor();
virtual ~CullVisitor();
2001-09-22 10:42:08 +08:00
virtual void reset();
2001-09-20 05:19:47 +08:00
virtual void apply(osg::Node&);
virtual void apply(osg::Geode& node);
virtual void apply(osg::Billboard& node);
virtual void apply(osg::LightSource& node);
virtual void apply(osg::Group& node);
virtual void apply(osg::Transform& node);
virtual void apply(osg::Switch& node);
virtual void apply(osg::LOD& node);
virtual void apply(osg::EarthSky& node);
2001-09-20 05:19:47 +08:00
virtual void apply(osg::Impostor& node);
void setCamera(const osg::Camera& camera);
2001-09-20 05:19:47 +08:00
const osg::Camera* getCamera() const { return _camera.get(); }
void setEarthSky(const osg::EarthSky* earthSky) { _earthSky = earthSky; }
const osg::EarthSky* getEarthSky() const { return _earthSky.get(); }
2001-09-20 05:19:47 +08:00
void setLODBias(const float bias) { _LODBias = bias; }
const float getLODBias() const { return _LODBias; }
/** Switch the creation of Impostors on or off.
* Setting active to false forces the CullVisitor to use the Impostor
* LOD children for rendering. Setting active to true forces the
* CullVisitor to create the appropriate pre-rendering stages which
* render to the ImpostorSprite's texture.*/
void setImpostorsActive(const bool active) { _impostorActive = active; }
/** Get whether impostors are active or not. */
const bool getImpostorsActive() const { return _impostorActive; }
/** Set the impostor error threshold.
* Used in calculation of whether impostors remain valid.*/
void setImpostorPixelErrorThreshold(const float numPixels) { _impostorPixelErrorThreshold=numPixels; }
/** Get the impostor error threshold.*/
const float getImpostorPixelErrorThreshold() const { return _impostorPixelErrorThreshold; }
/** Set whether ImpsotorSprite's should be placed in a depth sorted bin for rendering.*/
void setDepthSortImpostorSprites(const bool doDepthSort) { _depthSortImpostorSprites = doDepthSort; }
/** Get whether ImpsotorSprite's are depth sorted bin for rendering.*/
const bool setDepthSortImpostorSprites() const { return _depthSortImpostorSprites; }
/** Set the number of frames that an ImpsotorSprite's is kept whilst not being beyond,
* before being recycled.*/
void setNumberOfFrameToKeepImpostorSprites(const int numFrames) { _numFramesToKeepImpostorSprites = numFrames; }
/** Get the number of frames that an ImpsotorSprite's is kept whilst not being beyond,
* before being recycled.*/
const int getNumberOfFrameToKeepImpostorSprites() const { return _numFramesToKeepImpostorSprites; }
enum TransparencySortMode {
LOOK_VECTOR_DISTANCE,
OBJECT_EYE_POINT_DISTANCE
};
void setTransparencySortMode(TransparencySortMode tsm) { _tsm = tsm; }
/** Sets the current CullingMode.*/
void setCullingMode(CullViewState::CullingMode mode);
/** Returns the current CullingMode.*/
CullViewState::CullingMode getCullingMode() const;
2001-09-22 10:42:08 +08:00
2001-09-20 05:19:47 +08:00
/** Set the viewport.
* Used to enable the CullVisitor can make decision
2001-09-22 10:42:08 +08:00
* such as based on viewport dimensions.*/
void setViewport(osg::Viewport* viewport) { _viewport = viewport; }
2001-09-20 05:19:47 +08:00
2001-09-22 10:42:08 +08:00
/** Get the const viewport. */
const osg::Viewport* getViewport() const { return _viewport.get(); }
2001-09-20 05:19:47 +08:00
2001-09-22 10:42:08 +08:00
/** Get the viewport. */
osg::Viewport* getViewport() { return _viewport.get(); }
2001-09-20 05:19:47 +08:00
void pushCullViewState(const osg::Matrix* matrix=NULL);
void popCullViewState();
/** Push state set on the current state group.
* If the state exists in a child state group of the current
* state group then move the current state group to that child.
* Otherwise, create a new state group for the state set, add
* it to the current state group then move the current state
* group pointer to the new state group.
*/
inline void pushStateSet(const osg::StateSet* ss)
{
_currentRenderGraph = _currentRenderGraph->find_or_insert(ss);
if (ss->useRenderBinDetails())
{
_currentRenderBin = _currentRenderBin->find_or_insert(ss->getBinNumber(),ss->getBinName());
}
}
/** Pop the top state set and hence associated state group.
* Move the current state group to the parent of the popped
* state group.
*/
inline void popStateSet()
{
if (_currentRenderGraph->_stateset->useRenderBinDetails())
{
_currentRenderBin = _currentRenderBin->_parent;
}
_currentRenderGraph = _currentRenderGraph->_parent;
}
void setRenderGraph(RenderGraph* rg)
{
_rootRenderGraph = rg;
_currentRenderGraph = rg;
}
RenderGraph* getRenderGraph()
{
return _rootRenderGraph.get();
}
void setRenderStage(RenderStage* rg)
{
_rootRenderStage = rg;
_currentRenderBin = rg;
}
RenderStage* getRenderStage()
{
return _rootRenderStage.get();
}
const float getCalculatedNearPlane() const { return _calculated_znear; }
const float getCalculatedFarPlane() const { return _calculated_zfar; }
protected:
/** prevent unwanted copy construction.*/
CullVisitor(const CullVisitor&):osg::NodeVisitor() {}
/** prevent unwanted copy operator.*/
CullVisitor& operator = (const CullVisitor&) { return *this; }
inline osg::Matrix* getCurrentMatrix()
{
return _cvs->_matrix.get();
}
inline osg::Matrix* getInverseCurrentMatrix()
{
return _cvs->_inverse.get();
}
inline const osg::Vec3& getEyeLocal() const
{
return _cvs->_eyePoint;
}
inline const osg::Vec3& getCenterLocal() const
{
return _cvs->_centerPoint;
}
inline const osg::Vec3& getLookVectorLocal() const
{
return _cvs->_lookVector;
}
inline bool isCulled(const osg::BoundingSphere& sp,CullViewState::CullingMode& mode) const
{
return _cvs->isCulled(sp,mode);
}
inline const bool isCulled(const osg::BoundingBox& bb,const CullViewState::CullingMode mode) const
{
return _cvs->isCulled(bb,mode);
}
void updateCalculatedNearFar(const osg::BoundingBox& bb);
void updateCalculatedNearFar(const osg::Vec3& pos);
/** Add a drawable to current render graph.*/
inline void addDrawable(osg::Drawable* drawable,osg::Matrix* matrix)
{
if (_currentRenderGraph->leaves_empty())
{
// this is first leaf to be added to RenderGraph
// and therefore should not already know to current render bin,
// so need to add it.
_currentRenderBin->addRenderGraph(_currentRenderGraph);
}
//_currentRenderGraph->addLeaf(new RenderLeaf(drawable,matrix));
_currentRenderGraph->addLeaf(createOrReuseRenderLeaf(drawable,matrix));
}
/** Add a drawable and depth to current render graph.*/
inline void addDrawableAndDepth(osg::Drawable* drawable,osg::Matrix* matrix,const float depth)
{
if (_currentRenderGraph->leaves_empty())
{
// this is first leaf to be added to RenderGraph
// and therefore should not already know to current render bin,
// so need to add it.
_currentRenderBin->addRenderGraph(_currentRenderGraph);
}
//_currentRenderGraph->addLeaf(new RenderLeaf(drawable,matrix,depth));
_currentRenderGraph->addLeaf(createOrReuseRenderLeaf(drawable,matrix,depth));
}
/** Add a light to current render graph.*/
inline void addLight(osg::Light* light,osg::Matrix* matrix)
{
_currentRenderBin->_stage->addLight(light,matrix);
}
/** create an impostor sprite by setting up a pre-rendering stage
* to generate the impostor texture. */
osg::ImpostorSprite* createImpostorSprite(osg::Impostor& node);
typedef std::vector< osg::ref_ptr<CullViewState> > CullViewStateStack;
CullViewStateStack _viewStateStack;
osg::ref_ptr<CullViewState> _tvs;
osg::ref_ptr<CullViewState> _cvs;
osg::ref_ptr<RenderGraph> _rootRenderGraph;
RenderGraph* _currentRenderGraph;
osg::ref_ptr<RenderStage> _rootRenderStage;
RenderBin* _currentRenderBin;
std::vector<CullViewState::CullingMode> _cullingModeStack;
float _LODBias;
float _calculated_znear;
float _calculated_zfar;
osg::ref_ptr<const osg::Camera> _camera;
osg::ref_ptr<const osg::EarthSky> _earthSky;
2001-09-20 05:19:47 +08:00
TransparencySortMode _tsm;
2001-09-28 20:36:40 +08:00
// viewport x,y,width,height respectively.
2001-09-22 10:42:08 +08:00
osg::ref_ptr<osg::Viewport> _viewport;
2001-09-20 05:19:47 +08:00
bool _impostorActive;
bool _depthSortImpostorSprites;
float _impostorPixelErrorThreshold;
int _numFramesToKeepImpostorSprites;
typedef std::vector< osg::ref_ptr<osg::Matrix> > MatrixList;
MatrixList _reuseMatrixList;
unsigned int _currentReuseMatrixIndex;
inline osg::Matrix* createOrReuseMatrix()
{
// skip of any already reused matrix.
while (_currentReuseMatrixIndex<_reuseMatrixList.size() &&
_reuseMatrixList[_currentReuseMatrixIndex]->referenceCount()>1)
{
osg::notify(osg::NOTICE)<<"Warning:createOrReuseMatrix() skipping multiply refrenced entry."<<endl;
++_currentReuseMatrixIndex;
}
2001-09-28 20:36:40 +08:00
// if still within list, element must be singularly referenced
2001-09-20 05:19:47 +08:00
// there return it to be reused.
if (_currentReuseMatrixIndex<_reuseMatrixList.size())
{
osg::Matrix* matrix = _reuseMatrixList[_currentReuseMatrixIndex++].get();
matrix->makeIdent();
return matrix;
}
// otherwise need to create new matrix.
osg::Matrix* matrix = new osg::Matrix();
_reuseMatrixList.push_back(matrix);
++_currentReuseMatrixIndex;
return matrix;
}
typedef std::vector< osg::ref_ptr<RenderLeaf> > RenderLeafList;
RenderLeafList _reuseRenderLeafList;
unsigned int _currentReuseRenderLeafIndex;
inline RenderLeaf* createOrReuseRenderLeaf(osg::Drawable* drawable,osg::Matrix* matrix, float depth=0.0f)
{
// skip of any already reused renderleaf.
while (_currentReuseRenderLeafIndex<_reuseRenderLeafList.size() &&
_reuseRenderLeafList[_currentReuseRenderLeafIndex]->referenceCount()>1)
{
osg::notify(osg::NOTICE)<<"Warning:createOrReuseRenderLeaf() skipping multiply refrenced entry."<<endl;
++_currentReuseRenderLeafIndex;
}
2001-09-28 20:36:40 +08:00
// if still within list, element must be singularly referenced
2001-09-20 05:19:47 +08:00
// there return it to be reused.
if (_currentReuseRenderLeafIndex<_reuseRenderLeafList.size())
{
RenderLeaf* renderleaf = _reuseRenderLeafList[_currentReuseRenderLeafIndex++].get();
renderleaf->set(drawable,matrix,depth);
return renderleaf;
}
// otherwise need to create new renderleaf.
RenderLeaf* renderleaf = new RenderLeaf(drawable,matrix,depth);
_reuseRenderLeafList.push_back(renderleaf);
++_currentReuseRenderLeafIndex;
return renderleaf;
}
osg::ref_ptr<osg::ImpostorSpriteManager> _impostorSpriteManager;
};
};
#endif