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 <osgEarth/Notify> 00020 00021 #include <osgDB/ReadFile> 00022 #include <osgGA/StateSetManipulator> 00023 #include <osgViewer/Viewer> 00024 #include <osgViewer/ViewerEventHandlers> 00025 00026 #include <osgEarth/MapNode> 00027 #include <osgEarthUtil/EarthManipulator> 00028 #include <osgEarthUtil/OceanSurfaceNode> 00029 #include <osgEarthUtil/Controls> 00030 00031 class MyGraphicsContext { 00032 public: 00033 MyGraphicsContext() 00034 { 00035 osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; 00036 traits->x = 0; 00037 traits->y = 0; 00038 traits->width = 1; 00039 traits->height = 1; 00040 traits->windowDecoration = false; 00041 traits->doubleBuffer = false; 00042 traits->sharedContext = 0; 00043 traits->pbuffer = true; 00044 00045 _gc = osg::GraphicsContext::createGraphicsContext(traits.get()); 00046 00047 if (!_gc) 00048 { 00049 traits->pbuffer = false; 00050 _gc = osg::GraphicsContext::createGraphicsContext(traits.get()); 00051 } 00052 00053 if (_gc.valid()) 00054 { 00055 _gc->realize(); 00056 _gc->makeCurrent(); 00057 } 00058 } 00059 00060 bool valid() const { return _gc.valid() && _gc->isRealized(); } 00061 00062 private: 00063 osg::ref_ptr<osg::GraphicsContext> _gc; 00064 }; 00065 00066 // build an on-screen menu 00067 static osg::Node* createMenu( osgViewer::View* view ) 00068 { 00069 using namespace osgEarth::Util::Controls; 00070 00071 ControlCanvas* canvas = ControlCanvas::get( view ); 00072 00073 Grid* grid = new Grid(); 00074 grid->setBackColor( 0, 0, 0, 0.5 ); 00075 grid->setMargin( 5 ); 00076 grid->setChildSpacing( 3 ); 00077 grid->setVertAlign( Control::ALIGN_BOTTOM ); 00078 int row = 0; 00079 00080 grid->setControl( 1, row++, new LabelControl( "Ocean Demo", 18.0f, osg::Vec4(1,1,0,1) ) ); 00081 grid->setControl( 1, row++, new LabelControl( "Zoom in to the coastline to see ocean effects.", 14.0f, osg::Vec4(.6,.6,.6,1) ) ); 00082 00083 grid->setControl( 0, row , new LabelControl( "e" ) ); 00084 grid->setControl( 1, row++, new LabelControl( "toggle ocean effects" ) ); 00085 grid->setControl( 0, row , new LabelControl( "m" ) ); 00086 grid->setControl( 1, row++, new LabelControl( "toggle MSL adjustment" ) ); 00087 grid->setControl( 0, row , new LabelControl( "h/H" ) ); 00088 grid->setControl( 1, row++, new LabelControl( "inc/dec wave height" ) ); 00089 grid->setControl( 0, row , new LabelControl( "p/P" ) ); 00090 grid->setControl( 1, row++, new LabelControl( "inc/dec wave period" ) ); 00091 grid->setControl( 0, row , new LabelControl( "c/C" ) ); 00092 grid->setControl( 1, row++, new LabelControl( "inc/dec ocean modulation color" ) ); 00093 grid->setControl( 0, row , new LabelControl( "a/A" ) ); 00094 grid->setControl( 1, row++, new LabelControl( "inc/dec shimmer effect period" ) ); 00095 grid->setControl( 0, row , new LabelControl( "j/J" ) ); 00096 grid->setControl( 1, row++, new LabelControl( "inc/dec surface image size" ) ); 00097 grid->setControl( 0, row , new LabelControl( "i" ) ); 00098 grid->setControl( 1, row++, new LabelControl( "toggle ocean mask inversion" ) ); 00099 grid->setControl( 0, row , new LabelControl( "w" ) ); 00100 grid->setControl( 1, row++, new LabelControl( "toggle wireframe mode" ) ); 00101 00102 canvas->addControl( grid ); 00103 return canvas; 00104 } 00105 00106 // An event handler that will print out the elevation at the clicked point 00107 struct MyEventHandler : public osgGA::GUIEventHandler 00108 { 00109 MyEventHandler( osgEarth::Util::OceanSurfaceNode* ocean ) 00110 :_ocean(ocean) { } 00111 00112 bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) 00113 { 00114 if ( ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN ) 00115 { 00116 switch (ea.getKey()) 00117 { 00118 case 'h': 00119 { 00120 _ocean->setWaveHeight( _ocean->getWaveHeight() * 1.1 ); 00121 } 00122 break; 00123 case 'H': 00124 { 00125 _ocean->setWaveHeight( _ocean->getWaveHeight() * 0.9 ); 00126 } 00127 break; 00128 case 'p': 00129 { 00130 _ocean->setPeriod( _ocean->getPeriod() * 1.1 ); 00131 } 00132 break; 00133 case 'P': 00134 { 00135 _ocean->setPeriod( _ocean->getPeriod() * 0.9 ); 00136 } 00137 break; 00138 case 'e': 00139 { 00140 _ocean->setEnabled( !_ocean->getEnabled() ); 00141 } 00142 case 'i': 00143 { 00144 _ocean->setInvertMask( !_ocean->getInvertMask() ); 00145 } 00146 break; 00147 case 'C': 00148 { 00149 osg::Vec4f color = _ocean->getModulationColor(); 00150 color.a() = osg::clampBelow( color.a() + 0.1f, 1.0f ); 00151 _ocean->setModulationColor( color ); 00152 } 00153 break; 00154 case 'c': 00155 { 00156 osg::Vec4f color = _ocean->getModulationColor(); 00157 color.a() = osg::clampAbove( color.a() - 0.1f, 0.0f ); 00158 _ocean->setModulationColor( color ); 00159 } 00160 break; 00161 case 'A': 00162 { 00163 _ocean->setOceanAnimationPeriod(_ocean->getOceanAnimationPeriod() + 0.25); 00164 } 00165 break; 00166 case 'a': 00167 { 00168 _ocean->setOceanAnimationPeriod(_ocean->getOceanAnimationPeriod() - 0.25); 00169 } 00170 break; 00171 case 'J': 00172 { 00173 _ocean->setOceanSurfaceImageSizeRadians( _ocean->getOceanSurfaceImageSizeRadians() * 1.5f); 00174 } 00175 break; 00176 case 'j': 00177 { 00178 _ocean->setOceanSurfaceImageSizeRadians( _ocean->getOceanSurfaceImageSizeRadians() * 0.5f); 00179 } 00180 break; 00181 case 'm': 00182 { 00183 _ocean->setAdjustToMSL( !_ocean->getAdjustToMSL()); 00184 } 00185 break; 00186 } 00187 } 00188 return false; 00189 } 00190 00191 osg::ref_ptr< osgEarth::Util::OceanSurfaceNode > _ocean; 00192 }; 00193 00194 typedef std::vector< osg::ref_ptr< osg::Image > > ImageList; 00195 00196 osg::Image* make3DImage(const ImageList& images) 00197 { 00198 MyGraphicsContext gc; 00199 osg::notify(osg::NOTICE) << "Made graphic context " << std::endl; 00200 /*for (unsigned int i = 0; i < images.size(); ++i) 00201 { 00202 images[i]->scaleImage(256, 256, 1); 00203 osg::notify(osg::NOTICE) << "Scaled image " << i << std::endl; 00204 }*/ 00205 00206 osg::Image* image3D = new osg::Image; 00207 image3D->allocateImage(images[0]->s(), images[0]->t(), images.size(), 00208 images[0]->getPixelFormat(), images[0]->getDataType()); 00209 00210 for (unsigned int i = 0; i < images.size(); ++i) 00211 { 00212 image3D->copySubImage(0, 0, i, images[i].get()); 00213 } 00214 image3D->setInternalTextureFormat(images[0]->getInternalTextureFormat()); 00215 return image3D; 00216 } 00217 00218 00219 int usage( const std::string& msg ) 00220 { 00221 OE_NOTICE 00222 << msg << std::endl 00223 << "USAGE: osgearth_ocean [--mask-layer <layername>] [--invert-mask] <earthfile>" << std::endl 00224 << "(note: <layername> defaults to \"ocean\")" << std::endl; 00225 return -1; 00226 } 00227 00228 00229 int main(int argc, char** argv) 00230 { 00231 osg::ArgumentParser arguments(&argc,argv); 00232 00233 std::string maskLayerName = "ocean"; 00234 while( arguments.read("--mask-layer", maskLayerName) ); 00235 00236 bool invertMask = arguments.isOption("--invert-mask"); 00237 00238 osg::Group* group = new osg::Group; 00239 00240 osg::ref_ptr<osg::Node> loadedModel = osgDB::readNodeFiles(arguments); 00241 if ( !loadedModel.valid() ) 00242 return usage( "Failed to load an earth file." ); 00243 00244 osgEarth::Util::OceanSurfaceNode* ocean = new osgEarth::Util::OceanSurfaceNode(); 00245 00246 if ( !maskLayerName.empty() ) 00247 { 00248 osgEarth::MapNode* mapNode = osgEarth::MapNode::findMapNode( loadedModel.get() ); 00249 if ( mapNode ) 00250 { 00251 osgEarth::MapFrame mapf( mapNode->getMap() ); 00252 ocean->setOceanMaskImageLayer( mapf.getImageLayerByName( maskLayerName ) ); 00253 } 00254 } 00255 00256 ocean->setInvertMask( !invertMask ); 00257 00258 // install some water-surface images for an interesting shimmering effect: 00259 ImageList waterImages; 00260 waterImages.push_back( osgDB::readImageFile("../data/watersurface1.png") ); 00261 waterImages.push_back( osgDB::readImageFile("../data/watersurface2.png") ); 00262 waterImages.push_back( osgDB::readImageFile("../data/watersurface3.png") ); 00263 waterImages.push_back( osgDB::readImageFile("../data/watersurface4.png") ); 00264 00265 osg::ref_ptr<osg::Image> waterImage = make3DImage(waterImages); 00266 ocean->setOceanSurfaceImage( waterImage.get() ); 00267 00268 // Find the MapNode and add the ocean as a terrain decorator. 00269 osgEarth::MapNode* mapNode = osgEarth::MapNode::findMapNode( loadedModel.get() ); 00270 mapNode->addTerrainDecorator( ocean ); 00271 00272 // assemble the rest of the scene graph and go 00273 osgViewer::Viewer viewer(arguments); 00274 00275 group->addChild( loadedModel.get() ); 00276 group->addChild( createMenu(&viewer) ); 00277 viewer.setSceneData(group); 00278 00279 viewer.setCameraManipulator( new osgEarth::Util::EarthManipulator() ); 00280 00281 viewer.addEventHandler(new MyEventHandler(ocean)); 00282 viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) ); 00283 viewer.addEventHandler(new osgViewer::StatsHandler); 00284 00285 return viewer.run(); 00286 }