From 5e85cd59ab2e4e2ec98b250df645f0bb326a0884 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 18 Jun 2002 22:35:48 +0000 Subject: [PATCH] Added support for occluders occluding other occluders, which helps reduce the number of occluder that will be used in cull traversal to only the ones that will be effective. Note. Holes in occluders arn't handled in this occluder occlusion test, will implement this later. --- include/osg/CollectOccludersVisitor | 15 ++++++++--- include/osg/Polytope | 20 +++++++++++--- include/osg/ShadowVolumeOccluder | 4 ++- src/osg/CollectOccludersVisitor.cpp | 41 ++++++++++++++++++++++++++++- src/osg/ShadowVolumeOccluder.cpp | 41 ++++++++++++++++------------- src/osgUtil/SceneView.cpp | 9 +++++-- 6 files changed, 99 insertions(+), 31 deletions(-) diff --git a/include/osg/CollectOccludersVisitor b/include/osg/CollectOccludersVisitor index 29455edbd..0496e6ed5 100644 --- a/include/osg/CollectOccludersVisitor +++ b/include/osg/CollectOccludersVisitor @@ -8,6 +8,8 @@ #include #include +#include + namespace osg { class SG_EXPORT CollectOccludersVisitor : public osg::NodeVisitor, public osg::CullStack @@ -15,6 +17,8 @@ class SG_EXPORT CollectOccludersVisitor : public osg::NodeVisitor, public osg::C public: + typedef std::set ShadowVolumeOccluderSet; + CollectOccludersVisitor(); virtual ~CollectOccludersVisitor(); @@ -37,9 +41,12 @@ class SG_EXPORT CollectOccludersVisitor : public osg::NodeVisitor, public osg::C void setCreateDrawablesOnOccludeNodes(bool flag) { _createDrawables=flag; } bool getCreateDrawablesOnOccludeNodes() const { return _createDrawables; } - void setCollectedOcculderList(const ShadowVolumeOccluderList& svol) { _occluderList = svol; } - ShadowVolumeOccluderList& getCollectedOccluderList() { return _occluderList; } - const ShadowVolumeOccluderList& getCollectedOccluderList() const { return _occluderList; } + void setCollectedOcculderList(const ShadowVolumeOccluderSet& svol) { _occluderSet = svol; } + ShadowVolumeOccluderSet& getCollectedOccluderSet() { return _occluderSet; } + const ShadowVolumeOccluderSet& getCollectedOccluderSet() const { return _occluderSet; } + + /** remove occluded occluders for the collected occluders list.*/ + void removeOccludedOccluders(); protected: @@ -66,7 +73,7 @@ class SG_EXPORT CollectOccludersVisitor : public osg::NodeVisitor, public osg::C float _minimumShadowOccluderVolume; bool _createDrawables; - ShadowVolumeOccluderList _collectedOccluderList; + ShadowVolumeOccluderSet _occluderSet; }; diff --git a/include/osg/Polytope b/include/osg/Polytope index cf2c29ab3..201deef07 100644 --- a/include/osg/Polytope +++ b/include/osg/Polytope @@ -18,16 +18,18 @@ class SG_EXPORT Polytope public: - typedef unsigned int ClippingMask; - typedef std::vector PlaneList; - typedef fast_back_stack MaskStack; + typedef unsigned int ClippingMask; + typedef std::vector PlaneList; + typedef std::vector VertexList; + typedef fast_back_stack MaskStack; inline Polytope() {setupMask();} inline Polytope(const Polytope& cv) : _maskStack(cv._maskStack), _resultMask(cv._resultMask), - _planeList(cv._planeList) {} + _planeList(cv._planeList), + _referenceVertexList(cv._referenceVertexList) {} inline Polytope(const PlaneList& pl) : _planeList(pl) {setupMask();} @@ -41,6 +43,7 @@ class SG_EXPORT Polytope _maskStack = cv._maskStack; _resultMask = cv._resultMask; _planeList = cv._planeList; + _referenceVertexList = cv._referenceVertexList; return *this; } @@ -77,6 +80,14 @@ class SG_EXPORT Polytope inline const PlaneList& getPlaneList() const { return _planeList; } + + inline void setReferenceVertexList(VertexList& vertices) { _referenceVertexList=vertices; } + + inline VertexList& getReferenceVertexList() { return _referenceVertexList; } + + inline const VertexList& getReferenceVertexList() const { return _referenceVertexList; } + + inline void setupMask() { _resultMask = 0; @@ -312,6 +323,7 @@ class SG_EXPORT Polytope MaskStack _maskStack; ClippingMask _resultMask; PlaneList _planeList; + VertexList _referenceVertexList; }; diff --git a/include/osg/ShadowVolumeOccluder b/include/osg/ShadowVolumeOccluder index 6aa213090..ad59fcf06 100644 --- a/include/osg/ShadowVolumeOccluder +++ b/include/osg/ShadowVolumeOccluder @@ -33,6 +33,8 @@ class SG_EXPORT 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 ConvexPlanerOccluder& occluder,CullStack& cullStack,bool createDrawables=false); @@ -86,7 +88,7 @@ class SG_EXPORT ShadowVolumeOccluder } - protected: +// protected: float _volume; NodePath _nodePath; diff --git a/src/osg/CollectOccludersVisitor.cpp b/src/osg/CollectOccludersVisitor.cpp index 787198c38..846386c64 100644 --- a/src/osg/CollectOccludersVisitor.cpp +++ b/src/osg/CollectOccludersVisitor.cpp @@ -5,6 +5,8 @@ #include #include +#include + using namespace osg; CollectOccludersVisitor::CollectOccludersVisitor() @@ -137,7 +139,7 @@ void CollectOccludersVisitor::apply(osg::OccluderNode& node) { // need to test occluder against view frustum. //std::cout << " adding in Occluder"<(&(*occluderItr)); + if (occluder->contains(occludee._occluderVolume.getReferenceVertexList())) + { + // erase occluder from set. + // take a copy of the iterator then rewind it one element so to prevent invalidating the occludeeItr. + ShadowVolumeOccluderSet::iterator eraseItr = occludeeItr--; + _occluderSet.erase(eraseItr); + break; + } + } + } +} diff --git a/src/osg/ShadowVolumeOccluder.cpp b/src/osg/ShadowVolumeOccluder.cpp index 5006eb451..4688db293 100644 --- a/src/osg/ShadowVolumeOccluder.cpp +++ b/src/osg/ShadowVolumeOccluder.cpp @@ -14,8 +14,8 @@ typedef std::vector PointList; typedef std::vector VertexList; -// convert a vector for Vec3 into a vector of Point's. -void convert(const VertexList& in,PointList& out) +// copyVertexListToPointList a vector for Vec3 into a vector of Point's. +void copyVertexListToPointList(const VertexList& in,PointList& out) { out.reserve(in.size()); for(VertexList::const_iterator itr=in.begin(); @@ -26,6 +26,17 @@ void convert(const VertexList& in,PointList& out) } } +void copyPointListToVertexList(const PointList& in,VertexList& out) +{ + out.reserve(in.size()); + for(PointList::const_iterator itr=in.begin(); + itr!=in.end(); + ++itr) + { + out.push_back(itr->second); + } +} + // clip the convex hull 'in' to plane to generate a clipped convex hull 'out' // return true if points remain after clipping. unsigned int clip(const Plane& plane,const PointList& in, PointList& out,unsigned int planeMask) @@ -74,7 +85,7 @@ unsigned int clip(const Plane& plane,const PointList& in, PointList& out,unsigne unsigned int clip(const Polytope::PlaneList& planeList,const VertexList& vin,PointList& out) { PointList in; - convert(vin,in); + copyVertexListToPointList(vin,in); unsigned int planeMask = 0x1; for(Polytope::PlaneList::const_iterator itr=planeList.begin(); @@ -138,22 +149,6 @@ Plane computeFrontPlane(const PointList& front) return Plane(front[2].second,front[1].second,front[0].second); } - -// // compute the volume of tetrahedron -// inline float computeVolume(const osg::Vec3& a,const osg::Vec3& b,const osg::Vec3& c,const osg::Vec3& d) -// { -// return fabs(((b-c)^(a-b))*(d-b)); -// } -// -// // compute the volume of prism. -// inline float computeVolume(const osg::Vec3& f1,const osg::Vec3& f2,const osg::Vec3& f3, -// const osg::Vec3& b1,const osg::Vec3& b2,const osg::Vec3& b3) -// { -// return computeVolume(f1,f2,f3,b1)+ -// computeVolume(b1,b2,b3,f2)+ -// computeVolume(b1,b3,f2,f3); -// } - // compute the volume between the front and back polygons of the occluder/hole. float computePolytopeVolume(const PointList& front, const PointList& back) { @@ -275,6 +270,10 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex // move the occlude points into projection space. transform(points,MV); + // use the points on the front plane as reference vertices on the _occluderVolume + // so that the vertices can later by used to test for occlusion of the occluder itself. + copyPointListToVertexList(points,_occluderVolume.getReferenceVertexList()); + // create the front face of the occluder Plane occludePlane = computeFrontPlane(points); _occluderVolume.add(occludePlane); @@ -331,6 +330,10 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex // move the occlude points into projection space. transform(points,MV); + // use the points on the front plane as reference vertices on the _occluderVolume + // so that the vertices can later by used to test for occlusion of the occluder itself. + copyPointListToVertexList(points,polytope.getReferenceVertexList()); + // create the front face of the occluder Plane occludePlane = computeFrontPlane(points); diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index dd37dbbfd..bef5e32ab 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -341,9 +341,14 @@ void SceneView::cullStage(osg::Matrix* projection,osg::Matrix* modelview,osgUtil cov.popProjectionMatrix(); cov.popViewport(); - //std::cout << "finished searching for occluder"<setOccluderList(cov.getCollectedOccluderList()); + + //std::cout << "finished searching for occluder"<getOccluderList().clear(); + std::copy(cov.getCollectedOccluderSet().begin(),cov.getCollectedOccluderSet().end(), std::back_insert_iterator(cullVisitor->getOccluderList())); }