You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OpenSceneGraph/include/osg/ShadowVolumeOccluder

173 lines
5.8 KiB

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#ifndef OSG_SHADOWVOLUMEOCCLUDER
#define OSG_SHADOWVOLUMEOCCLUDER 1
#include <osg/Polytope>
#include <osg/ConvexPlanarOccluder>
#include <osg/Node>
namespace osg {
class CullStack;
/** ShadowVolumeOccluder is a helper class for implementing shadow occlusion culling. */
class OSG_EXPORT ShadowVolumeOccluder
{
public:
typedef std::vector<Polytope> HoleList;
ShadowVolumeOccluder(const ShadowVolumeOccluder& svo):
_volume(svo._volume),
_nodePath(svo._nodePath),
_projectionMatrix(svo._projectionMatrix),
_occluderVolume(svo._occluderVolume),
_holeList(svo._holeList) {}
ShadowVolumeOccluder():
_volume(0.0f) {}
bool operator < (const ShadowVolumeOccluder& svo) const { return getVolume()>svo.getVolume(); } // not greater volume first.
/** compute the shadow volume occluder. */
bool computeOccluder(const NodePath& nodePath,const ConvexPlanarOccluder& occluder,CullStack& cullStack,bool createDrawables=false);
inline void disableResultMasks();
inline void pushCurrentMask();
inline void popCurrentMask();
/** return true if the matrix passed in matches the projection matrix that this ShadowVolumeOccluder is
* associated with.*/
bool matchProjectionMatrix(const osg::Matrix& matrix) const
{
if (_projectionMatrix.valid()) return matrix==*_projectionMatrix;
else return false;
}
/** Set the NodePath which describes which node in the scene graph
* that this occluder is attached to. */
inline void setNodePath(NodePath& nodePath) { _nodePath = nodePath; }
inline NodePath& getNodePath() { return _nodePath; }
inline const NodePath& getNodePath() const { return _nodePath; }
/** get the volume of the occluder minus its holes, in eye coords, the volume is normalized by dividing by
* the volume of the view frustum in eye coords.*/
float getVolume() const { return _volume; }
/** return the occluder polytope.*/
Polytope& getOccluder() { return _occluderVolume; }
/** return the const occluder polytope.*/
const Polytope& getOccluder() const { return _occluderVolume; }
/** return the list of holes.*/
HoleList& getHoleList() { return _holeList; }
/** return the const list of holes.*/
const HoleList& getHoleList() const { return _holeList; }
/** return true if the specified vertex list is contained entirely
* within this shadow occluder volume.*/
bool contains(const std::vector<Vec3>& vertices);
/** return true if the specified bounding sphere is contained entirely
* within this shadow occluder volume.*/
bool contains(const BoundingSphere& bound);
/** return true if the specified bounding box is contained entirely
* within this shadow occluder volume.*/
bool contains(const BoundingBox& bound);
inline void transformProvidingInverse(const osg::Matrix& matrix)
{
_occluderVolume.transformProvidingInverse(matrix);
for(HoleList::iterator itr=_holeList.begin();
itr!=_holeList.end();
++itr)
{
itr->transformProvidingInverse(matrix);
}
}
protected:
float _volume;
NodePath _nodePath;
ref_ptr<const RefMatrix> _projectionMatrix;
Polytope _occluderVolume;
HoleList _holeList;
};
/** A list of ShadowVolumeOccluder, used by CollectOccluderVisitor and CullVistor's.*/
typedef std::vector<ShadowVolumeOccluder> ShadowVolumeOccluderList;
inline void ShadowVolumeOccluder::disableResultMasks()
{
//std::cout<<"ShadowVolumeOccluder::disableResultMasks() - _occluderVolume.getMaskStack().size()="<<_occluderVolume.getMaskStack().size()<<" "<<_occluderVolume.getCurrentMask()<<std::endl;
_occluderVolume.setResultMask(0);
for(HoleList::iterator itr=_holeList.begin();
itr!=_holeList.end();
++itr)
{
itr->setResultMask(0);
}
}
inline void ShadowVolumeOccluder::pushCurrentMask()
{
//std::cout<<"ShadowVolumeOccluder::pushCurrentMasks() - _occluderVolume.getMaskStack().size()="<<_occluderVolume.getMaskStack().size()<<" "<<_occluderVolume.getCurrentMask()<<std::endl;
_occluderVolume.pushCurrentMask();
if (!_holeList.empty())
{
for(HoleList::iterator itr=_holeList.begin();
itr!=_holeList.end();
++itr)
{
itr->pushCurrentMask();
}
}
}
inline void ShadowVolumeOccluder::popCurrentMask()
{
_occluderVolume.popCurrentMask();
if (!_holeList.empty())
{
for(HoleList::iterator itr=_holeList.begin();
itr!=_holeList.end();
++itr)
{
itr->popCurrentMask();
}
}
//std::cout<<"ShadowVolumeOccluder::popCurrentMasks() - _occluderVolume.getMaskStack().size()="<<_occluderVolume.getMaskStack().size()<<" "<<_occluderVolume.getCurrentMask()<<std::endl;
}
} // end of namespace
#endif