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 <osgGA/StateSetManipulator> 00022 #include <osgGA/GUIEventHandler> 00023 #include <osgViewer/Viewer> 00024 #include <osgViewer/ViewerEventHandlers> 00025 #include <osgEarth/MapNode> 00026 #include <osgEarthUtil/EarthManipulator> 00027 #include <osgEarthUtil/AutoClipPlaneHandler> 00028 #include <osgEarthUtil/Controls> 00029 #include <osgEarth/Utils> 00030 00031 #include <osg/ImageStream> 00032 #include <osgDB/FileNameUtils> 00033 #include <osg/Version> 00034 #include <osgEarth/Version> 00035 00036 #include <osgEarthUtil/ImageOverlay> 00037 #if OSG_MIN_VERSION_REQUIRED(2,9,6) 00038 #include <osgEarthUtil/ImageOverlayEditor> 00039 #endif 00040 00041 using namespace osgEarth; 00042 using namespace osgEarth::Util; 00043 using namespace osgEarth::Util::Controls; 00044 00045 static Grid* s_layerBox = NULL; 00046 00047 osg::Node* 00048 createControlPanel( osgViewer::View* view ) 00049 { 00050 ControlCanvas* canvas = ControlCanvas::get( view ); 00051 00052 // the outer container: 00053 s_layerBox = new Grid(); 00054 s_layerBox->setBackColor(0,0,0,0.5); 00055 s_layerBox->setMargin( 10 ); 00056 s_layerBox->setPadding( 10 ); 00057 s_layerBox->setChildSpacing( 10 ); 00058 s_layerBox->setChildVertAlign( Control::ALIGN_CENTER ); 00059 s_layerBox->setAbsorbEvents( true ); 00060 s_layerBox->setVertAlign( Control::ALIGN_BOTTOM ); 00061 00062 00063 00064 canvas->addControl( s_layerBox ); 00065 return canvas; 00066 } 00067 00068 int 00069 usage( const std::string& msg ) 00070 { 00071 OE_NOTICE << msg << std::endl; 00072 OE_NOTICE << "USAGE: osgearth_imageoverlay file.earth" << std::endl; 00073 OE_NOTICE << " --image <file> xmin ymin xmax ymax : An image to overlay and it's bounds" << std::endl; 00074 OE_NOTICE << " --vert : Move individual verts when editing" << std::endl; 00075 00076 00077 return -1; 00078 } 00079 00080 struct OpacityHandler : public ControlEventHandler 00081 { 00082 OpacityHandler( ImageOverlay* overlay ) : _overlay(overlay) { } 00083 void onValueChanged( Control* control, float value ) { 00084 _overlay->setAlpha( value ); 00085 } 00086 ImageOverlay* _overlay; 00087 }; 00088 00089 struct EnabledHandler : public ControlEventHandler 00090 { 00091 EnabledHandler( ImageOverlay* overlay ) : _overlay(overlay) { } 00092 void onValueChanged( Control* control, bool value ) { 00093 _overlay->setNodeMask( value ? ~0 : 0 ); 00094 } 00095 ImageOverlay* _overlay; 00096 }; 00097 00098 00099 00100 struct EditHandler : public ControlEventHandler 00101 { 00102 EditHandler( ImageOverlay* overlay, osgViewer::Viewer* viewer, osg::Node* editor) : 00103 _overlay(overlay), 00104 _viewer(viewer), 00105 _editor(editor){ } 00106 00107 void onClick( Control* control, int mouseButtonMask ) { 00108 #if OSG_MIN_VERSION_REQUIRED(2,9,6) 00109 if (_editor->getNodeMask() != ~0) 00110 { 00111 static_cast<LabelControl*>(control)->setText( "Finish" ); 00112 _editor->setNodeMask(~0); 00113 } 00114 else 00115 { 00116 static_cast<LabelControl*>(control)->setText( "Edit" ); 00117 _editor->setNodeMask(0); 00118 } 00119 00120 #else 00121 OE_NOTICE << "Use OSG 2.9.6 or greater to use editing" << std::endl; 00122 #endif 00123 } 00124 ImageOverlay* _overlay; 00125 osgViewer::Viewer* _viewer; 00126 osg::Node* _editor; 00127 }; 00128 00129 struct ChangeImageHandler : public ControlEventHandler 00130 { 00131 ChangeImageHandler( osg::Image* image, ImageOverlay* overlay, ImageControl* preview) : 00132 _image(image), 00133 _overlay(overlay), 00134 _preview(preview){ } 00135 00136 void onClick( Control* control, int mouseButtonMask ) { 00137 _overlay->setImage( _image.get() ); 00138 _preview->setImage( _image.get() ); 00139 } 00140 ImageOverlay* _overlay; 00141 osg::ref_ptr< osg::Image > _image; 00142 osg::ref_ptr< ImageControl> _preview; 00143 }; 00144 00145 struct UpdateLabelCallback : public ImageOverlay::ImageOverlayCallback 00146 { 00147 UpdateLabelCallback(LabelControl* label, ImageOverlay* overlay, ImageOverlay::ControlPoint controlPoint): 00148 _label(label), 00149 _overlay(overlay), 00150 _controlPoint(controlPoint) 00151 { 00152 00153 } 00154 00155 virtual void onOverlayChanged() 00156 { 00157 osg::Vec2d location = _overlay->getControlPoint( _controlPoint ); 00158 std::stringstream ss; 00159 ss << location.y() << ", " << location.x(); 00160 _label->setText( ss.str() ); 00161 } 00162 00163 00164 osg::ref_ptr< LabelControl > _label; 00165 osg::ref_ptr< ImageOverlay > _overlay; 00166 ImageOverlay::ControlPoint _controlPoint; 00167 }; 00168 00169 00170 00171 int 00172 main(int argc, char** argv) 00173 { 00174 osg::ArgumentParser arguments(&argc,argv); 00175 osg::DisplaySettings::instance()->setMinimumNumStencilBits( 8 ); 00176 00177 00178 std::vector< std::string > imageFiles; 00179 std::vector< Bounds > imageBounds; 00180 00181 //Read in the image files 00182 std::string filename; 00183 Bounds bounds; 00184 while (arguments.read("--image", filename, bounds.xMin(), bounds.yMin(), bounds.xMax(), bounds.yMax())) 00185 { 00186 imageFiles.push_back( filename ); 00187 imageBounds.push_back( bounds ); 00188 } 00189 00190 if (imageFiles.empty()) 00191 { 00192 imageFiles.push_back("../data/osgearth.gif"); 00193 imageBounds.push_back( Bounds(-100, 30, -90, 40) ); 00194 } 00195 00196 00197 bool moveVert = arguments.read("--vert"); 00198 00199 // load the .earth file from the command line. 00200 osg::Node* earthNode = osgDB::readNodeFiles( arguments ); 00201 if (!earthNode) 00202 return usage( "Unable to load earth model." ); 00203 00204 osgViewer::Viewer viewer(arguments); 00205 00206 EarthManipulator* manip = new EarthManipulator(); 00207 viewer.setCameraManipulator( manip ); 00208 00209 osg::Group* root = new osg::Group(); 00210 root->addChild( earthNode ); 00211 00212 //Create the control panel 00213 root->addChild( createControlPanel(&viewer) ); 00214 00215 viewer.setSceneData( root ); 00216 00217 osgEarth::MapNode* mapNode = osgEarth::MapNode::findMapNode( earthNode ); 00218 if ( mapNode ) 00219 { 00220 00221 for (unsigned int i = 0; i < imageFiles.size(); i++) 00222 { 00223 std::string imageFile = imageFiles[i]; 00224 //Read the image file and play it if it's a movie 00225 osg::Image* image = osgDB::readImageFile(imageFile); 00226 if (image) 00227 { 00228 osg::ImageStream* is = dynamic_cast<osg::ImageStream*>(image); 00229 if (is) 00230 { 00231 is->play(); 00232 } 00233 } 00234 00235 //Create a new ImageOverlay and set it's bounds 00236 //ImageOverlay* overlay = new ImageOverlay(mapNode->getMap()->getProfile()->getSRS()->getEllipsoid(), image); 00237 ImageOverlay* overlay = new ImageOverlay(mapNode); 00238 overlay->setImage( image ); 00239 overlay->setBounds(imageBounds[i]); 00240 00241 root->addChild( overlay ); 00242 00243 00244 //Create a new ImageOverlayEditor and set it's node mask to 0 to hide it initially 00245 #if OSG_MIN_VERSION_REQUIRED(2,9,6) 00246 osg::Node* editor = new ImageOverlayEditor( overlay, mapNode->getMap()->getProfile()->getSRS()->getEllipsoid(), mapNode ); 00247 #else 00248 //Just make an empty group for pre-2.9.6 00249 osg::Node* editor = new osg::Group; 00250 #endif 00251 editor->setNodeMask( 0 ); 00252 root->addChild( editor ); 00253 00254 // Add an image preview 00255 ImageControl* imageCon = new ImageControl( image ); 00256 imageCon->setSize( 64, 64 ); 00257 imageCon->setVertAlign( Control::ALIGN_CENTER ); 00258 s_layerBox->setControl( 0, i, imageCon ); 00259 00260 00261 //Add some controls 00262 CheckBoxControl* enabled = new CheckBoxControl( true ); 00263 enabled->addEventHandler( new EnabledHandler(overlay) ); 00264 enabled->setVertAlign( Control::ALIGN_CENTER ); 00265 s_layerBox->setControl( 1, i, enabled ); 00266 00267 //The overlay name 00268 LabelControl* name = new LabelControl( osgDB::getSimpleFileName( imageFile) ); 00269 name->setVertAlign( Control::ALIGN_CENTER ); 00270 s_layerBox->setControl( 2, i, name ); 00271 00272 // an opacity slider 00273 HSliderControl* opacity = new HSliderControl( 0.0f, 1.0f, overlay->getAlpha() ); 00274 opacity->setWidth( 125 ); 00275 opacity->setHeight( 12 ); 00276 opacity->setVertAlign( Control::ALIGN_CENTER ); 00277 opacity->addEventHandler( new OpacityHandler(overlay) ); 00278 s_layerBox->setControl( 3, i, opacity ); 00279 00280 // Add a text label: 00281 LabelControl* edit = new LabelControl( "Edit" ); 00282 edit->setVertAlign( Control::ALIGN_CENTER ); 00283 edit->addEventHandler(new EditHandler(overlay, &viewer, editor)); 00284 s_layerBox->setControl(4, i, edit ); 00285 } 00286 } 00287 00288 // osgEarth benefits from pre-compilation of GL objects in the pager. In newer versions of 00289 // OSG, this activates OSG's IncrementalCompileOpeartion in order to avoid frame breaks. 00290 viewer.getDatabasePager()->setDoPreCompile( true ); 00291 00292 // add some stock OSG handlers: 00293 viewer.addEventHandler(new osgViewer::StatsHandler()); 00294 viewer.addEventHandler(new osgViewer::WindowSizeHandler()); 00295 viewer.addEventHandler(new osgViewer::LODScaleHandler()); 00296 viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())); 00297 viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage())); 00298 00299 return viewer.run(); 00300 }