OpenSceneGraph/include/osg/CullStack
Robert Osfield f36bc69c58 Made the more of the OSG's referenced object desctructors protected to ensure
that they arn't created on the stack inappropriately.

Split the implemention of Matrix up so that it is a simple no referenced counted
class and can be safefly created on the stack.  To support referenced counting a
seperate subclass now exists, this is RefMatrix which inherits from both Matrix and
Object.
2003-01-10 09:25:42 +00:00

302 lines
9.4 KiB
Plaintext

//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.
#ifndef OSG_CULLSTACK
#define OSG_CULLSTACK 1
#include <osg/CullingSet>
#include <osg/Viewport>
#include <osg/fast_back_stack>
#include <osg/Notify>
namespace osg {
/** A CullStack class which accumulates the current project, modelview matrices
and the CullingSet. */
class SG_EXPORT CullStack
{
public:
CullStack();
~CullStack();
typedef std::vector<ShadowVolumeOccluder> OccluderList;
enum CullingModeValues
{
NO_CULLING = 0x0,
VIEW_FRUSTUM_CULLING = 0x1,
NEAR_PLANE_CULLING = 0x2,
FAR_PLANE_CULLING = 0x4,
SMALL_FEATURE_CULLING = 0x8,
SHADOW_OCCLUSION_CULLING = 0x10,
ENABLE_ALL_CULLING = VIEW_FRUSTUM_CULLING|
SMALL_FEATURE_CULLING|
SHADOW_OCCLUSION_CULLING
};
typedef unsigned int CullingMode;
void reset();
void setOccluderList(const ShadowVolumeOccluderList& svol) { _occluderList = svol; }
ShadowVolumeOccluderList& getOccluderList() { return _occluderList; }
const ShadowVolumeOccluderList& getOccluderList() const { return _occluderList; }
void pushViewport(osg::Viewport* viewport);
void popViewport();
void pushProjectionMatrix(osg::RefMatrix* matrix);
void popProjectionMatrix();
void pushModelViewMatrix(osg::RefMatrix* matrix);
void popModelViewMatrix();
inline float getFrustumVolume() { if (_frustumVolume<0.0f) computeFrustumVolume(); return _frustumVolume; }
/** Sets the current CullingMode.*/
void setCullingMode(CullingMode mode) { _cullingMode = mode; }
/** Returns the current CullingMode.*/
CullingMode getCullingMode() const { return _cullingMode; }
void setLODScale(float bias) { _LODScale = bias; }
float getLODScale() const { return _LODScale; }
void setSmallFeatureCullingPixelSize(float value) { _smallFeatureCullingPixelSize=value; }
float getSmallFeatureCullingPixelSize() const { return _smallFeatureCullingPixelSize; }
/** Compute the pixel of an object at position v, with specified radius.*/
float pixelSize(const Vec3& v,float radius) const
{
return _modelviewCullingStack.back()->pixelSize(v,radius);
}
/** Compute the pixel of an bounding sphere.*/
float pixelSize(const BoundingSphere& bs) const
{
return pixelSize(bs.center(),bs.radius());
}
inline void disableAndPushOccludersCurrentMask(NodePath& nodePath)
{
_modelviewCullingStack.back()->disableAndPushOccludersCurrentMask(nodePath);
}
inline void popOccludersCurrentMask(NodePath& nodePath)
{
_modelviewCullingStack.back()->popOccludersCurrentMask(nodePath);
}
inline bool isCulled(const std::vector<Vec3>& vertices)
{
return _modelviewCullingStack.back()->isCulled(vertices);
}
inline bool isCulled(const BoundingBox& bb)
{
return bb.valid() && _modelviewCullingStack.back()->isCulled(bb);
}
inline bool isCulled(const BoundingSphere& bs)
{
return _modelviewCullingStack.back()->isCulled(bs);
}
inline bool isCulled(const osg::Node& node)
{
return node.isCullingActive() && _modelviewCullingStack.back()->isCulled(node.getBound());
}
inline void pushCurrentMask()
{
_modelviewCullingStack.back()->pushCurrentMask();
}
inline void popCurrentMask()
{
_modelviewCullingStack.back()->popCurrentMask();
}
typedef fast_back_stack<ref_ptr<CullingSet> > CullingStack;
CullingStack& getClipSpaceCullingStack() { return _clipspaceCullingStack; }
CullingStack& getProjectionCullingStack() { return _projectionCullingStack; }
CullingStack& getModelViewCullingStack() { return _modelviewCullingStack; }
CullingSet& getCurrentCullingSet() { return *_modelviewCullingStack.back(); }
inline osg::Viewport* getViewport();
inline osg::RefMatrix& getModelViewMatrix();
inline osg::RefMatrix& getProjectionMatrix();
inline osg::Matrix getWindowMatrix();
inline const osg::RefMatrix& getMVPW();
inline const osg::Vec3& getEyeLocal() const { return _eyePointStack.back(); }
inline const osg::Vec3 getUpLocal() const
{
const osg::Matrix& matrix = *_modelviewStack.back();
return osg::Vec3(matrix(0,1),matrix(1,1),matrix(2,1));
}
inline const osg::Vec3 getLookVectorLocal() const
{
const osg::Matrix& matrix = *_modelviewStack.back();
return osg::Vec3(-matrix(0,2),-matrix(1,2),-matrix(2,2));
}
protected:
void pushCullingSet();
void popCullingSet();
CullingMode _cullingMode;
float _LODScale;
float _smallFeatureCullingPixelSize;
// base set of shadow volume occluder to use in culling.
ShadowVolumeOccluderList _occluderList;
typedef fast_back_stack< ref_ptr<RefMatrix> > MatrixStack;
MatrixStack _projectionStack;
MatrixStack _modelviewStack;
MatrixStack _MVPW_Stack;
typedef fast_back_stack<ref_ptr<Viewport> > ViewportStack;
ViewportStack _viewportStack;
typedef fast_back_stack<Vec3> EyePointStack;
EyePointStack _eyePointStack;
CullingStack _clipspaceCullingStack;
CullingStack _projectionCullingStack;
CullingStack _modelviewCullingStack;
void computeFrustumVolume();
float _frustumVolume;
unsigned int _bbCornerNear;
unsigned int _bbCornerFar;
ref_ptr<osg::RefMatrix> _identity;
typedef std::vector< osg::ref_ptr<osg::RefMatrix> > MatrixList;
MatrixList _reuseMatrixList;
unsigned int _currentReuseMatrixIndex;
inline osg::RefMatrix* createOrReuseMatrix(const osg::Matrix& value);
};
inline osg::Viewport* CullStack::getViewport()
{
if (!_viewportStack.empty())
{
return _viewportStack.back().get();
}
else
{
return 0L;
}
}
inline osg::RefMatrix& CullStack::getModelViewMatrix()
{
if (!_modelviewStack.empty())
{
return *_modelviewStack.back();
}
else
{
return *_identity;
}
}
inline osg::RefMatrix& CullStack::getProjectionMatrix()
{
if (!_projectionStack.empty())
{
return *_projectionStack.back();
}
else
{
return *_identity;
}
}
inline osg::Matrix CullStack::getWindowMatrix()
{
if (!_viewportStack.empty())
{
osg::Viewport* viewport = _viewportStack.back().get();
return viewport->computeWindowMatrix();
}
else
{
return *_identity;
}
}
inline const osg::RefMatrix& CullStack::getMVPW()
{
if (!_MVPW_Stack.empty())
{
if (!_MVPW_Stack.back())
{
_MVPW_Stack.back() = createOrReuseMatrix(getModelViewMatrix());
(*_MVPW_Stack.back()) *= getProjectionMatrix();
(*_MVPW_Stack.back()) *= getWindowMatrix();
}
return *_MVPW_Stack.back();
}
else
{
return *_identity;
}
}
inline RefMatrix* CullStack::createOrReuseMatrix(const osg::Matrix& value)
{
// skip of any already reused matrix.
while (_currentReuseMatrixIndex<_reuseMatrixList.size() &&
_reuseMatrixList[_currentReuseMatrixIndex]->referenceCount()>1)
{
notify(osg::NOTICE)<<"Warning:createOrReuseMatrix() skipping multiply refrenced entry."<< std::endl;
++_currentReuseMatrixIndex;
}
// if still within list, element must be singularly referenced
// there return it to be reused.
if (_currentReuseMatrixIndex<_reuseMatrixList.size())
{
RefMatrix* matrix = _reuseMatrixList[_currentReuseMatrixIndex++].get();
matrix->set(value);
return matrix;
}
// otherwise need to create new matrix.
osg::RefMatrix* matrix = new RefMatrix(value);
_reuseMatrixList.push_back(matrix);
++_currentReuseMatrixIndex;
return matrix;
}
} // end of namespace
#endif