From 21beb236d2765d7b22d697b66983c0b2e7a6bb4b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 19 Jun 2002 10:19:10 +0000 Subject: [PATCH] Added support for occlusion of holes in occluders, and cleaned up the interface to ShadowVolumeOccluders. --- include/osg/ShadowVolumeOccluder | 16 ++++++++++++++- src/Demos/osgoccluder/osgoccluder.cpp | 28 ++++++++++++++++++++++++--- src/osg/CollectOccludersVisitor.cpp | 20 +++++++++++++++++-- src/osg/ShadowVolumeOccluder.cpp | 3 ++- src/osgUtil/SceneView.cpp | 2 +- 5 files changed, 61 insertions(+), 8 deletions(-) diff --git a/include/osg/ShadowVolumeOccluder b/include/osg/ShadowVolumeOccluder index ad59fcf06..65a6d30cb 100644 --- a/include/osg/ShadowVolumeOccluder +++ b/include/osg/ShadowVolumeOccluder @@ -60,8 +60,22 @@ class SG_EXPORT ShadowVolumeOccluder 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 contaned entirely @@ -88,7 +102,7 @@ class SG_EXPORT ShadowVolumeOccluder } -// protected: + protected: float _volume; NodePath _nodePath; diff --git a/src/Demos/osgoccluder/osgoccluder.cpp b/src/Demos/osgoccluder/osgoccluder.cpp index 5e864a608..9840daad7 100644 --- a/src/Demos/osgoccluder/osgoccluder.cpp +++ b/src/Demos/osgoccluder/osgoccluder.cpp @@ -52,7 +52,7 @@ void write_usage(std::ostream& out,const std::string& name) } -osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,const osg::Vec3& v4) +osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,const osg::Vec3& v4,float holeRatio=-1.0f) { // create and occluder which will site along side the loadmodel model. osg::OccluderNode* occluderNode = osgNew osg::OccluderNode; @@ -70,7 +70,28 @@ osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec occluder.add(v2); occluder.add(v3); occluder.add(v4); - + + // create a whole at the center of the occluder if needed. + if (holeRatio>0.0f) + { + // create hole. + float ratio = holeRatio; + float one_minus_ratio = 1-ratio; + osg::Vec3 center = (v1+v2+v3+v4)*0.25f; + osg::Vec3 v1dash = v1*ratio + center*one_minus_ratio; + osg::Vec3 v2dash = v2*ratio + center*one_minus_ratio; + osg::Vec3 v3dash = v3*ratio + center*one_minus_ratio; + osg::Vec3 v4dash = v4*ratio + center*one_minus_ratio; + + osg::ConvexPlanerPolygon hole; + hole.add(v1dash); + hole.add(v2dash); + hole.add(v3dash); + hole.add(v4dash); + + cpo->addHole(hole); + } + // create a drawable for occluder. osg::GeoSet* geoset = osgNew osg::GeoSet; @@ -145,7 +166,8 @@ osg::Node* createOccludersAroundModel(osg::Node* model) scene->addChild(createOccluder(bb.corner(3), bb.corner(2), bb.corner(6), - bb.corner(7))); + bb.corner(7), + 0.5f)); // create a hole half the size of the occluder. return scene; } diff --git a/src/osg/CollectOccludersVisitor.cpp b/src/osg/CollectOccludersVisitor.cpp index 846386c64..214556456 100644 --- a/src/osg/CollectOccludersVisitor.cpp +++ b/src/osg/CollectOccludersVisitor.cpp @@ -175,7 +175,9 @@ void CollectOccludersVisitor::removeOccludedOccluders() // search for any occluders that occlude the current occluder, // we only need to test any occluder near the front of the set since // you can't be occluder by something smaller than you. - const ShadowVolumeOccluder& occludee = *occludeeItr; + ShadowVolumeOccluder& occludee = const_cast(*occludeeItr); + ShadowVolumeOccluder::HoleList& holeList = occludee.getHoleList(); + for(ShadowVolumeOccluderSet::iterator occluderItr=_occluderSet.begin(); occluderItr!=occludeeItr; ++occluderItr) @@ -184,7 +186,7 @@ void CollectOccludersVisitor::removeOccludedOccluders() // and the std::set is a const, just for the invariance of the operator (&(*occluderItr)); - if (occluder->contains(occludee._occluderVolume.getReferenceVertexList())) + if (occluder->contains(occludee.getOccluder().getReferenceVertexList())) { // erase occluder from set. // take a copy of the iterator then rewind it one element so to prevent invalidating the occludeeItr. @@ -192,6 +194,20 @@ void CollectOccludersVisitor::removeOccludedOccluders() _occluderSet.erase(eraseItr); break; } + + // now check all the holes in the occludee against the occluder, + // do so in reverse order so that the iterators remain valid. + for(ShadowVolumeOccluder::HoleList::reverse_iterator holeItr=holeList.rbegin(); + holeItr!=holeList.rend(); + ++holeItr) + { + if (occluder->contains(holeItr->getReferenceVertexList())) + { + holeList.erase(holeItr.base()); + } + + } + } } } diff --git a/src/osg/ShadowVolumeOccluder.cpp b/src/osg/ShadowVolumeOccluder.cpp index 4688db293..f732f509f 100644 --- a/src/osg/ShadowVolumeOccluder.cpp +++ b/src/osg/ShadowVolumeOccluder.cpp @@ -390,7 +390,8 @@ bool ShadowVolumeOccluder::contains(const std::vector& vertices) itr!=_holeList.end(); ++itr) { - if (itr->contains(vertices)) return false; + PointList points; + if (clip(itr->getPlaneList(),vertices,points)>=3) return false; } return true; } diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index bef5e32ab..63016b25d 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -345,7 +345,7 @@ void SceneView::cullStage(osg::Matrix* projection,osg::Matrix* modelview,osgUtil cov.removeOccludedOccluders(); - //std::cout << "finished searching for occluder"<getOccluderList().clear(); std::copy(cov.getCollectedOccluderSet().begin(),cov.getCollectedOccluderSet().end(), std::back_insert_iterator(cullVisitor->getOccluderList()));