Further work on occlusion culling.

This commit is contained in:
Robert Osfield 2002-06-13 23:46:02 +00:00
parent 8c5722577e
commit 61df1ed6b7
9 changed files with 203 additions and 70 deletions

View File

@ -198,6 +198,10 @@ SOURCE=..\..\..\src\osgPlugins\osg\Object.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\osg\OccluderNode.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\src\osgPlugins\osg\Point.cpp
# End Source File
# Begin Source File

View File

@ -30,6 +30,10 @@ class SG_EXPORT CollectOccludersVisitor : public osg::NodeVisitor, public osg::C
virtual void apply(osg::LOD& node);
virtual void apply(osg::OccluderNode& node);
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; }
@ -43,7 +47,8 @@ class SG_EXPORT CollectOccludersVisitor : public osg::NodeVisitor, public osg::C
/** prevent unwanted copy operator.*/
CollectOccludersVisitor& operator = (const CollectOccludersVisitor&) { return *this; }
ShadowVolumeOccluderList _collectedOccluderList;
bool _createDrawables;
ShadowVolumeOccluderList _collectedOccluderList;
};

View File

@ -35,7 +35,7 @@ class SG_EXPORT ShadowVolumeOccluder
/** compute the shadow volume occluder. */
bool computeOccluder(const NodePath& nodePath,const ConvexPlanerOccluder& occluder,CullStack& cullStack);
bool computeOccluder(const NodePath& nodePath,const ConvexPlanerOccluder& occluder,CullStack& cullStack,bool createDrawables=false);
inline void disableResultMasks();

View File

@ -82,7 +82,7 @@ osg::Node* createOccludersAroundModel(osg::Node* model)
occluderNode->setOccluder(cpo);
// create a drawable for occluder.
// create a drawable for occluder.
osg::GeoSet* geoset = osgNew osg::GeoSet;
osg::Vec3* coords = osgNew osg::Vec3[occluder.getVertexList().size()];

View File

@ -11,6 +11,9 @@ CollectOccludersVisitor::CollectOccludersVisitor()
{
// overide the default node visitor mode.
setTraversalMode(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
_createDrawables = false;
}
CollectOccludersVisitor::~CollectOccludersVisitor()
@ -117,11 +120,13 @@ void CollectOccludersVisitor::apply(osg::OccluderNode& node)
// planes, all with their normals facing inward towards the volume,
// and then transform them back into projection space.
ShadowVolumeOccluder svo;
if (svo.computeOccluder(_nodePath, *node.getOccluder(), *this))
if (svo.computeOccluder(_nodePath, *node.getOccluder(), *this,_createDrawables))
{
// need to test occluder against view frustum.
// std::cout << " adding in Occluder"<<std::endl;
_occluderList.push_back(svo);
}
}

View File

