osgEarth 2.1.1
|
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 #include "OSGOptions" 00020 00021 #include <osgEarth/HTTPClient> 00022 #include <osgEarth/FileUtils> 00023 #include <osgEarth/ImageUtils> 00024 #include <osgDB/FileNameUtils> 00025 00026 #include <cstring> 00027 00028 #define LC "[OSG Driver] " 00029 00030 #define LOG2(X) (::log((double)(X))/::log(2.0)) 00031 00032 using namespace osgEarth; 00033 using namespace osgEarth::Drivers; 00034 00035 struct CopyAndSetAlpha 00036 { 00037 bool operator()( const osg::Vec4& in, osg::Vec4& out ) { 00038 out = in; 00039 out.a() = 0.3333*(in.r() + in.g() + in.b()); 00040 return true; 00041 } 00042 }; 00043 00044 static 00045 osg::Image* makeRGBAandComputeAlpha(osg::Image* image) 00046 { 00047 osg::Image* result = new osg::Image(); 00048 result->allocateImage( image->s(), image->t(), image->r(), GL_RGBA, GL_UNSIGNED_BYTE ); 00049 result->setInternalTextureFormat( GL_RGBA8 ); 00050 ImageUtils::PixelVisitor<CopyAndSetAlpha>().accept( image, result ); 00051 return result; 00052 } 00053 00054 class OSGTileSource : public TileSource 00055 { 00056 public: 00057 OSGTileSource( const TileSourceOptions& options ) : 00058 TileSource( options ), 00059 _maxDataLevel( 21 ), 00060 _options( options ) 00061 { 00062 //nop 00063 } 00064 00065 void initialize( const std::string& referenceURI, const Profile* overrideProfile) 00066 { 00067 if ( !overrideProfile ) 00068 { 00069 OE_WARN << LC << "An explicit profile definition is required by the OSG driver." << std::endl; 00070 return; 00071 } 00072 00073 setProfile( overrideProfile ); 00074 00075 osg::ref_ptr<osg::Image> image; 00076 00077 URI url = _options.url().value(); 00078 if ( !url.empty() ) 00079 { 00080 url = URI( url.full(), referenceURI ); // obselete? 00081 HTTPClient::ResultCode code = HTTPClient::readImageFile( url.full(), image ); 00082 if ( code != HTTPClient::RESULT_OK ) 00083 { 00084 OE_WARN << LC << "Failed to load data from \"" << url.full() << "\", because: " << 00085 HTTPClient::getResultCodeString(code) << std::endl; 00086 } 00087 } 00088 00089 if ( !image.valid() ) 00090 OE_WARN << LC << "Faild to load data from \"" << url.full() << "\"" << std::endl; 00091 00092 // calculate and store the maximum LOD for which to return data 00093 if ( image.valid() ) 00094 { 00095 int minSpan = osg::minimum( image->s(), image->t() ); 00096 int tileSize = _options.tileSize().value(); 00097 _maxDataLevel = (int)LOG2((minSpan/tileSize)+1); 00098 //OE_NOTICE << "[osgEarth::OSG driver] minSpan=" << minSpan << ", _tileSize=" << tileSize << ", maxDataLevel = " << _maxDataLevel << std::endl; 00099 00100 00101 getDataExtents().push_back( DataExtent(overrideProfile->getExtent(), 0, _maxDataLevel) ); 00102 00103 bool computeAlpha = 00104 (_options.convertLuminanceToRGBA() == true && image->getPixelFormat() == GL_LUMINANCE) || 00105 (_options.addAlpha() == true && !ImageUtils::hasAlphaChannel( image.get() ) ); 00106 00107 if ( computeAlpha ) 00108 { 00109 image = makeRGBAandComputeAlpha( image.get() ); 00110 } 00111 else if ( ImageUtils::hasAlphaChannel( image.get() )) 00112 { 00113 image = ImageUtils::convertToRGBA8( image.get() ); 00114 } 00115 else 00116 { 00117 image = ImageUtils::convertToRGB8( image.get() ); 00118 } 00119 00120 _image = GeoImage( image.get(), getProfile()->getExtent() ); 00121 } 00122 00123 _extension = osgDB::getFileExtension( url.full() ); 00124 } 00125 00126 //override 00127 unsigned int getMaxDataLevel() const 00128 { 00129 return _maxDataLevel; 00130 } 00131 00132 osg::Image* 00133 createImage( const TileKey& key, ProgressCallback* progress ) 00134 { 00135 if ( !_image.valid() || key.getLevelOfDetail() > getMaxDataLevel() ) 00136 return NULL; 00137 00138 GeoImage cropped = _image.crop( key.getExtent(), true, getPixelsPerTile(), getPixelsPerTile() ); 00139 return cropped.valid() ? cropped.takeImage() : 0L; 00140 } 00141 00142 std::string 00143 getExtension() const 00144 { 00145 return _extension; 00146 } 00147 00148 private: 00149 std::string _extension; 00150 int _maxDataLevel; 00151 GeoImage _image; 00152 const OSGOptions _options; 00153 }; 00154 00155 00163 class OSGTileSourceFactory : public TileSourceDriver 00164 { 00165 public: 00166 OSGTileSourceFactory() 00167 { 00168 supportsExtension( "osgearth_osg", "OSG image driver for osgEarth" ); 00169 } 00170 00171 virtual const char* className() 00172 { 00173 return "OSG Image Driver"; 00174 } 00175 00176 virtual ReadResult readObject(const std::string& file_name, const Options* options) const 00177 { 00178 if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name ))) 00179 return ReadResult::FILE_NOT_HANDLED; 00180 00181 return new OSGTileSource( getTileSourceOptions(options) ); 00182 } 00183 }; 00184 00185 REGISTER_OSGPLUGIN(osgearth_osg, OSGTileSourceFactory) 00186