OpenSceneGraph/examples/osgintersection/osgintersection.cpp
Robert Osfield 6a67be2e32 Introduced CMake option OSG_PROVIDE_READFILE option that defaults to ON, but when switched to OFF disables the building of the osgDB::read*File() methods,
forcing users to use osgDB::readRef*File() methods.  The later is preferable as it closes a potential threading bug when using paging databases in conjunction
with the osgDB::Registry Object Cache.  This threading bug occurs when one thread gets an object from the Cache via an osgDB::read*File() call where only
a pointer to the object is passed back, so taking a reference to the object is delayed till it gets reassigned to a ref_ptr<>, but at the same time another
thread calls a flush of the Object Cache deleting this object as it's referenceCount is now zero.  Using osgDB::readREf*File() makes sure the a ref_ptr<> is
passed back and the referenceCount never goes to zero.

To ensure the OSG builds when OSG_PROVIDE_READFILE is to OFF the many cases of osgDB::read*File() usage had to be replaced with a ref_ptr<> osgDB::readRef*File()
usage.  The avoid this change causing lots of other client code to be rewritten to handle the use of ref_ptr<> in place of C pointer I introduced a serious of
templte methods in various class to adapt ref_ptr<> to the underly C pointer to be passed to old OSG API's, example of this is found in include/osg/Group:

    bool addChild(Node* child); // old method which can only be used with a Node*

    tempalte<class T> bool addChild(const osg::ref_ptr<T>& child) { return addChild(child.get()); } // adapter template method

These changes together cover 149 modified files, so it's a large submission. This extent of changes are warrent to make use of the Object Cache
and multi-threaded loaded more robust.



git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/branches/OpenSceneGraph-3.4@15165 16af8721-9629-0410-8352-f15c8da7e697
2015-10-22 14:14:53 +00:00

278 lines
10 KiB
C++