@ -1,6 +1,10 @@
#include <osg/ShadowVolumeOccluder>
#include <osg/CullStack>
#include <osg/Group>
#include <osg/Geode>
#include <osg/GeoSet>
using namespace osg;
@ -108,7 +112,9 @@ void pushToFarPlane(PointList& points)
itr!=points.end();
++itr)
{
itr->second.z()=-1.0f;
// std::cout << "itr->second "<< itr->second<< " after ";
itr->second.z() += 1.0f;
// std::cout << itr->second<< std::endl;
}
}
@ -129,7 +135,59 @@ Plane computeFrontPlane(const PointList& front)
return Plane(front[2].second,front[1].second,front[0].second);
}
bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const ConvexPlanerOccluder& occluder,CullStack& cullStack)
Drawable* createOccluderDrawable(const PointList& front, const PointList& back)
{
// create a drawable for occluder.
osg::GeoSet* geoset = osgNew osg::GeoSet;
int totalNumber = front.size()+back.size();
osg::Vec3* coords = osgNew osg::Vec3[front.size()+back.size()];
osg::Vec3* cptr = coords;
for(PointList::const_iterator fitr=front.begin();
fitr!=front.end();
++fitr)
{
*cptr = fitr->second;
++cptr;
}
for(PointList::const_iterator bitr=back.begin();
bitr!=back.end();
++bitr)
{
*cptr = bitr->second;
++cptr;
}
geoset->setCoords(coords);
osg::Vec4* color = osgNew osg::Vec4[1];
color[0].set(1.0f,1.0f,1.0f,0.5f);
geoset->setColors(color);
geoset->setColorBinding(osg::GeoSet::BIND_OVERALL);
geoset->setPrimType(osg::GeoSet::POINTS);
geoset->setNumPrims(totalNumber);
//cout << "totalNumber = "<<totalNumber<<endl;
osg::Geode* geode = osgNew osg::Geode;
geode->addDrawable(geoset);
osg::StateSet* stateset = osgNew osg::StateSet;
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
geoset->setStateSet(stateset);
return geoset;
}
bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const ConvexPlanerOccluder& occluder,CullStack& cullStack,bool createDrawables)
{
@ -153,9 +211,25 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex
Matrix invP;
invP.invert(P);
// std::cout<<"P "<<P<<std::endl;
// std::cout<<"invP "<<invP<<std::endl;
//
// Vec3 v1(0,0,1000);
// std::cout<<"v1 "<<v1<<std::endl;
// Vec3 v2 = v1*P;
// std::cout<<"v2 "<<v2<<std::endl;
// Vec3 v3 = v2*invP;
// std::cout<<"v3 "<<v3<<std::endl;
//
// Vec3 v4(0,0,1);
// std::cout<<"v4 "<<v4<<std::endl;
// Vec3 v5=v4*invP;
// std::cout<<"v5 "<<v5<<std::endl;
// compute the transformation matrix which takes form local coords into clip space.
Matrix MVP(MV);
MVP *= P;
Matrix MVP(MV*P);
//MVP *= P;
// for the occluder polygon and each of the holes do
// first transform occluder polygon into clipspace by multiple it by c[i] = v[i]*(MV*P)
@ -191,16 +265,32 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex
// if the front face is pointing away from the eye point flip the whole polytope.
if (occludePlane[3]>0.0f)
{
// std::cout << " flipping polytope"<<std::endl;
_occluderVolume.flip();
}
for(Polytope::PlaneList::const_iterator itr=_occluderVolume.getPlaneList().begin();
itr!=_occluderVolume.getPlaneList().end();
++itr)
if (createDrawables && !nodePath.empty())
{
// std::cout << " compute plane "<<*itr<<std::endl;
osg::Group* group = dynamic_cast<osg::Group*>(nodePath.back());
if (group)
{
osg::Matrix invMV;
invMV.invert(MV);
transform(points,invMV);
transform(farPoints,invMV);
// Vec3 v6=v5*invMV;
// std::cout<<"******************"<<std::endl;
// std::cout<<"MV "<<MV<<std::endl;
// std::cout<<"invMV "<<invMV<<std::endl;
// std::cout<<"MV*invMV "<<MV*invMV<<std::endl;
// std::cout<<"v6 "<<v6<<std::endl;
osg::Geode* geode = osgNew osg::Geode;
group->addChild(geode);
geode->addDrawable(createOccluderDrawable(points,farPoints));
}
}
@ -208,7 +298,7 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex
}
else
{
// std::cout << " occluder clipped out of frustum."<<points.size()<<std::endl;
std::cout << " occluder clipped out of frustum."<<points.size()<<std::endl;
return false;
}
}

View File

