6a67be2e32
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
278 lines
10 KiB
C++
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;
|
|
}
|