Further work on occlusion culling.
This commit is contained in:
parent
8c5722577e
commit
61df1ed6b7
@ -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
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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()];
|
||||
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 :
|
||||
|
||||
|
@ -28,6 +28,7 @@ CXXFILES =\
|
||||
Matrix.cpp\
|
||||
Node.cpp\
|
||||
Object.cpp\
|
||||
OccluderNode.cpp\
|
||||
Point.cpp\
|
||||
PolygonMode.cpp\
|
||||
PolygonOffset.cpp\
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user