@ -32,6 +32,7 @@
#include <osg/LightModel>
#include <osg/ShadeModel>
#include <osg/Notify>
#include <osg/CollectOccludersVisitor>
#include <osgDB/WriteFile>
@ -1080,67 +1081,94 @@ void Viewer::keyboard(unsigned char key, int x, int y)
osg::notify(osg::NOTICE) << "Saved screen image to `"<<filename<<"`"<< std::endl;
}
break;
case 'v' :
{
osg::notify(osg::NOTICE) << "Creating occluders"<< std::endl;
osg::CollectOccludersVisitor cov;
cov.setCreateDrawablesOnOccludeNodes(true);
cov.pushViewport(sceneView->getViewport());
if (sceneView->getProjectionMatrix()) cov.pushProjectionMatrix(sceneView->getProjectionMatrix());
else if (sceneView->getCamera()) cov.pushProjectionMatrix(osgNew Matrix(sceneView->getCamera()->getProjectionMatrix()));
else cov.pushProjectionMatrix(osgNew Matrix());
if (sceneView->getModelViewMatrix()) cov.pushModelViewMatrix(sceneView->getModelViewMatrix());
else if (sceneView->getCamera()) cov.pushModelViewMatrix(osgNew Matrix(sceneView->getCamera()->getModelViewMatrix()));
else cov.pushModelViewMatrix(osgNew Matrix());
sceneView->getSceneData()->accept(cov);
cov.popModelViewMatrix();
cov.popProjectionMatrix();
cov.popViewport();
}
break;
case 'i' :
case 'r' :
{
osg::notify(osg::NOTICE) << "***** Intersecting **************"<< std::endl;
osg::Vec3 near_point,far_point;
if (!sceneView->projectWindowXYIntoObject(x,_wh-y,near_point,far_point))
{
osg::notify(osg::NOTICE) << "Failed to calculate intersection ray."<< std::endl;
return;
}
osg::notify(osg::NOTICE) << "***** Intersecting **************"<< std::endl;
osg::ref_ptr<osg::LineSegment> lineSegment = osgNew osg::LineSegment;
lineSegment->set(near_point,far_point);
osg::notify(osg::NOTICE) << "start("<<lineSegment->start()<<") end("<<lineSegment->end()<<")"<< std::endl;
osgUtil::IntersectVisitor iv;
iv.addLineSegment(lineSegment.get());
float startTime = clockSeconds();
sceneView->getSceneData()->accept(iv);
float endTime = clockSeconds();
osg::notify(osg::NOTICE) << "Time for interesection = "<<(endTime-startTime)*1000<<"ms"<< std::endl;
if (iv.hits())
{
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(lineSegment.get());
for(osgUtil::IntersectVisitor::HitList::iterator hitr=hitList.begin();
hitr!=hitList.end();
++hitr)
osg::Vec3 near_point,far_point;
if (!sceneView->projectWindowXYIntoObject(x,_wh-y,near_point,far_point))
{
osg::Vec3 ip = hitr->getLocalIntersectPoint();
osg::Vec3 in = hitr->getLocalIntersectNormal();
osg::Geode* geode = hitr->_geode.get();
osg::notify(osg::NOTICE) << " Itersection Point ("<<ip<<") Normal ("<<in<<")"<< std::endl;
if (hitr->_matrix.valid())
{
osg::Vec3 ipEye = hitr->getWorldIntersectPoint();
osg::Vec3 inEye = hitr->getWorldIntersectNormal();
inEye.normalize();
if (geode) osg::notify(osg::NOTICE) << "Geode '"<<geode->getName()<< std::endl;
osg::notify(osg::NOTICE) << " Eye Itersection Point ("<<ipEye<<") Normal ("<<inEye<<")"<< std::endl;
osg::notify(osg::NOTICE) << "Failed to calculate intersection ray."<< std::endl;
return;
}
}
if (key=='r' && geode)
osg::ref_ptr<osg::LineSegment> lineSegment = osgNew osg::LineSegment;
lineSegment->set(near_point,far_point);
osg::notify(osg::NOTICE) << "start("<<lineSegment->start()<<") end("<<lineSegment->end()<<")"<< std::endl;
osgUtil::IntersectVisitor iv;
iv.addLineSegment(lineSegment.get());
float startTime = clockSeconds();
sceneView->getSceneData()->accept(iv);
float endTime = clockSeconds();
osg::notify(osg::NOTICE) << "Time for interesection = "<<(endTime-startTime)*1000<<"ms"<< std::endl;
if (iv.hits())
{
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(lineSegment.get());
for(osgUtil::IntersectVisitor::HitList::iterator hitr=hitList.begin();
hitr!=hitList.end();
++hitr)
{
// remove geoset..
osg::GeoSet* gset = hitr->_geoset.get();
osg::notify(osg::NOTICE) << " geoset ("<<gset<<") "<<geode->removeDrawable(gset)<<")"<< std::endl;
osg::Vec3 ip = hitr->getLocalIntersectPoint();
osg::Vec3 in = hitr->getLocalIntersectNormal();
osg::Geode* geode = hitr->_geode.get();
osg::notify(osg::NOTICE) << " Itersection Point ("<<ip<<") Normal ("<<in<<")"<< std::endl;
if (hitr->_matrix.valid())
{
osg::Vec3 ipEye = hitr->getWorldIntersectPoint();
osg::Vec3 inEye = hitr->getWorldIntersectNormal();
inEye.normalize();
if (geode) osg::notify(osg::NOTICE) << "Geode '"<<geode->getName()<< std::endl;
osg::notify(osg::NOTICE) << " Eye Itersection Point ("<<ipEye<<") Normal ("<<inEye<<")"<< std::endl;
}
if (key=='r' && geode)
{
// remove geoset..
osg::GeoSet* gset = hitr->_geoset.get();
osg::notify(osg::NOTICE) << " geoset ("<<gset<<") "<<geode->removeDrawable(gset)<<")"<< std::endl;
}
}
}
osg::notify(osg::NOTICE) << std::endl << std::endl;
}
osg::notify(osg::NOTICE) << std::endl << std::endl;
}
break;
break;
case 27 :

View File

@ -28,6 +28,7 @@ CXXFILES =\
Matrix.cpp\
Node.cpp\
Object.cpp\
OccluderNode.cpp\
Point.cpp\
PolygonMode.cpp\
PolygonOffset.cpp\

View File

@ -289,11 +289,11 @@ void SceneView::cull()
_cullVisitor->setTraversalMask(_cullMask);
cullStage(projection.get(),modelview.get(),_cullVisitor.get(),_rendergraph.get(),_renderStage.get());
// if (_camera.valid())
// {
// // clamp the camera to the near/far computed in cull traversal.
// _camera->setNearFar(_cullVisitor->getCalculatedNearPlane(),_cullVisitor->getCalculatedFarPlane());
// }
if (_camera.valid())
{
// clamp the camera to the near/far computed in cull traversal.
_camera->setNearFar(_cullVisitor->getCalculatedNearPlane(),_cullVisitor->getCalculatedFarPlane());
}
}