/* -*-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 #include #include namespace osg { class CullStack; /** ShadowVolumeOccluder is a helper class for implementing shadow occlusion culling. */ class OSG_EXPORT ShadowVolumeOccluder { public: typedef std::vector 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& 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 _projectionMatrix; Polytope _occluderVolume; HoleList _holeList; }; /** A list of ShadowVolumeOccluder, used by CollectOccluderVisitor and CullVistor's.*/ typedef std::vector ShadowVolumeOccluderList; inline void ShadowVolumeOccluder::disableResultMasks() { //std::cout<<"ShadowVolumeOccluder::disableResultMasks() - _occluderVolume.getMaskStack().size()="<<_occluderVolume.getMaskStack().size()<<" "<<_occluderVolume.getCurrentMask()<setResultMask(0); } } inline void ShadowVolumeOccluder::pushCurrentMask() { //std::cout<<"ShadowVolumeOccluder::pushCurrentMasks() - _occluderVolume.getMaskStack().size()="<<_occluderVolume.getMaskStack().size()<<" "<<_occluderVolume.getCurrentMask()<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()<