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/AutoTransform> 00025 #include <osg/MatrixTransform> 00026 #include <osgText/Text> 00027 #include <osgGA/StateSetManipulator> 00028 #include <osgGA/GUIEventHandler> 00029 #include <osgViewer/Viewer> 00030 #include <osgViewer/ViewerEventHandlers> 00031 #include <osgUtil/LineSegmentIntersector> 00032 #include <osgEarth/MapNode> 00033 #include <osgEarth/FindNode> 00034 #include <osgEarth/ElevationQuery> 00035 #include <osgEarthUtil/EarthManipulator> 00036 #include <osgEarthUtil/ObjectLocator> 00037 #include <osg/Depth> 00038 #include <sstream> 00039 #include <iomanip> 00040 00041 using namespace osgEarth; 00042 using namespace osgEarth::Util; 00043 00044 static osg::Node* s_flagNode; 00045 static osgText::Text* s_flagText; 00046 00047 static 00048 osg::Node* createFlag() 00049 { 00050 osg::Geode* g = new osg::Geode(); 00051 osgText::Text* text = new osgText::Text(); 00052 text->setCharacterSizeMode( osgText::Text::SCREEN_COORDS ); 00053 text->setCharacterSize( 24.f ); 00054 text->setFont( osgText::readFontFile("arial.ttf") ); 00055 text->setBackdropType( osgText::Text::OUTLINE ); 00056 text->setText( "00000000000000" ); 00057 text->setAutoRotateToScreen( true ); 00058 text->setPosition( osg::Vec3d( 0, 0, 0 ) ); 00059 text->setDataVariance( osg::Object::DYNAMIC ); 00060 g->addDrawable( text ); 00061 g->getOrCreateStateSet()->setMode( GL_LIGHTING, 0 ); 00062 g->getStateSet()->setAttribute( new osg::Depth(osg::Depth::ALWAYS), 1 ); 00063 g->getStateSet()->setRenderBinDetails( 99, "RenderBin" ); 00064 g->setDataVariance( osg::Object::DYNAMIC ); 00065 g->setCullingActive( false ); 00066 g->setNodeMask( 0 ); 00067 s_flagText = text; 00068 s_flagNode = g; 00069 return g; 00070 } 00071 00072 // An event handler that will print out the elevation at the clicked point 00073 struct QueryElevationHandler : public osgGA::GUIEventHandler 00074 { 00075 QueryElevationHandler(const Map* map, ObjectLocator* flagLocator ) 00076 : _map(map), 00077 _mouseDown( false ), 00078 _flagLocator(flagLocator), 00079 _query(map) 00080 { 00081 _query.setMaxTilesToCache(10); 00082 } 00083 00084 void update( float x, float y, osgViewer::View* view ) 00085 { 00086 osgUtil::LineSegmentIntersector::Intersections results; 00087 if ( view->computeIntersections( x, y, results, 0x01 ) ) 00088 { 00089 // find the first hit under the mouse: 00090 osgUtil::LineSegmentIntersector::Intersection first = *(results.begin()); 00091 osg::Vec3d point = first.getWorldIntersectPoint(); 00092 osg::Vec3d lla; 00093 00094 // transform it to map coordinates: 00095 _map->worldPointToMapPoint(point, lla); 00096 00097 // find the elevation at that map point: 00098 osg::Matrixd out_mat; 00099 double query_resolution = 0.1; // 1/10th of a degree 00100 double out_elevation = 0.0; 00101 double out_resolution = 0.0; 00102 00103 bool ok = _query.getElevation( 00104 lla, 00105 _map->getProfile()->getSRS(), 00106 out_elevation, 00107 query_resolution, 00108 &out_resolution ); 00109 00110 if ( ok ) 00111 { 00112 _flagLocator->setPosition( osg::Vec3d(lla.x(), lla.y(), out_elevation) ); 00113 s_flagNode->setNodeMask( ~0 ); 00114 00115 std::stringstream buf; 00116 buf << std::fixed << std::setprecision(2) 00117 << "Pos: " << lla.x() << ", " << lla.y() << std::endl 00118 << "Elv: " << out_elevation << "m" << std::endl 00119 << "X: " << point.x() << std::endl 00120 << "Y: " << point.y() << std::endl 00121 << "Z: " << point.z(); 00122 s_flagText->setText( buf.str() ); 00123 00124 OE_NOTICE << buf.str() << std::endl; 00125 } 00126 else 00127 { 00128 OE_NOTICE 00129 << "getElevation FAILED! at (" << point.x() << ", " << point.y() << ")" << std::endl; 00130 } 00131 00132 } 00133 else 00134 { 00135 s_flagNode->setNodeMask(0); 00136 } 00137 } 00138 00139 bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) 00140 { 00141 if ( ea.getEventType() == osgGA::GUIEventAdapter::MOVE ) 00142 { 00143 osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView()); 00144 update( ea.getX(), ea.getY(), view ); 00145 } 00146 00147 return false; 00148 } 00149 00150 const Map* _map; 00151 bool _mouseDown; 00152 ElevationQuery _query; 00153 ObjectLocator* _flagLocator; 00154 }; 00155 00156 00157 int main(int argc, char** argv) 00158 { 00159 osg::ArgumentParser arguments(&argc,argv); 00160 00161 osgViewer::Viewer viewer(arguments); 00162 00163 osgEarth::MapNode* mapNode = NULL; 00164 00165 osg::Node* loadedNode = osgDB::readNodeFiles( arguments ); 00166 if (loadedNode) 00167 { 00168 mapNode = findTopMostNodeOfType<osgEarth::MapNode>( loadedNode ); 00169 } 00170 00171 if ( !mapNode ) 00172 { 00173 OE_WARN << "Unable to load earth file." << std::endl; 00174 return -1; 00175 } 00176 00177 osg::Group* root = new osg::Group(); 00178 00179 // The MapNode will render the Map object in the scene graph. 00180 mapNode->setNodeMask( 0x01 ); 00181 root->addChild( mapNode ); 00182 00183 // A flag so we can see where we clicked 00184 ObjectLocatorNode* flag = new ObjectLocatorNode( mapNode->getMap() ); 00185 flag->addChild( createFlag() ); 00186 flag->setNodeMask( 0x02 ); 00187 root->addChild( flag ); 00188 00189 viewer.setSceneData( root ); 00190 00191 // An event handler that will respond to mouse clicks: 00192 viewer.addEventHandler( new QueryElevationHandler( mapNode->getMap(), flag->getLocator() ) ); 00193 00194 // add some stock OSG handlers: 00195 viewer.addEventHandler(new osgViewer::StatsHandler()); 00196 viewer.addEventHandler(new osgViewer::WindowSizeHandler()); 00197 viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); 00198 00199 // install the programmable manipulator. 00200 if ( mapNode->getMap()->isGeocentric() ) 00201 viewer.setCameraManipulator( new osgEarth::Util::EarthManipulator() ); 00202 00203 return viewer.run(); 00204 }