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 00020 #include <osg/Notify> 00021 #include <osg/Shape> 00022 #include <osg/ShapeDrawable> 00023 #include <osg/Geode> 00024 #include <osg/PagedLOD> 00025 #include <osg/PolygonMode> 00026 #include <osg/AutoTransform> 00027 #include <osg/MatrixTransform> 00028 #include <osgText/Text> 00029 #include <osgGA/StateSetManipulator> 00030 #include <osgGA/GUIEventHandler> 00031 #include <osgViewer/Viewer> 00032 #include <osgViewer/ViewerEventHandlers> 00033 #include <osgUtil/LineSegmentIntersector> 00034 #include <osgEarth/MapNode> 00035 #include <osgEarth/FindNode> 00036 #include <osgEarthUtil/AutoClipPlaneHandler> 00037 #include <osgEarthUtil/EarthManipulator> 00038 #include <osgEarthDrivers/tms/TMSOptions> 00039 #include <osgEarthDrivers/engine_seamless/PatchInfo> 00040 #include <osgEarthDrivers/engine_seamless/SeamlessOptions> 00041 #include <sstream> 00042 00043 // Print info about terrain rendered using the seamless engine. Copied 00044 // from osgearth_elevation. 00045 00046 using namespace osgEarth::Drivers; 00047 00048 static 00049 osg::MatrixTransform* createFlag() 00050 { 00051 osg::Cylinder* c = new osg::Cylinder( osg::Vec3d(0,0,0), 2.0f, 250.f ); 00052 osg::Geode* g = new osg::Geode(); 00053 g->addDrawable( new osg::ShapeDrawable( c ) ); 00054 osgText::Text* text = new osgText::Text(); 00055 text->setCharacterSizeMode( osgText::Text::SCREEN_COORDS ); 00056 text->setCharacterSize( 72.f ); 00057 text->setBackdropType( osgText::Text::OUTLINE ); 00058 text->setText( "00000000000000" ); 00059 text->setAutoRotateToScreen( true ); 00060 text->setPosition( osg::Vec3d( 0, 0, 125 ) ); 00061 text->setDataVariance( osg::Object::DYNAMIC ); 00062 g->addDrawable( text ); 00063 osg::StateSet* ss = g->getOrCreateStateSet(); 00064 ss->setAttribute(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, 00065 osg::PolygonMode::FILL), 00066 osg::StateAttribute::ON | osg::StateAttribute::PROTECTED); 00067 osg::AutoTransform* at = new osg::AutoTransform(); 00068 at->setAutoScaleToScreen( true ); 00069 at->addChild( g ); 00070 at->getOrCreateStateSet()->setMode( GL_LIGHTING, 0 ); 00071 osg::MatrixTransform* xf = new osg::MatrixTransform(); 00072 xf->addChild( at ); 00073 xf->setDataVariance( osg::Object::DYNAMIC ); 00074 return xf; 00075 } 00076 00077 static void 00078 updateFlag(osg::MatrixTransform* xf, const osg::Matrix& mat, 00079 const osgEarth::TileKey& key) 00080 { 00081 osg::Geode* g = static_cast<osg::Geode*>( xf->getChild(0)->asGroup()->getChild(0) ); 00082 std::stringstream buf; 00083 buf << key.getLevelOfDetail() << " " << key.getTileX() << " " 00084 << key.getTileY(); 00085 std::string bufStr; 00086 bufStr = buf.str(); 00087 static_cast<osgText::Text*>( g->getDrawable(1) )->setText( bufStr ); 00088 xf->setMatrix( mat ); 00089 } 00090 00091 // An event handler that will print out the elevation at the clicked point 00092 struct QueryTileHandler : public osgGA::GUIEventHandler 00093 { 00094 QueryTileHandler(osg::MatrixTransform* flag, 00095 const osgEarth::SpatialReference* srs) 00096 : _mouseDown(false), _flag(flag), _srs(srs) { } 00097 00098 void update( float x, float y, osgViewer::View* view ) 00099 { 00100 using namespace osg; 00101 using namespace osgUtil; 00102 using namespace osgEarth; 00103 LineSegmentIntersector::Intersections results; 00104 TileKey key(TileKey::INVALID); 00105 if ( view->computeIntersections( x, y, results, 0x01 ) ) 00106 { 00107 // find the first hit under the mouse: 00108 LineSegmentIntersector::Intersection first 00109 = *(results.begin()); 00110 for (NodePath::const_reverse_iterator itr = first.nodePath.rbegin(), 00111 end = first.nodePath.rend(); 00112 itr != end; 00113 ++itr) 00114 { 00115 const PagedLOD* plod = dynamic_cast<const PagedLOD*>(*itr); 00116 if (!plod) 00117 continue; 00118 const seamless::PatchInfo* popt 00119 = dynamic_cast<const seamless::PatchInfo*>( 00120 plod->getDatabaseOptions()); 00121 if (!popt) 00122 continue; 00123 key = popt->getTileKey(); 00124 break; 00125 } 00126 00127 if (!key.valid()) 00128 { 00129 OE_WARN << "Couldn't get tile key.\n"; 00130 return; 00131 } 00132 osg::Vec3d point = first.getWorldIntersectPoint(); 00133 00134 // transform it to map coordinates: 00135 Matrixd coordFrame; 00136 _srs->getEllipsoid()->computeLocalToWorldTransformFromXYZ( 00137 point.x(), point.y(), point.z(), coordFrame); 00138 updateFlag(_flag.get(), coordFrame, key); 00139 } 00140 } 00141 00142 bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) 00143 { 00144 if ( ea.getEventType() == osgGA::GUIEventAdapter::MOVE ) 00145 { 00146 osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView()); 00147 update( ea.getX(), ea.getY(), view ); 00148 } 00149 00150 return false; 00151 } 00152 00153 bool _mouseDown; 00154 osg::ref_ptr<osg::MatrixTransform> _flag; 00155 osg::ref_ptr<const osgEarth::SpatialReference> _srs; 00156 }; 00157 00158 00159 int main(int argc, char** argv) 00160 { 00161 osg::ArgumentParser arguments(&argc,argv); 00162 00163 osgViewer::Viewer viewer(arguments); 00164 00165 // install the programmable manipulator. 00166 osgEarth::Util::EarthManipulator* manip = new osgEarth::Util::EarthManipulator(); 00167 viewer.setCameraManipulator( manip ); 00168 00169 osgEarth::MapNode* mapNode = NULL; 00170 00171 osg::Node* loadedNode = osgDB::readNodeFiles( arguments ); 00172 if (!loadedNode) 00173 { 00174 // load up a map with an elevation layer: 00175 osgEarth::Map *map = new osgEarth::Map(); 00176 00177 // Add some imagery 00178 { 00179 TMSOptions tms; 00180 tms.url() = "http://demo.pelicanmapping.com/rmweb/data/bluemarble-tms/tms.xml"; 00181 map->addImageLayer( new osgEarth::ImageLayer( "BLUEMARBLE", tms ) ); 00182 } 00183 00184 // Add some elevation 00185 { 00186 TMSOptions tms; 00187 tms.url() = "http://demo.pelicanmapping.com/rmweb/data/srtm30_plus_tms/tms.xml"; 00188 map->addElevationLayer( new osgEarth::ElevationLayer( "SRTM", tms ) ); 00189 } 00190 00191 MapNodeOptions nodeOptions; 00192 nodeOptions.setTerrainOptions( osgEarth::Drivers::SeamlessOptions() ); 00193 00194 mapNode = new osgEarth::MapNode( map, nodeOptions ); 00195 } 00196 else 00197 { 00198 mapNode = findTopMostNodeOfType<osgEarth::MapNode>( loadedNode ); 00199 } 00200 00201 osg::Group* root = new osg::Group(); 00202 00203 // The MapNode will render the Map object in the scene graph. 00204 mapNode->setNodeMask( 0x01 ); 00205 root->addChild( mapNode ); 00206 00207 manip->setNode(mapNode->getTerrainEngine()); 00208 if ( mapNode->getMap()->isGeocentric() ) 00209 { 00210 manip->setHomeViewpoint( 00211 osgEarth::Util::Viewpoint( osg::Vec3d( -90, 0, 0 ), 0.0, -90.0, 5e7 ) ); 00212 00213 // add a handler that will automatically calculate good clipping planes 00214 viewer.addEventHandler( new osgEarth::Util::AutoClipPlaneHandler() ); 00215 } 00216 // A flag so we can see where we clicked 00217 osg::MatrixTransform* flag = createFlag(); 00218 flag->setNodeMask( 0x02 ); 00219 root->addChild( flag ); 00220 00221 viewer.setSceneData( root ); 00222 00223 // An event handler that will respond to mouse clicks: 00224 viewer.addEventHandler( 00225 new QueryTileHandler(flag, mapNode->getMap()->getProfile()->getSRS())); 00226 00227 // add some stock OSG handlers: 00228 viewer.addEventHandler(new osgViewer::StatsHandler()); 00229 viewer.addEventHandler(new osgViewer::WindowSizeHandler()); 00230 viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); 00231 00232 return viewer.run(); 00233 }