/* OpenSceneGraph example, osgintersection.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <osg/ArgumentParser>
#include <osg/ApplicationUsage>
#include <osg/Timer>
#include <osg/CoordinateSystemNode>
#include <osg/Notify>
#include <osg/io_utils>
#include <osgDB/ReadFile>
#include <osgUtil/IntersectionVisitor>
#include <osgUtil/LineSegmentIntersector>
#include <osgSim/LineOfSight>
#include <osgSim/HeightAboveTerrain>
#include <osgSim/ElevationSlice>
#include <iostream>
struct MyReadCallback : public osgUtil::IntersectionVisitor::ReadCallback
{
virtual osg::Node* readNodeFile(const std::string& filename)
{
return osgDB::readRefNodeFile(filename).release();
}
};
int main(int argc, char **argv)
{
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
osg::ref_ptr<osg::Node> scene = osgDB::readRefNodeFiles(arguments);
if (!scene)
{
std::cout<<"No model loaded, please specify a valid model on the command line."<<std::endl;
return 0;
}
std::cout<<"Intersection "<<std::endl;
osg::BoundingSphere bs = scene->getBound();
bool useIntersectorGroup = true;
bool useLineOfSight = true;
//osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(scene.get());
//osg::EllipsoidModel* em = csn ? csn->getEllipsoidModel() : 0;
if (useLineOfSight)
{
osg::Vec3d start = bs.center() + osg::Vec3d(0.0,bs.radius(),0.0);
osg::Vec3d end = bs.center() - osg::Vec3d(0.0, bs.radius(),0.0);
osg::Vec3d deltaRow( 0.0, 0.0, bs.radius()*0.01);
osg::Vec3d deltaColumn( bs.radius()*0.01, 0.0, 0.0);
osgSim::LineOfSight los;
#if 1
unsigned int numRows = 20;
unsigned int numColumns = 20;
osgSim::HeightAboveTerrain hat;
hat.setDatabaseCacheReadCallback(los.getDatabaseCacheReadCallback());
for(unsigned int r=0; r<numRows; ++r)
{
for(unsigned int c=0; c<numColumns; ++c)
{
osg::Vec3d s = start + deltaColumn * double(c) + deltaRow * double(r);
osg::Vec3d e = end + deltaColumn * double(c) + deltaRow * double(r);
los.addLOS(s,e);
hat.addPoint(s);
}
}
{
std::cout<<"Computing LineOfSight"<<std::endl;
osg::Timer_t startTick = osg::Timer::instance()->tick();
los.computeIntersections(scene.get());
osg::Timer_t endTick = osg::Timer::instance()->tick();
std::cout<<"Completed in "<<osg::Timer::instance()->delta_s(startTick,endTick)<<std::endl;
for(unsigned int i=0; i<los.getNumLOS(); i++)
{
const osgSim::LineOfSight::Intersections& intersections = los.getIntersections(i);
for(osgSim::LineOfSight::Intersections::const_iterator itr = intersections.begin();
itr != intersections.end();
++itr)
{
std::cout<<" point "<<*itr<<std::endl;
}
}
}
{
// now do a second traversal to test performance of cache.
osg::Timer_t startTick = osg::Timer::instance()->tick();
std::cout<<"Computing HeightAboveTerrain"<<std::endl;
hat.computeIntersections(scene.get());
osg::Timer_t endTick = osg::Timer::instance()->tick();
for(unsigned int i=0; i<hat.getNumPoints(); i++)
{
std::cout<<" point = "<<hat.getPoint(i)<<" hat = "<<hat.getHeightAboveTerrain(i)<<std::endl;
}
std::cout<<"Completed in "<<osg::Timer::instance()->delta_s(startTick,endTick)<<std::endl;
}
#endif
{
// now do a second traversal to test performance of cache.
osg::Timer_t startTick = osg::Timer::instance()->tick();
std::cout<<"Computing ElevationSlice"<<std::endl;
osgSim::ElevationSlice es;
es.setDatabaseCacheReadCallback(los.getDatabaseCacheReadCallback());
es.setStartPoint(bs.center()+osg::Vec3d(bs.radius(),0.0,0.0) );
es.setEndPoint(bs.center()+osg::Vec3d(0.0,0.0, bs.radius()) );
es.computeIntersections(scene.get());
osg::Timer_t endTick = osg::Timer::instance()->tick();
std::cout<<"Completed in "<<osg::Timer::instance()->delta_s(startTick,endTick)<<std::endl;
typedef osgSim::ElevationSlice::DistanceHeightList DistanceHeightList;
const DistanceHeightList& dhl = es.getDistanceHeightIntersections();
std::cout<<"Number of intersections ="<<dhl.size()<<std::endl;
for(DistanceHeightList::const_iterator dhitr = dhl.begin();
dhitr != dhl.end();
++dhitr)
{
std::cout.precision(10);
std::cout<<" "<<dhitr->first<<" "<<dhitr->second<<std::endl;
}
}
}
else if (useIntersectorGroup)
{
osg::Timer_t startTick = osg::Timer::instance()->tick();
osg::Vec3d start = bs.center() + osg::Vec3d(0.0,bs.radius(),0.0);
osg::Vec3d end = bs.center();// - osg::Vec3d(0.0, bs.radius(),0.0);
osg::Vec3d deltaRow( 0.0, 0.0, bs.radius()*0.01);
osg::Vec3d deltaColumn( bs.radius()*0.01, 0.0, 0.0);
unsigned int numRows = 20;
unsigned int numColumns = 20;
osg::ref_ptr<osgUtil::IntersectorGroup> intersectorGroup = new osgUtil::IntersectorGroup();
for(unsigned int r=0; r<numRows; ++r)
{
for(unsigned int c=0; c<numColumns; ++c)
{
osg::Vec3d s = start + deltaColumn * double(c) + deltaRow * double(r);
osg::Vec3d e = end + deltaColumn * double(c) + deltaRow * double(r);
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector(s, e);
intersectorGroup->addIntersector( intersector.get() );
}
}
osgUtil::IntersectionVisitor intersectVisitor( intersectorGroup.get(), new MyReadCallback );
scene->accept(intersectVisitor);
osg::Timer_t endTick = osg::Timer::instance()->tick();
std::cout<<"Completed in "<<osg::Timer::instance()->delta_s(startTick,endTick)<<std::endl;
if ( intersectorGroup->containsIntersections() )
{
std::cout<<"Found intersections "<<std::endl;
osgUtil::IntersectorGroup::Intersectors& intersectors = intersectorGroup->getIntersectors();
for(osgUtil::IntersectorGroup::Intersectors::iterator intersector_itr = intersectors.begin();
intersector_itr != intersectors.end();
++intersector_itr)
{
osgUtil::LineSegmentIntersector* lsi = dynamic_cast<osgUtil::LineSegmentIntersector*>(intersector_itr->get());
if (lsi)
{
osgUtil::LineSegmentIntersector::Intersections& intersections = lsi->getIntersections();
for(osgUtil::LineSegmentIntersector::Intersections::iterator itr = intersections.begin();
itr != intersections.end();
++itr)
{
const osgUtil::LineSegmentIntersector::Intersection& intersection = *itr;
std::cout<<" ratio "<<intersection.ratio<<std::endl;
std::cout<<" point "<<intersection.localIntersectionPoint<<std::endl;
std::cout<<" normal "<<intersection.localIntersectionNormal<<std::endl;
std::cout<<" indices "<<intersection.indexList.size()<<std::endl;
std::cout<<" primitiveIndex "<<intersection.primitiveIndex<<std::endl;
std::cout<<std::endl;
}
}
}
}
}
else
{
osg::Timer_t startTick = osg::Timer::instance()->tick();
#if 1
osg::Vec3d start = bs.center() + osg::Vec3d(0.0,bs.radius(),0.0);
osg::Vec3d end = bs.center() - osg::Vec3d(0.0, bs.radius(),0.0);
#else
osg::Vec3d start = bs.center() + osg::Vec3d(0.0,0.0, bs.radius());
osg::Vec3d end = bs.center() - osg::Vec3d(0.0, 0.0, bs.radius());
#endif
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector(start, end);
osgUtil::IntersectionVisitor intersectVisitor( intersector.get(), new MyReadCallback );
scene->accept(intersectVisitor);
osg::Timer_t endTick = osg::Timer::instance()->tick();
std::cout<<"Completed in "<<osg::Timer::instance()->delta_s(startTick,endTick)<<std::endl;
if ( intersector->containsIntersections() )
{
osgUtil::LineSegmentIntersector::Intersections& intersections = intersector->getIntersections();
for(osgUtil::LineSegmentIntersector::Intersections::iterator itr = intersections.begin();
itr != intersections.end();
++itr)
{
const osgUtil::LineSegmentIntersector::Intersection& intersection = *itr;
std::cout<<" ratio "<<intersection.ratio<<std::endl;
std::cout<<" point "<<intersection.localIntersectionPoint<<std::endl;
std::cout<<" normal "<<intersection.localIntersectionNormal<<std::endl;
std::cout<<" indices "<<intersection.indexList.size()<<std::endl;
std::cout<<" primitiveIndex "<<intersection.primitiveIndex<<std::endl;
std::cout<<std::endl;
}
}
}
return 0;
}