osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthDrivers/vpb/Copy of ReaderWriterVPB.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003  * Copyright 2008-2009 Pelican Ventures, Inc.
00004  * http://osgearth.org
00005  *
00006  * osgEarth is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 
00020 #include <osgEarth/Registry>
00021 #include <osgEarth/TileSource>
00022 #include <osgEarth/HTTPClient>
00023 
00024 #include <osg/Notify>
00025 #include <osg/io_utils>
00026 #include <osg/Version>
00027 #include <osgTerrain/Terrain>
00028 
00029 #include <osgDB/FileNameUtils>
00030 #include <osgDB/FileUtils>
00031 #include <osgDB/Registry>
00032 #include <osgDB/ReadFile>
00033 #include <osgDB/WriteFile>
00034 
00035 #include <OpenThreads/Mutex>
00036 #include <OpenThreads/ScopedLock>
00037 
00038 #include <sstream>
00039 
00040 using namespace osgEarth;
00041 using namespace OpenThreads;
00042 
00043 #define PROPERTY_URL                    "url"
00044 #define PROPERTY_PRIMARY_SPLIT_LEVEL    "primary_split_level"
00045 #define PROPERTY_SECONDARY_SPLIT_LEVEL  "secondary_split_level"
00046 #define PROPERTY_DIRECTORY_STRUCTURE    "directory_structure"
00047 #define PROPERTY_LAYER_NUM              "layer"
00048 #define PROPERTY_NUM_TILES_WIDE_AT_LOD0 "num_tiles_wide_at_lod0"
00049 #define PROPERTY_NUM_TILES_HIGH_AT_LOD0 "num_tiles_high_at_lod0"
00050 #define PROPERTY_BASE_NAME              "base_name"
00051 
00052 
00053 class CollectTiles : public osg::NodeVisitor
00054 {
00055 public:
00056 
00057     CollectTiles(): 
00058         osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
00059     {
00060     }
00061     
00062     void reset()
00063     {
00064         _terrainTiles.clear();
00065     }
00066     
00067     void apply(osg::Group& group)
00068     {
00069         osgTerrain::TerrainTile* terrainTile = dynamic_cast<osgTerrain::TerrainTile*>(&group);
00070         if (terrainTile)
00071         {
00072             osg::notify(osg::INFO)<<"Found terrain tile TileID("<<
00073                                 TileKey::getLOD(terrainTile->getTileID())<<", "<<
00074                 terrainTile->getTileID().x<<", "<<
00075                 terrainTile->getTileID().y<<")"<<std::endl;
00076             
00077             _terrainTiles.push_back(terrainTile);
00078         }
00079         else
00080         {
00081             traverse(group);
00082         }
00083     }
00084     
00085     osgTerrain::Locator* getLocator()
00086     {
00087         for(unsigned int i=0; i<_terrainTiles.size(); ++i)
00088         {
00089             osgTerrain::TerrainTile* tile = _terrainTiles[i].get();
00090             osgTerrain::Locator* locator = tile->getLocator();
00091             if (locator) return locator;
00092         }
00093         return 0;
00094     }
00095 
00096     bool getRange(double& min_x, double& min_y, double& max_x, double& max_y) const
00097     {
00098         min_x = DBL_MAX;
00099         max_x = -DBL_MAX;
00100         min_y = DBL_MAX;
00101         max_y = -DBL_MAX;
00102         
00103         typedef std::vector<osg::Vec3d> Corners;
00104         Corners corners;
00105         corners.push_back(osg::Vec3d(0.0f,0.0f,0.0f));
00106         corners.push_back(osg::Vec3d(1.0f,0.0f,0.0f));
00107         corners.push_back(osg::Vec3d(1.0f,1.0f,0.0f));
00108         corners.push_back(osg::Vec3d(1.0f,1.0f,0.0f));
00109         
00110         for(unsigned int i=0; i<_terrainTiles.size(); ++i)
00111         {
00112             osgTerrain::TerrainTile* tile = _terrainTiles[i].get();
00113             osgTerrain::Locator* locator = tile->getLocator();
00114             if (locator)
00115             {
00116                 for(Corners::iterator itr = corners.begin();
00117                     itr != corners.end();
00118                     ++itr)
00119                 {
00120                     osg::Vec3d& local = *itr;
00121                     osg::Vec3d projected = local * locator->getTransform();
00122 
00123                     if (projected.x()<min_x) min_x = projected.x();
00124                     if (projected.x()>max_x) max_x = projected.x();
00125 
00126                     if (projected.y()<min_y) min_y = projected.y();
00127                     if (projected.y()>max_y) max_y = projected.y();
00128                 }
00129             }
00130         }
00131         
00132         return min_x <= max_x;
00133     }
00134     
00135     typedef std::vector< osg::ref_ptr<osgTerrain::TerrainTile> > TerrainTiles;
00136     TerrainTiles _terrainTiles;
00137 };
00138 
00139 
00140 class VPBDatabase : public osg::Referenced
00141 {
00142 public:
00143 
00144     enum DirectoryStructure
00145     {
00146         FLAT,
00147         FLAT_TASK_DIRECTORIES,
00148         NESTED_TASK_DIRECTORIES
00149     };
00150 
00151     VPBDatabase(const PluginOptions* in_options ) :
00152         options( in_options),
00153         primary_split_level(-1),
00154         secondary_split_level(-1),
00155         directory_structure(FLAT_TASK_DIRECTORIES),
00156         maxNumTilesInCache(128),
00157         profile( osgEarth::Registry::instance()->getGlobalGeodeticProfile() ),
00158         initialized( false )
00159     {
00160         //NOP
00161     }
00162 
00163     void init()
00164     {
00165         if ( initialized ) return;
00166         initialized = true;
00167 
00168         unsigned int numTilesWideAtLod0, numTilesHighAtLod0;
00169         profile->getNumTiles(0, numTilesWideAtLod0, numTilesHighAtLod0);
00170 
00171         if ( options.valid() )
00172         {
00173             const Config& conf = options->config();
00174 
00175             url = conf.value( PROPERTY_URL );
00176             primary_split_level = conf.value<int>( PROPERTY_PRIMARY_SPLIT_LEVEL, -1 );
00177             secondary_split_level = conf.value<int>( PROPERTY_SECONDARY_SPLIT_LEVEL, -1 );
00178 
00179             std::string dir_string = conf.value( PROPERTY_DIRECTORY_STRUCTURE );
00180             if (dir_string=="nested" || dir_string=="nested_task_directories" ) directory_structure = NESTED_TASK_DIRECTORIES;
00181             if (dir_string=="task" || dir_string=="flat_task_directories") directory_structure = FLAT_TASK_DIRECTORIES;
00182             if (dir_string=="flat") directory_structure = FLAT;
00183             
00184             base_name = conf.value( PROPERTY_BASE_NAME );
00185         }
00186 
00187         // validate dataset
00188         if (!url.empty())
00189         {
00190             osg::ref_ptr<osgDB::ReaderWriter::Options> localOptions = new osgDB::ReaderWriter::Options;
00191             localOptions->setPluginData("osgearth_vpb Plugin",(void*)(1));
00192             root_node = osgDB::readNodeFile(url, localOptions.get());
00193 
00194 
00195             if (root_node.valid())
00196             {
00197                 path = osgDB::getFilePath(url);
00198                 if ( base_name.empty() )
00199                     base_name = osgDB::getStrippedName(url);
00200                 extension = osgDB::getFileExtension(url);
00201                 
00202                 osg::notify(osg::INFO)<<"VPBasebase constructor: Loaded root "<<url<<", path="<<path<<" base_name="<<base_name<<" extension="<<extension<<std::endl;
00203                 
00204                 std::string srs = profile->getSRS()->getInitString(); //.srs();
00205                 
00206                 osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(root_node.get());
00207                 if (csn)
00208                 {
00209                     osg::notify(osg::INFO)<<"CordinateSystemNode found, coordinate system is : "<<csn->getCoordinateSystem()<<std::endl;
00210                     
00211                     srs = csn->getCoordinateSystem();
00212                 }
00213 
00214                 CollectTiles ct;
00215                 root_node->accept(ct);
00216 
00217                     
00218                 osgTerrain::Locator* locator = ct.getLocator();
00219                 if (locator)
00220                 {
00221                     double min_x, max_x, min_y, max_y;
00222                     ct.getRange(min_x, min_y, max_x, max_y);
00223 
00224                     osg::notify(osg::INFO)<<"range("<<min_x<<", "<<min_y<<", "<<max_x<<", "<<max_y<<std::endl;
00225 
00226                     srs = locator->getCoordinateSystem();
00227                 
00228                     //osgEarth::Profile::ProfileType ptype = osgEarth::Profile::TYPE_UNKNOWN;
00229 
00230                     //switch(locator->getCoordinateSystemType())
00231                     //{
00232                     //    case(osgTerrain::Locator::GEOCENTRIC):
00233                     //        ptype = Profile::TYPE_GEODETIC; //profile.setProfileType(osgEarth::Profile::GLOBAL_GEODETIC);
00234                     //        break;
00235                     //    case(osgTerrain::Locator::GEOGRAPHIC):
00236                     //        ptype = Profile::TYPE_LOCAL; //profile.setProfileType(osgEarth::Profile::PROJECTED);
00237                     //        break;
00238                     //    case(osgTerrain::Locator::PROJECTED):
00239                     //        ptype = Profile::TYPE_LOCAL; //profile.setProfileType(osgEarth::Profile::PROJECTED);
00240                     //        break;
00241                     //}
00242 
00243                     double aspectRatio = (max_x-min_x)/(max_y-min_y);
00244                     
00245                     osg::notify(osg::INFO)<<"aspectRatio = "<<aspectRatio<<std::endl;
00246 
00247                     if (aspectRatio>1.0)
00248                     {
00249                         numTilesWideAtLod0 = static_cast<unsigned int>(floor(aspectRatio+0.499999));
00250                         numTilesHighAtLod0 = 1;
00251                     }
00252                     else
00253                     {
00254                         numTilesWideAtLod0 = 1;
00255                         numTilesHighAtLod0 = static_cast<unsigned int>(floor(1.0/aspectRatio+0.499999));
00256                     }
00257                     
00258                     osg::notify(osg::INFO)<<"computed numTilesWideAtLod0 = "<<numTilesWideAtLod0<<std::endl;
00259                     osg::notify(osg::INFO)<<"computed numTilesHightAtLod0 = "<<numTilesHighAtLod0<<std::endl;
00260                     
00261                     if ( options.valid() )
00262                     {
00263                         if ( options->getPluginData( PROPERTY_NUM_TILES_WIDE_AT_LOD0 ) )
00264                             numTilesWideAtLod0 = atoi( (const char*)options->getPluginData( PROPERTY_NUM_TILES_WIDE_AT_LOD0 ) );
00265 
00266                         if ( options->getPluginData( PROPERTY_NUM_TILES_HIGH_AT_LOD0 ) )
00267                             numTilesHighAtLod0 = atoi( (const char*)options->getPluginData( PROPERTY_NUM_TILES_HIGH_AT_LOD0 ) );
00268                     }
00269 
00270                     osg::notify(osg::INFO)<<"final numTilesWideAtLod0 = "<<numTilesWideAtLod0<<std::endl;
00271                     osg::notify(osg::INFO)<<"final numTilesHightAtLod0 = "<<numTilesHighAtLod0<<std::endl;
00272                    
00273                     profile = osgEarth::Profile::create( 
00274                         srs,
00275                         osg::RadiansToDegrees(min_x), 
00276                         osg::RadiansToDegrees(min_y), 
00277                         osg::RadiansToDegrees(max_x), 
00278                         osg::RadiansToDegrees(max_y),
00279                         numTilesWideAtLod0,
00280                         numTilesHighAtLod0 );
00281                 }
00282                 
00283             }
00284             else
00285             {
00286                 osg::notify(osg::NOTICE)<<"Unable to read file "<<url<<std::endl;
00287                 url = "";
00288             }
00289         }
00290         else 
00291         {
00292             osg::notify(osg::NOTICE)<<"No data referenced "<<std::endl;
00293         }
00294 
00295     }
00296     
00297     std::string createTileName( int level, int tile_x, int tile_y )
00298     {
00299         init();
00300         std::stringstream buf;
00301         if (directory_structure==FLAT)
00302         {
00303              buf<<path<<"/"<<base_name<<"_L"<<level<<"_X"<<tile_x/2<<"_Y"<<tile_y/2<<"_subtile."<<extension;
00304         }
00305         else
00306         {
00307             if (level<primary_split_level)
00308             {
00309                 buf<<path<<"/"<<base_name<<"_root_L0_X0_Y0/"<<
00310                      base_name<<"_L"<<level<<"_X"<<tile_x/2<<"_Y"<<tile_y/2<<"_subtile."<<extension;
00311 
00312             }
00313             else if (level<secondary_split_level)
00314             {
00315                 tile_x /= 2;
00316                 tile_y /= 2;
00317 
00318                 int split_x = tile_x >> (level - primary_split_level);
00319                 int split_y = tile_y >> (level - primary_split_level);
00320 
00321                 buf<<path<<"/"<<base_name<<"_subtile_L"<<primary_split_level<<"_X"<<split_x<<"_Y"<<split_y<<"/"<<
00322                      base_name<<"_L"<<level<<"_X"<<tile_x<<"_Y"<<tile_y<<"_subtile."<<extension;
00323             }
00324             else if (directory_structure==NESTED_TASK_DIRECTORIES)
00325             {
00326                 tile_x /= 2;
00327                 tile_y /= 2;
00328 
00329                 int split_x = tile_x >> (level - primary_split_level);
00330                 int split_y = tile_y >> (level - primary_split_level);
00331 
00332                 int secondary_split_x = tile_x >> (level - secondary_split_level);
00333                 int secondary_split_y = tile_y >> (level - secondary_split_level);
00334 
00335                 buf<<path<<"/"<<base_name<<"_subtile_L"<<primary_split_level<<"_X"<<split_x<<"_Y"<<split_y<<"/"<<
00336                      base_name<<"_subtile_L"<<secondary_split_level<<"_X"<<secondary_split_x<<"_Y"<<secondary_split_y<<"/"<< 
00337                      base_name<<"_L"<<level<<"_X"<<tile_x<<"_Y"<<tile_y<<"_subtile."<<extension;
00338             }
00339             else
00340             {
00341                 tile_x /= 2;
00342                 tile_y /= 2;
00343 
00344                 int split_x = tile_x >> (level - secondary_split_level);
00345                 int split_y = tile_y >> (level - secondary_split_level);
00346 
00347                 buf<<path<<"/"<<base_name<<"_subtile_L"<<secondary_split_level<<"_X"<<split_x<<"_Y"<<split_y<<"/"<<
00348                      base_name<<"_L"<<level<<"_X"<<tile_x<<"_Y"<<tile_y<<"_subtile."<<extension;
00349             }
00350         }
00351         
00352         osg::notify(osg::INFO)<<"VPBDatabase::createTileName(), buf.str()=="<<buf.str()<<std::endl;
00353         
00354         return buf.str();
00355     }
00356     
00357     osgTerrain::TerrainTile* getTerrainTile( const TileKey* key, ProgressCallback* progress )
00358     {
00359         init();
00360         int level = key->getLevelOfDetail();
00361         unsigned int tile_x, tile_y;
00362         key->getTileXY( tile_x, tile_y );
00363         
00364         int max_x = (2 << level) - 1;
00365         int max_y = (1 << level) - 1;
00366         
00367         tile_y = max_y - tile_y;
00368 
00369         osgTerrain::TileID tileID(level, tile_x, tile_y);
00370 
00371         osg::ref_ptr<osgTerrain::TerrainTile> tile = findTile(tileID, false);
00372         if (tile.valid()) return tile.get();
00373         
00374         osg::notify(osg::INFO)<<"Max_x = "<<max_x<<std::endl;
00375         osg::notify(osg::INFO)<<"Max_y = "<<max_y<<std::endl;
00376 
00377         osg::notify(osg::INFO)<<"base_name = "<<base_name<<" psl="<<primary_split_level<<" ssl="<<secondary_split_level<<std::endl;
00378         osg::notify(osg::INFO)<<"level = "<<level<<", x = "<<tile_x<<", tile_y = "<<tile_y<<std::endl;
00379         osg::notify(osg::INFO)<<"tile_name "<<createTileName(level, tile_x, tile_y)<<std::endl;
00380         osg::notify(osg::INFO)<<"thread "<<OpenThreads::Thread::CurrentThread()<<std::endl;
00381 
00382         std::string filename = createTileName(level, tile_x, tile_y);
00383         
00384         {
00385             OpenThreads::ScopedLock<OpenThreads::Mutex> lock(blacklistMutex);
00386             if (blacklistedFilenames.count(filename)==1)
00387             {
00388                 osg::notify(osg::INFO)<<"file has been found in black list : "<<filename<<std::endl;
00389 
00390                 insertTile(tileID, 0);
00391                 return 0;
00392             }
00393         }
00394         
00395 
00396         osg::ref_ptr<osgDB::ReaderWriter::Options> localOptions = new osgDB::ReaderWriter::Options;
00397         localOptions->setPluginData("osgearth_vpb Plugin",(void*)(1));
00398 
00399         //osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(filename, localOptions.get());
00400         osg::ref_ptr<osg::Node> node;
00401         if (osgDB::containsServerAddress( filename ) )
00402         {
00403             node = HTTPClient::readNodeFile( filename, localOptions.get(), progress );
00404         }
00405         else
00406         {
00407             node = osgDB::readNodeFile( filename, localOptions.get() );
00408         }
00409 
00410         if (node.valid())
00411         {
00412             osg::notify(osg::INFO)<<"Loaded model "<<filename<<std::endl;
00413             CollectTiles ct;
00414             node->accept(ct);
00415 
00416             int base_x = (tile_x / 2) * 2;
00417             int base_y = (tile_y / 2) * 2;
00418             
00419             double min_x, max_x, min_y, max_y;
00420             ct.getRange(min_x, min_y, max_x, max_y);
00421 
00422             double center_x = (min_x + max_x)*0.5;
00423             double center_y = (min_y + max_y)*0.5;
00424 
00425             osg::Vec3d local(0.5,0.5,0.0);
00426             for(unsigned int i=0; i<ct._terrainTiles.size(); ++i)
00427             {
00428                 osgTerrain::TerrainTile* tile = ct._terrainTiles[i].get();
00429                 osgTerrain::Locator* locator = tile->getLocator();
00430                 if (locator)
00431                 {
00432                     osg::Vec3d projected = local * locator->getTransform();
00433                     
00434                     int local_x = base_x + ((projected.x() > center_x) ? 1 : 0);
00435                     int local_y = base_y + ((projected.y() > center_y) ? 1 : 0);
00436                     osgTerrain::TileID local_tileID(level, local_x, local_y);
00437                     
00438                     tile->setTileID(local_tileID);
00439                     insertTile(local_tileID, tile);
00440                 }
00441 
00442             }
00443 
00444         }
00445         else
00446         {
00447             //Only blacklist if the request wasn't cancelled by the callback.
00448             if (!progress || (!progress->isCanceled()))
00449             {
00450                 osg::notify(osg::INFO)<<"Black listing : "<<filename<<std::endl;
00451                 OpenThreads::ScopedLock<OpenThreads::Mutex> lock(blacklistMutex);
00452                 blacklistedFilenames.insert(filename);
00453             }
00454         }
00455         
00456         return findTile(tileID, true);
00457     }
00458     
00459     void insertTile(const osgTerrain::TileID& tileID, osgTerrain::TerrainTile* tile)
00460     {
00461         init();
00462         OpenThreads::ScopedLock<OpenThreads::Mutex> lock(tileMapMutex);
00463 
00464         if ( tileMap.find(tileID) == tileMap.end() )
00465         {
00466             tileMap[tileID] = tile;
00467 
00468             tileFIFO.push_back(tileID);
00469 
00470             if (tileFIFO.size()>maxNumTilesInCache)
00471             {
00472                 osgTerrain::TileID tileToRemove = tileFIFO.front();
00473                 tileFIFO.pop_front();
00474                 tileMap.erase(tileToRemove);
00475 
00476                             osg::notify(osg::INFO)<<"Pruned tileID ("<<TileKey::getLOD(tileID)<<", "<<tileID.x<<", "<<tileID.y<<")"<<std::endl;
00477             }
00478 
00479             osg::notify(osg::INFO)<<"insertTile ("
00480                 << TileKey::getLOD(tileID)<<", "<<tileID.x<<", "<<tileID.y<<") " 
00481                 << " tileFIFO.size()=="<<tileFIFO.size()<<std::endl;
00482         }
00483         else
00484         {
00485             osg::notify(osg::INFO)<<"insertTile ("
00486                 << TileKey::getLOD(tileID)<<", "<<tileID.x<<", "<<tileID.y<<") " 
00487                 << " ...already in cache!"<<std::endl;
00488         }
00489     }
00490 
00491     osgTerrain::TerrainTile* findTile(const osgTerrain::TileID& tileID, bool insertBlankTileIfNotFound = false)
00492     {
00493         init();
00494         {
00495             OpenThreads::ScopedLock<OpenThreads::Mutex> lock(tileMapMutex);
00496             TileMap::iterator itr = tileMap.find(tileID);
00497             if (itr!=tileMap.end()) return itr->second.get();
00498         }
00499 
00500         if (insertBlankTileIfNotFound) insertTile(tileID, 0);
00501 
00502         return 0;
00503     }
00504 
00505     const Profile* getProfile() 
00506     {
00507         init();
00508         return profile.get();
00509     }
00510 
00511     const std::string& getExtension()
00512     {
00513         init();
00514         return extension;
00515     }
00516 
00517     bool initialized;
00518 
00519     osg::ref_ptr<const PluginOptions> options;
00520     std::string url;
00521     std::string path;
00522     std::string base_name;
00523     std::string extension;
00524     int primary_split_level;
00525     int secondary_split_level;
00526     DirectoryStructure directory_structure;
00527 
00528     osg::ref_ptr<const Profile> profile;
00529     osg::ref_ptr<osg::Node> root_node;
00530     
00531     unsigned int maxNumTilesInCache;
00532     
00533     typedef std::map<osgTerrain::TileID, osg::ref_ptr<osgTerrain::TerrainTile> > TileMap;
00534     TileMap tileMap;
00535     OpenThreads::Mutex tileMapMutex;
00536     
00537     typedef std::list<osgTerrain::TileID> TileIDList;
00538     TileIDList tileFIFO;
00539     
00540     typedef std::set<std::string> StringSet;
00541     StringSet blacklistedFilenames;
00542     OpenThreads::Mutex blacklistMutex;
00543     
00544 };
00545 
00546 class VPBSource : public TileSource
00547 {
00548 public:
00549     VPBSource( VPBDatabase* vpbDatabase, const PluginOptions* in_options) :  
00550       TileSource(in_options),
00551       _vpbDatabase(vpbDatabase),
00552       _layerNum(0)
00553     {
00554         if ( in_options )
00555         {
00556             _layerNum = in_options->config().value<int>( PROPERTY_LAYER_NUM, _layerNum );
00557         }
00558     }
00559 
00560     void initialize( const std::string& referenceURI, const Profile* overrideProfile)
00561     {
00562                 if ( overrideProfile)
00563                 {
00564                         setProfile( overrideProfile );
00565                 }
00566                 else
00567                 {
00568                         setProfile( _vpbDatabase->getProfile() ); //profile.get() );
00569                 }
00570     }
00571     
00572     osg::Image* createImage( const TileKey* key,
00573                              ProgressCallback* progress)
00574     {
00575         //TODO:  Make VPB driver use progress callback
00576         osg::ref_ptr<osgTerrain::TerrainTile> tile = _vpbDatabase->getTerrainTile(key, progress);                
00577         if (tile.valid())
00578         {        
00579             if (_layerNum < tile->getNumColorLayers())
00580             {
00581                 osgTerrain::Layer* layer = tile->getColorLayer(_layerNum);
00582                 osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(layer);
00583                 if (imageLayer)
00584                 {
00585                     return imageLayer->getImage();
00586                 }
00587             }
00588         }
00589         
00590         return 0;
00591     }
00592 
00593     osg::HeightField* createHeightField( const TileKey* key,
00594                                          ProgressCallback* progress
00595                                          )
00596     {
00597         osg::ref_ptr<osgTerrain::TerrainTile> tile = _vpbDatabase->getTerrainTile(key, progress);                
00598         if (tile.valid())
00599         {        
00600             osgTerrain::Layer* elevationLayer = tile->getElevationLayer();
00601             osgTerrain::HeightFieldLayer* hfLayer = dynamic_cast<osgTerrain::HeightFieldLayer*>(elevationLayer);
00602             if (hfLayer) 
00603             {
00604                 return hfLayer->getHeightField();
00605             }
00606         }
00607 
00608         return 0;
00609     }
00610 
00611     virtual std::string getExtension()  const 
00612     {
00613         //All VPB tiles are in IVE format
00614         return _vpbDatabase->getExtension();
00615     }
00616 
00617 private:
00618     osg::ref_ptr<VPBDatabase>   _vpbDatabase;
00619     unsigned int                _layerNum;
00620     osg::ref_ptr<PluginOptions> _options;
00621 };
00622 
00623 
00624 class ReaderWriterVPB : public osgDB::ReaderWriter
00625 {
00626     public:
00627         ReaderWriterVPB()
00628         {
00629             supportsExtension( "osgearth_vpb", "VirtualPlanetBuilder data" );
00630         }
00631 
00632         virtual const char* className()
00633         {
00634             return "VirtualPlanetBuilder ReaderWriter";
00635         }
00636 
00637         virtual ReadResult readObject(const std::string& file_name, const Options* options) const
00638         {
00639             if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
00640                 return ReadResult::FILE_NOT_HANDLED;
00641 
00642             const PluginOptions* pluginOpts = static_cast<const PluginOptions*>( options );
00643 
00644             //osg::notify(osg::NOTICE) << pluginOpts->config().toString() << std::endl;
00645 
00646             std::string url = pluginOpts->config().value( PROPERTY_URL );
00647             if ( !url.empty() )
00648             {                
00649                 OpenThreads::ScopedLock<OpenThreads::Mutex> lock(vpbDatabaseMapMutex);
00650                 osg::observer_ptr<VPBDatabase>& db_ptr = vpbDatabaseMap[url];
00651                 
00652                 if (!db_ptr) db_ptr = new VPBDatabase( pluginOpts );
00653                 
00654                 if (db_ptr.valid()) return new VPBSource(db_ptr.get(), pluginOpts );
00655                 else return ReadResult::FILE_NOT_FOUND;               
00656             }
00657             else
00658             {
00659                 return ReadResult::FILE_NOT_HANDLED;
00660             }
00661         }
00662         
00663         typedef std::map<std::string, osg::observer_ptr<VPBDatabase> > VPBDatabaseMap;
00664         mutable OpenThreads::Mutex vpbDatabaseMapMutex;
00665         mutable VPBDatabaseMap vpbDatabaseMap;
00666 };
00667 
00668 REGISTER_OSGPLUGIN(osgearth_vpb, ReaderWriterVPB)
00669 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines