osgEarth 2.1.1

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

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003  * Copyright 2008-2010 Pelican Mapping
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 #include <osgEarth/FileUtils>
00024 #include <osgEarth/ThreadingUtils>
00025 
00026 #include <osg/Notify>
00027 #include <osg/io_utils>
00028 #include <osg/Version>
00029 #include <osgTerrain/Terrain>
00030 
00031 #include <osgDB/FileNameUtils>
00032 #include <osgDB/FileUtils>
00033 #include <osgDB/Registry>
00034 #include <osgDB/ReadFile>
00035 #include <osgDB/WriteFile>
00036 
00037 #include <sstream>
00038 
00039 #include "VPBOptions"
00040 
00041 #define LC "[VPB] "
00042 
00043 using namespace osgEarth;
00044 using namespace osgEarth::Drivers;
00045 
00046 //#define PROPERTY_URL                    "url"
00047 //#define PROPERTY_PRIMARY_SPLIT_LEVEL    "primary_split_level"
00048 //#define PROPERTY_SECONDARY_SPLIT_LEVEL  "secondary_split_level"
00049 //#define PROPERTY_DIRECTORY_STRUCTURE    "directory_structure"
00050 //#define PROPERTY_LAYER_NUM              "layer"
00051 //#define PROPERTY_NUM_TILES_WIDE_AT_LOD0 "num_tiles_wide_at_lod0"
00052 //#define PROPERTY_NUM_TILES_HIGH_AT_LOD0 "num_tiles_high_at_lod0"
00053 //#define PROPERTY_BASE_NAME              "base_name"
00054 
00055 
00056 class CollectTiles : public osg::NodeVisitor
00057 {
00058 public:
00059 
00060     CollectTiles(): 
00061         osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
00062     {
00063     }
00064     
00065     void reset()
00066     {
00067         _terrainTiles.clear();
00068     }
00069     
00070     void apply(osg::Group& group)
00071     {
00072         osgTerrain::TerrainTile* terrainTile = dynamic_cast<osgTerrain::TerrainTile*>(&group);
00073         if (terrainTile)
00074         {
00075             OE_DEBUG<<"VPB: Found terrain tile TileID("<<
00076                                 TileKey::getLOD(terrainTile->getTileID())<<", "<<
00077                 terrainTile->getTileID().x<<", "<<
00078                 terrainTile->getTileID().y<<")"<<std::endl;
00079             
00080             _terrainTiles.push_back(terrainTile);
00081         }
00082         else
00083         {
00084             traverse(group);
00085         }
00086     }
00087     
00088     osgTerrain::Locator* getLocator()
00089     {
00090         for(unsigned int i=0; i<_terrainTiles.size(); ++i)
00091         {
00092             osgTerrain::TerrainTile* tile = _terrainTiles[i].get();
00093             osgTerrain::Locator* locator = tile->getLocator();
00094             if (locator) return locator;
00095         }
00096         return 0;
00097     }
00098 
00099     bool getRange(double& min_x, double& min_y, double& max_x, double& max_y) const
00100     {
00101         min_x = DBL_MAX;
00102         max_x = -DBL_MAX;
00103         min_y = DBL_MAX;
00104         max_y = -DBL_MAX;
00105         
00106         typedef std::vector<osg::Vec3d> Corners;
00107         Corners corners;
00108         corners.push_back(osg::Vec3d(0.0f,0.0f,0.0f));
00109         corners.push_back(osg::Vec3d(1.0f,0.0f,0.0f));
00110         corners.push_back(osg::Vec3d(1.0f,1.0f,0.0f));
00111         corners.push_back(osg::Vec3d(1.0f,1.0f,0.0f));
00112         
00113         for(unsigned int i=0; i<_terrainTiles.size(); ++i)
00114         {
00115             osgTerrain::TerrainTile* tile = _terrainTiles[i].get();
00116             osgTerrain::Locator* locator = tile->getLocator();
00117             if (locator)
00118             {
00119                 for(Corners::iterator itr = corners.begin();
00120                     itr != corners.end();
00121                     ++itr)
00122                 {
00123                     osg::Vec3d& local = *itr;
00124                     osg::Vec3d projected = local * locator->getTransform();
00125 
00126                     if (projected.x()<min_x) min_x = projected.x();
00127                     if (projected.x()>max_x) max_x = projected.x();
00128 
00129                     if (projected.y()<min_y) min_y = projected.y();
00130                     if (projected.y()>max_y) max_y = projected.y();
00131                 }
00132             }
00133         }
00134         
00135         return min_x <= max_x;
00136     }
00137     
00138     typedef std::vector< osg::ref_ptr<osgTerrain::TerrainTile> > TerrainTiles;
00139     TerrainTiles _terrainTiles;
00140 };
00141 
00142 
00143 class VPBDatabase : public osg::Referenced
00144 {
00145 public:
00146     VPBDatabase( const VPBOptions& in_options ) :
00147         _options( in_options ),
00148         //_directory_structure( FLAT_TASK_DIRECTORIES ),
00149         _profile( osgEarth::Registry::instance()->getGlobalGeodeticProfile() ),
00150         _maxNumTilesInCache( 128 ),
00151         _initialized( false )
00152     {
00153         }
00154         
00155         void initialize( const std::string& referenceURI)
00156         {
00157         Threading::ScopedMutexLock lock( _initializeMutex );
00158 
00159         if ( _initialized )
00160             return;
00161 
00162         unsigned int numTilesWideAtLod0, numTilesHighAtLod0;
00163         _profile->getNumTiles(0, numTilesWideAtLod0, numTilesHighAtLod0);
00164 
00165         // validate dataset
00166         _url = _options.url().value();
00167 
00168         if ( !_url.empty() )
00169         {
00170                         //If the path doesn't contain a server address, get the full path to the file.
00171                         if (!osgDB::containsServerAddress( *_url ))
00172                         {
00173                 //todo: obselete..?
00174                 _url = URI(_url.full(), referenceURI);
00175                                 //_url = osgEarth::getFullPath(referenceURI, _url);
00176                         }
00177                         
00178             osg::ref_ptr<osgDB::ReaderWriter::Options> localOptions = new osgDB::ReaderWriter::Options;
00179             localOptions->setPluginData("osgearth_vpb Plugin",(void*)(1));
00180             //_rootNode = osgDB::readNodeFile( _url, localOptions.get() );
00181 
00182             HTTPClient::ResultCode rc = HTTPClient::readNodeFile( _url.full(), _rootNode, localOptions.get() );
00183 
00184             if ( rc == HTTPClient::RESULT_OK && _rootNode.valid() )
00185             {
00186                 _baseNameToUse = _options.baseName().value();
00187 
00188                 _path = osgDB::getFilePath( *_url );
00189                 if ( _baseNameToUse.empty() )
00190                     _baseNameToUse = osgDB::getStrippedName( *_url );
00191                 _extension = osgDB::getFileExtension( *_url );
00192                 
00193                 OE_INFO << LC << "Loaded root "<< _url.full() <<", path="<<_path<<" base_name="<<_baseNameToUse<<" extension="<<_extension<<std::endl;
00194                 
00195                 std::string srs = _profile->getSRS()->getInitString(); //.srs();
00196                 
00197                 osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(_rootNode.get());
00198                 if (csn)
00199                 {
00200                     OE_INFO << LC << "CSN found: "<<csn->getCoordinateSystem()<<std::endl;
00201                     
00202                     srs = csn->getCoordinateSystem();
00203                 }
00204 
00205                 CollectTiles ct;
00206                 _rootNode->accept(ct);
00207 
00208                     
00209                 osgTerrain::Locator* locator = ct.getLocator();
00210                 if (locator)
00211                 {
00212                     double min_x, max_x, min_y, max_y;
00213                     ct.getRange(min_x, min_y, max_x, max_y);
00214 
00215                     OE_DEBUG << LC << "range("<<min_x<<", "<<min_y<<", "<<max_x<<", "<<max_y<< ")" <<std::endl;
00216                                         OE_DEBUG << LC << "range("<<osg::RadiansToDegrees(min_x)<<", "<<osg::RadiansToDegrees(min_y)<<", "
00217                                                 <<osg::RadiansToDegrees(max_x)<<", "<<osg::RadiansToDegrees(max_y)<< ")" <<std::endl;
00218 
00219                     srs = locator->getCoordinateSystem();
00220 
00221                     double aspectRatio = (max_x-min_x)/(max_y-min_y);
00222                     
00223                     OE_DEBUG << LC << "aspectRatio = "<<aspectRatio<<std::endl;
00224 
00225                     if (aspectRatio>1.0)
00226                     {
00227                         numTilesWideAtLod0 = static_cast<unsigned int>(floor(aspectRatio+0.499999));
00228                         numTilesHighAtLod0 = 1;
00229                     }
00230                     else
00231                     {
00232                         numTilesWideAtLod0 = 1;
00233                         numTilesHighAtLod0 = static_cast<unsigned int>(floor(1.0/aspectRatio+0.499999));
00234                     }
00235                     
00236                     OE_DEBUG << LC << "computed numTilesWideAtLod0 = "<<numTilesWideAtLod0<<std::endl;
00237                     OE_DEBUG << LC << "computed numTilesHightAtLod0 = "<<numTilesHighAtLod0<<std::endl;
00238                     
00239                     //if ( _options.valid() )
00240                     {
00241                         if ( _options.numTilesWideAtLod0().isSet() )
00242                             numTilesWideAtLod0 = _options.numTilesWideAtLod0().value();
00243 
00244                         if ( _options.numTilesHighAtLod0().isSet() )
00245                             numTilesHighAtLod0 = _options.numTilesHighAtLod0().value();
00246                     }
00247 
00248                     OE_DEBUG << LC << "final numTilesWideAtLod0 = "<<numTilesWideAtLod0<<std::endl;
00249                     OE_DEBUG << LC << "final numTilesHightAtLod0 = "<<numTilesHighAtLod0<<std::endl;
00250                    
00251                     _profile = osgEarth::Profile::create( 
00252                         srs,
00253                         osg::RadiansToDegrees(min_x), 
00254                         osg::RadiansToDegrees(min_y), 
00255                         osg::RadiansToDegrees(max_x), 
00256                         osg::RadiansToDegrees(max_y),
00257                         "",
00258                         numTilesWideAtLod0,
00259                         numTilesHighAtLod0 );
00260                 }
00261                 
00262             }
00263             else
00264             {
00265                 OE_WARN << LC << HTTPClient::getResultCodeString(rc) << ": " << *_url << std::endl;
00266                 _url = URI();
00267             }
00268         }
00269         else 
00270         {
00271             OE_WARN<<"VPB: No data referenced "<<std::endl;
00272         }
00273         
00274         _initialized = true;
00275     }
00276     
00277     std::string createTileName( int level, int tile_x, int tile_y )
00278     {
00279         std::stringstream buf;
00280         if ( _options.directoryStructure() == VPBOptions::DS_FLAT )
00281         {
00282              buf<<_path<<"/"<<_baseNameToUse<<"_L"<<level<<"_X"<<tile_x/2<<"_Y"<<tile_y/2<<"_subtile."<<_extension;
00283         }
00284         else
00285         {
00286             int psl = _options.primarySplitLevel().value();
00287             int ssl = _options.secondarySplitLevel().value();
00288 
00289             if (level<psl)
00290             {
00291                 buf<<_path<<"/"<<_baseNameToUse<<"_root_L0_X0_Y0/"<<
00292                      _baseNameToUse<<"_L"<<level<<"_X"<<tile_x/2<<"_Y"<<tile_y/2<<"_subtile."<<_extension;
00293 
00294             }
00295             else if (level<ssl)
00296             {
00297                 tile_x /= 2;
00298                 tile_y /= 2;
00299 
00300                 int split_x = tile_x >> (level - psl);
00301                 int split_y = tile_y >> (level - psl);
00302 
00303                 buf<<_path<<"/"<<_baseNameToUse<<"_subtile_L"<<psl<<"_X"<<split_x<<"_Y"<<split_y<<"/"<<
00304                      _baseNameToUse<<"_L"<<level<<"_X"<<tile_x<<"_Y"<<tile_y<<"_subtile."<<_extension;
00305             }
00306             else if ( _options.directoryStructure() == VPBOptions::DS_TASK )
00307             {
00308                 tile_x /= 2;
00309                 tile_y /= 2;
00310 
00311                 int split_x = tile_x >> (level - psl);
00312                 int split_y = tile_y >> (level - psl);
00313 
00314                 int secondary_split_x = tile_x >> (level - ssl);
00315                 int secondary_split_y = tile_y >> (level - ssl);
00316 
00317                 buf<<_path<<"/"<<_baseNameToUse<<"_subtile_L"<<psl<<"_X"<<split_x<<"_Y"<<split_y<<"/"<<
00318                      _baseNameToUse<<"_subtile_L"<<ssl<<"_X"<<secondary_split_x<<"_Y"<<secondary_split_y<<"/"<< 
00319                      _baseNameToUse<<"_L"<<level<<"_X"<<tile_x<<"_Y"<<tile_y<<"_subtile."<<_extension;
00320             }
00321             else
00322             {
00323                 tile_x /= 2;
00324                 tile_y /= 2;
00325 
00326                 int split_x = tile_x >> (level - ssl);
00327                 int split_y = tile_y >> (level - ssl);
00328 
00329                 buf<<_path<<"/"<<_baseNameToUse<<"_subtile_L"<<ssl<<"_X"<<split_x<<"_Y"<<split_y<<"/"<<
00330                      _baseNameToUse<<"_L"<<level<<"_X"<<tile_x<<"_Y"<<tile_y<<"_subtile."<<_extension;
00331             }
00332         }
00333         
00334                 std::string bufStr;
00335                 bufStr = buf.str();
00336         OE_DEBUG<<"VPB: VPBDatabase::createTileName(), buf.str()=="<< bufStr <<std::endl;
00337         
00338                 return bufStr;
00339     }
00340     
00341     void getTerrainTile( const TileKey& key, ProgressCallback* progress, osg::ref_ptr<osgTerrain::TerrainTile>& out_tile )
00342     {
00343         int level = key.getLevelOfDetail();
00344         unsigned int tile_x, tile_y;
00345         key.getTileXY( tile_x, tile_y );
00346         
00347         //int max_x = (2 << level) - 1;
00348         int max_y = (1 << level) - 1;
00349         
00350         tile_y = max_y - tile_y;
00351 
00352         osgTerrain::TileID tileID(level, tile_x, tile_y);
00353 
00354         findTile(tileID, false, out_tile);
00355         if (out_tile.valid()) 
00356             return;
00357 
00358         std::string filename = createTileName(level, tile_x, tile_y);
00359         
00360         bool foundInBlacklist = false;
00361         {
00362             Threading::ScopedReadLock sharedLock( _blacklistMutex );
00363             foundInBlacklist = _blacklistedFilenames.count(filename) == 1;
00364         }
00365         if ( foundInBlacklist )
00366         {
00367             OE_DEBUG << LC << "file has been found in black list : "<<filename<<std::endl;
00368             insertTile(tileID, 0);
00369             return; //return 0;
00370         }
00371 
00372         //    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_blacklistMutex);
00373         //    if (_blacklistedFilenames.count(filename)==1)
00374         //    {
00375         //        OE_DEBUG<<"VPB: file has been found in black list : "<<filename<<std::endl;
00376         //        insertTile(tileID, 0);
00377         //        return 0;
00378         //    }
00379         //}
00380         
00381 
00382         osg::ref_ptr<osgDB::ReaderWriter::Options> localOptions = new osgDB::ReaderWriter::Options;
00383         localOptions->setPluginData("osgearth_vpb Plugin",(void*)(1));
00384 
00385 
00386         //osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(filename, localOptions.get());
00387         osg::ref_ptr<osg::Node> node;
00388         HTTPClient::ResultCode result = HTTPClient::readNodeFile( filename, node, localOptions.get(), progress );
00389         if ( result == HTTPClient::RESULT_OK && node.valid() )
00390         {
00391             //OE_INFO << LC << "Loaded model "<<filename<<std::endl;
00392             CollectTiles ct;
00393             node->accept(ct);
00394 
00395             int base_x = (tile_x / 2) * 2;
00396             int base_y = (tile_y / 2) * 2;
00397             
00398             double min_x, max_x, min_y, max_y;
00399             ct.getRange(min_x, min_y, max_x, max_y);
00400 
00401             double center_x = (min_x + max_x)*0.5;
00402             double center_y = (min_y + max_y)*0.5;
00403 
00404             osg::Vec3d local(0.5,0.5,0.0);
00405             for(unsigned int i=0; i<ct._terrainTiles.size(); ++i)
00406             {
00407                 osgTerrain::TerrainTile* tile = ct._terrainTiles[i].get();
00408                 osgTerrain::Locator* locator = tile->getLocator();
00409                 if (locator)
00410                 {
00411                     osg::Vec3d projected = local * locator->getTransform();
00412                     
00413                     int local_x = base_x + ((projected.x() > center_x) ? 1 : 0);
00414                     int local_y = base_y + ((projected.y() > center_y) ? 1 : 0);
00415                     osgTerrain::TileID local_tileID(level, local_x, local_y);
00416                     
00417                     tile->setTileID(local_tileID);
00418                     insertTile(local_tileID, tile);
00419 
00420                     if ( local_tileID == tileID )
00421                         out_tile = tile;
00422                 }
00423 
00424             }
00425 
00426         }
00427         else
00428         {
00429             // in the case of an "unrecoverable" error, black-list the URL for this tile.
00430             if ( ! HTTPClient::isRecoverable( result ) )
00431             {
00432                 Threading::ScopedWriteLock exclusiveLock( _blacklistMutex );
00433                 _blacklistedFilenames.insert( filename );
00434             }
00435         }
00436         
00437         //TODO: just return it instead...
00438         //findTile(tileID, false, out_tile);
00439     }
00440     
00441     void insertTile(const osgTerrain::TileID& tileID, osgTerrain::TerrainTile* tile)
00442     {
00443         Threading::ScopedWriteLock exclusiveLock( _tileMapMutex );
00444 
00445         if ( _tileMap.find(tileID) == _tileMap.end() )
00446         {
00447             _tileMap[tileID] = tile;
00448 
00449             _tileFIFO.push_back(tileID);
00450 
00451             if (_tileFIFO.size() > _maxNumTilesInCache)
00452             {
00453                 osgTerrain::TileID tileToRemove = _tileFIFO.front();
00454                 _tileFIFO.pop_front();
00455                 _tileMap.erase(tileToRemove);
00456 
00457                 OE_DEBUG << LC << "Pruned tileID ("<<TileKey::getLOD(tileID)<<", "<<tileID.x<<", "<<tileID.y<<")"<<std::endl;
00458             }
00459 
00460             OE_DEBUG << LC << "insertTile ("
00461                 << TileKey::getLOD(tileID)<<", "<<tileID.x<<", "<<tileID.y<<") " 
00462                 << " tileFIFO.size()=="<<_tileFIFO.size()<<std::endl;
00463         }
00464         else
00465         {
00466             OE_DEBUG << LC << "insertTile ("
00467                 << TileKey::getLOD(tileID)<<", "<<tileID.x<<", "<<tileID.y<<") " 
00468                 << " ...already in cache!"<<std::endl;
00469         }
00470     }
00471 
00472     void findTile(const osgTerrain::TileID& tileID, bool insertBlankTileIfNotFound, osg::ref_ptr<osgTerrain::TerrainTile>& out_tile)
00473     {
00474         // read with a shared lock
00475         {
00476             Threading::ScopedReadLock sharedLock( _tileMapMutex );
00477             TileMap::iterator itr = _tileMap.find(tileID);
00478             if (itr != _tileMap.end())
00479                 out_tile = itr->second.get();
00480         }
00481 
00482         // upgrade lock and write:
00483         if (insertBlankTileIfNotFound) 
00484             insertTile(tileID, 0);
00485 
00486         //return 0;
00487     }
00488 
00489     const VPBOptions _options;
00490     URI _url;
00491     std::string _path;
00492     std::string _extension;
00493 
00494     std::string _baseNameToUse;
00495 
00496     osg::ref_ptr<const Profile> _profile;
00497     osg::ref_ptr<osg::Node> _rootNode;
00498     
00499     unsigned int _maxNumTilesInCache;
00500     
00501     typedef std::map<osgTerrain::TileID, osg::ref_ptr<osgTerrain::TerrainTile> > TileMap;
00502     TileMap _tileMap;
00503     Threading::ReadWriteMutex _tileMapMutex;
00504     
00505     typedef std::list<osgTerrain::TileID> TileIDList;
00506     TileIDList _tileFIFO;
00507     
00508     typedef std::set<std::string> StringSet;
00509     StringSet _blacklistedFilenames;
00510     Threading::ReadWriteMutex _blacklistMutex;
00511 
00512     bool _initialized;
00513     Threading::Mutex _initializeMutex;
00514     
00515 };
00516 
00517 class VPBSource : public TileSource
00518 {
00519 public:
00520     VPBSource( VPBDatabase* vpbDatabase, const VPBOptions& in_options ) : 
00521         TileSource(in_options),
00522         _vpbDatabase(vpbDatabase),
00523         _options( in_options ),
00524         _referenceUri()
00525     {
00526         //nop
00527     }
00528 
00529     void initialize( const std::string& referenceURI, const Profile* overrideProfile)
00530     {
00531             _referenceUri = referenceURI;
00532 
00533             _vpbDatabase->initialize(referenceURI);
00534 
00535             if ( overrideProfile)
00536             {
00537                     setProfile( overrideProfile );
00538             }
00539             else
00540             {
00541                     setProfile(_vpbDatabase->_profile.get());
00542             }
00543     }
00544     
00545         osg::Image* createImage( const TileKey& key, ProgressCallback* progress)
00546         {
00547                 osg::Image * ret = NULL;
00548                 //TODO:  Make VPB driver use progress callback
00549                 osg::ref_ptr<osgTerrain::TerrainTile> tile;
00550         _vpbDatabase->getTerrainTile(key, progress, tile);
00551                 if (tile.valid())
00552                 {        
00553                         int layerNum = _options.layer().value();
00554                         const optional<std::string> & layerSetName = _options.layerSetName();
00555 
00556                         int numColorLayers = (int)tile->getNumColorLayers();
00557                         if(layerNum > numColorLayers)
00558                                 layerNum = 0;
00559                         if (layerNum < numColorLayers)
00560                         {
00561                                 osgTerrain::Layer* layer = tile->getColorLayer(layerNum);
00562 
00563                                 osgTerrain::ImageLayer* imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(layer);
00564                                 if (imageLayer)
00565                                 {
00566                                         OE_DEBUG << LC << "createImage(" << key.str() << " layerNum=" << layerNum << ") successful." <<std::endl;
00567                                         ret = new osg::Image( *imageLayer->getImage() );
00568                                 }
00569                                 else
00570                                 {
00571                                         osgTerrain::SwitchLayer* switchLayer = dynamic_cast<osgTerrain::SwitchLayer*>(layer);
00572                                         if (switchLayer && layerSetName.isSet())
00573                                         {
00574                                                 for(unsigned int si=0; !imageLayer && si<switchLayer->getNumLayers(); ++si)
00575                                                 {
00576                                                         if(switchLayer->getSetName(si) == layerSetName.value())
00577                                                         {
00578                                                                 imageLayer = dynamic_cast<osgTerrain::ImageLayer*>(switchLayer->getLayer(si));
00579                                                         }
00580                                                 }
00581                                         }
00582                                         if(imageLayer)
00583                                         {
00584                                                 OE_DEBUG << LC << "createImage(" << key.str() << " layerSet=" << layerSetName.value() << ") successful." <<std::endl;
00585                                                 ret = new osg::Image( *imageLayer->getImage() );
00586                                         }
00587                                 }
00588                         }
00589                         if(!ret)
00590                         {
00591                                 OE_DEBUG << LC << "createImage(" << key.str() << " layerSet=" << layerSetName.value() << " layerNum=" << layerNum << "/" << numColorLayers << ") failed." <<std::endl;
00592                         }
00593                 }
00594                 else
00595                 {
00596                         OE_DEBUG << LC << "createImage(" << key.str() << ") database retrieval failed." <<std::endl;
00597                 }
00598                 return ret;
00599         }
00600 
00601     osg::HeightField* createHeightField( const TileKey& key,
00602                                          ProgressCallback* progress
00603                                          )
00604     {
00605         osg::ref_ptr<osgTerrain::TerrainTile> tile;
00606         _vpbDatabase->getTerrainTile(key, progress, tile);
00607         if (tile.valid())
00608         {        
00609             osgTerrain::Layer* elevationLayer = tile->getElevationLayer();
00610             osgTerrain::HeightFieldLayer* hfLayer = dynamic_cast<osgTerrain::HeightFieldLayer*>(elevationLayer);
00611             if (hfLayer) 
00612             {
00613                 //return hfLayer->getHeightField();
00614                 return new osg::HeightField(*hfLayer->getHeightField());
00615             }
00616         }
00617 
00618         return 0;
00619     }
00620 
00621     virtual std::string getExtension()  const 
00622     {
00623         //All VPB tiles are in IVE format
00624         return _vpbDatabase->_extension;
00625     }
00626 
00627 private:
00628     osg::ref_ptr<VPBDatabase> _vpbDatabase;
00629     const VPBOptions _options;
00630         std::string     _referenceUri;
00631 };
00632 
00633 
00634 class VPBSourceFactory : public TileSourceDriver
00635 {
00636     public:
00637         VPBSourceFactory()
00638         {
00639             supportsExtension( "osgearth_vpb", "VirtualPlanetBuilder data" );
00640         }
00641 
00642         virtual const char* className()
00643         {
00644             return "VirtualPlanetBuilder ReaderWriter";
00645         }
00646 
00647         virtual ReadResult readObject(const std::string& file_name, const Options* options) const
00648         {
00649             if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
00650                 return ReadResult::FILE_NOT_HANDLED;
00651 
00652             VPBOptions vpbOptions( getTileSourceOptions(options) );
00653 
00654             URI url = vpbOptions.url().value();
00655             if ( !url.empty() )
00656             {                
00657                 OpenThreads::ScopedLock<OpenThreads::Mutex> lock(vpbDatabaseMapMutex);
00658                 osg::observer_ptr<VPBDatabase>& db_ptr = vpbDatabaseMap[*url]; //get or create
00659                 
00660                 if (!db_ptr) db_ptr = new VPBDatabase( vpbOptions );
00661                 
00662                 if (db_ptr.valid())
00663                     return new VPBSource( db_ptr.get(), vpbOptions );
00664                 else
00665                     return ReadResult::FILE_NOT_FOUND;               
00666             }
00667             else
00668             {
00669                 return ReadResult::FILE_NOT_HANDLED;
00670             }
00671         }
00672         
00673         typedef std::map<std::string, osg::observer_ptr<VPBDatabase> > VPBDatabaseMap;
00674         mutable OpenThreads::Mutex vpbDatabaseMapMutex;
00675         mutable VPBDatabaseMap vpbDatabaseMap;
00676 };
00677 
00678 REGISTER_OSGPLUGIN(osgearth_vpb, VPBSourceFactory)
00679 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines