diff --git a/examples/osgintersection/osgintersection.cpp b/examples/osgintersection/osgintersection.cpp index db226fdbc..6fc5fcdc2 100644 --- a/examples/osgintersection/osgintersection.cpp +++ b/examples/osgintersection/osgintersection.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -9,6 +10,7 @@ #include #include +#include #include @@ -31,9 +33,9 @@ int main(int argc, char **argv) arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()); arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information"); - osg::ref_ptr root = osgDB::readNodeFiles(arguments); + osg::ref_ptr scene = osgDB::readNodeFiles(arguments); - if (!root) + if (!scene) { std::cout<<"No model loaded, please specify a valid model on the command line."<(scene.get()); + osg::EllipsoidModel* em = csn ? csn->getEllipsoidModel() : 0; - osg::BoundingSphere bs = root->getBound(); + osg::BoundingSphere bs = scene->getBound(); bool useIntersectorGroup = true; @@ -57,10 +61,13 @@ int main(int argc, char **argv) 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 = 50; - unsigned int numColumns = 50; + unsigned int numRows = 20; + unsigned int numColumns = 20; osgSim::LineOfSight los; + + osgSim::HeightAboveTerrain hat; + hat.setDatabaseCacheReadCallback(los.getDatabaseCacheReadCallback()); for(unsigned int r=0; rtick(); std::cout<<"Completed in "<delta_s(startTick,endTick)<tick(); - los.computeIntersections(root.get()); + std::cout<<"Computing HeightAboveTerrain"<delta_s(startTick,endTick)<accept(intersectVisitor); + scene->accept(intersectVisitor); osg::Timer_t endTick = osg::Timer::instance()->tick(); @@ -181,7 +198,7 @@ int main(int argc, char **argv) osgUtil::IntersectionVisitor intersectVisitor( intersector.get(), new MyReadCallback ); - root->accept(intersectVisitor); + scene->accept(intersectVisitor); osg::Timer_t endTick = osg::Timer::instance()->tick(); diff --git a/include/osgSim/HeightAboveTerrain b/include/osgSim/HeightAboveTerrain index 13365f9f8..39b77b155 100644 --- a/include/osgSim/HeightAboveTerrain +++ b/include/osgSim/HeightAboveTerrain @@ -16,7 +16,8 @@ #include -#include +// include so we can get access to the DatabaseCacheReadCallback +#include namespace osgSim { @@ -25,7 +26,85 @@ class OSGSIM_EXPORT HeightAboveTerrain { public : + + HeightAboveTerrain(); + + + /** Clear the internal HAT List so it contains no height above terrain tests.*/ + void clear(); + + /** Add a height above terrain test point in the CoordinateFrame.*/ + unsigned int addPoint(const osg::Vec3d& point); + + /** Get the number of height above terrain tests.*/ + unsigned int getNumPoints() const { return _HATList.size(); } + + /** Set the source point of single height above terrain test.*/ + void setPoint(unsigned int i, const osg::Vec3d& point) { _HATList[i]._point = point; } + + /** Get the source point of single height above terrain test.*/ + const osg::Vec3d& getPoint(unsigned int i) const { return _HATList[i]._point; } + + /** Get the intersection height for a single height above terrain test. + * Note, you must call computeIntersections(..) before you can querry the HeightAboveTerrain. + * If no intersections are found then height returned will be the height above mean sea level. */ + double getHeightAboveTerrain(unsigned int i) const { return _HATList[i]._hat; } + + /** Set the lowest height that the should be tested for. + * Defaults to -1000, i.e. 1000m below mean sea level. */ + void setLowestHeight(double lowestHeight) { _lowestHeight = lowestHeight; } + + /** Get the lowest height that the should be tested for.*/ + double getLowestHeight() const { return _lowestHeight; } + + /** Compute the HAT intersections with the specified scene graph. + * The results are all stored in the form of a single height above terrain value per HAT test. + * Note, if the topmost node is a CoordinateSystemNode then the input points are assumed to be geocentric, + * with the up vector defined by the EllipsoidModel attached to the CoordinateSystemNode. + * If the topmost node is not a CoordinateSystemNode then a local coordinates frame is assumed, with a local up vector. */ + void computeIntersections(osg::Node* scene); + + /** Compute the vertical distance between the specified scene graph and a single HAT point. .*/ + static double computeHeightAboveTerrain(osg::Node* scene, const osg::Vec3d& point); + + + /** Clear the database cache.*/ + void clearDatabaseCache() { if (_dcrc.valid()) _dcrc->clearDatabaseCache(); } + + /** Set the ReadCallback that does the reading of external PagedLOD models, and caching of loaded subgraphs. + * Note, if you have mulitple LineOfSight or HeightAboveTerrain objects in use at one time then you should share a single + * DatabaseCacheReadCallback between all of them. */ + void setDatabaseCacheReadCallback(DatabaseCacheReadCallback* dcrc); + + /** Get the ReadCallback that does the reading of external PagedLOD models, and caching of loaded subgraphs.*/ + DatabaseCacheReadCallback* getDatabaseCacheReadCallback() { return _dcrc.get(); } + + /** Get the IntersectionVistor that does the intersection traversal over the scene. + * Note, if you want to customized the traversal then you can use the IntersectionVisitor's method to alter its behavior. */ + osgUtil::IntersectionVisitor& getIntersectionVisitor() { return _intersectionVisitor; } + protected : + + struct HAT + { + HAT(const osg::Vec3d& point): + _point(point), + _hat(0.0) {} + + osg::Vec3d _point; + double _hat; + }; + + typedef std::vector HATList; + + + double _lowestHeight; + HATList _HATList; + + + osg::ref_ptr _dcrc; + osgUtil::IntersectionVisitor _intersectionVisitor; + }; diff --git a/include/osgSim/LineOfSight b/include/osgSim/LineOfSight index 65c781368..e82247edc 100644 --- a/include/osgSim/LineOfSight +++ b/include/osgSim/LineOfSight @@ -52,7 +52,7 @@ class OSGSIM_EXPORT LineOfSight LineOfSight(); /** Clear the internal LOS List so it contains no line of sight tests.*/ - void clearLOS(); + void clear(); /** Add a line of sight test, consisting of start and end point. Returns the index number of the newly adding LOS test.*/ unsigned int addLOS(const osg::Vec3d& start, const osg::Vec3d& end); @@ -78,7 +78,7 @@ class OSGSIM_EXPORT LineOfSight const Intersections& getIntersections(unsigned int i) const { return _LOSList[i]._intersections; } /** Compute the LOS intersections with the specified scene graph. - * The results are all stored in the form of IntersectionList, one per LOS test.*/ + * The results are all stored in the form of Intersections list, one per LOS test.*/ void computeIntersections(osg::Node* scene); /** Compute the intersection between the specified scene graph and a single LOS start,end pair. Returns an IntersectionList, of all the points intersected.*/ diff --git a/src/osgSim/HeightAboveTerrain.cpp b/src/osgSim/HeightAboveTerrain.cpp index a7b468a7f..1a28935ea 100644 --- a/src/osgSim/HeightAboveTerrain.cpp +++ b/src/osgSim/HeightAboveTerrain.cpp @@ -11,6 +11,111 @@ * OpenSceneGraph Public License for more details. */ +#include #include +#include + using namespace osgSim; + +HeightAboveTerrain::HeightAboveTerrain() +{ + _lowestHeight = -1000.0; + + setDatabaseCacheReadCallback(new DatabaseCacheReadCallback); +} + +void HeightAboveTerrain::clear() +{ + _HATList.clear(); +} + +unsigned int HeightAboveTerrain::addPoint(const osg::Vec3d& point) +{ + unsigned int index = _HATList.size(); + _HATList.push_back(HAT(point)); + return index; +} + +void HeightAboveTerrain::computeIntersections(osg::Node* scene) +{ + osg::CoordinateSystemNode* csn = dynamic_cast(scene); + osg::EllipsoidModel* em = csn ? csn->getEllipsoidModel() : 0; + + osg::ref_ptr intersectorGroup = new osgUtil::IntersectorGroup(); + + for(HATList::iterator itr = _HATList.begin(); + itr != _HATList.end(); + ++itr) + { + if (em) + { + + osg::Vec3d start = itr->_point; + osg::Vec3d upVector = em->computeLocalUpVector(start.x(), start.y(), start.z()); + + double latitude, longitude, height; + em->convertXYZToLatLongHeight(start.x(), start.y(), start.z(), latitude, longitude, height); + osg::Vec3d end = start - upVector * (height - _lowestHeight); + + itr->_hat = height; + + osg::notify(osg::NOTICE)<<"lat = "<