1 /* -*-c++-*- */
2 /* osgEarth - Geospatial SDK for OpenSceneGraph
3 * Copyright 2019 Pelican Mapping
4 * http://osgearth.org
5 *
6 * osgEarth is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
16 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
17 * IN THE SOFTWARE.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program.  If not, see <http://www.gnu.org/licenses/>
21 */
22 
23 #include <osgViewer/Viewer>
24 #include <osgEarth/Notify>
25 #include <osgEarth/TerrainEngineNode>
26 #include <osgEarthUtil/EarthManipulator>
27 #include <osgEarthUtil/ExampleResources>
28 
29 #define LC "[viewer] "
30 
31 using namespace osgEarth;
32 using namespace osgEarth::Util;
33 
34 int
usage(const char * name)35 usage(const char* name)
36 {
37     OE_NOTICE
38         << "\nUsage: " << name << " file.earth" << std::endl
39         << MapNodeHelper().usage() << std::endl;
40 
41     return 0;
42 }
43 
44 struct MyComputeRangeCallback : public osgEarth::ComputeRangeCallback
45 {
operator ()MyComputeRangeCallback46     virtual float operator()(osg::Node* node, osg::NodeVisitor& nv)
47     {
48         osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
49         if (cv)
50         {
51             // This code assumes that the range_mode is PIXEL_SIZE_ON_SCREEN and computes the pixel size on screen
52             // without just using the vertical field of view.
53             float distance = nv.getDistanceToViewPoint(node->getBound().center(),true);
54             float radius = node->getBound().radius();
55 
56             double fov, ar, near, far;
57             cv->getCurrentCamera()->getProjectionMatrixAsPerspective(fov, ar, near,far);
58 
59             osg::Viewport* viewPort = cv->getCurrentCamera()->getViewport();
60             double angularSize = osg::RadiansToDegrees( 2.0*atan(radius/distance) );
61             double dpp = osg::maximum(fov, 1.0e-17) / viewPort->height();
62             float pixelSize = angularSize / dpp;
63             //OE_NOTICE << "Returning " << pixelSize << std::endl;
64             return pixelSize;
65         }
66 
67         // Fall back to the base calculation.
68         return -1.0;
69     }
70 };
71 
72 int
main(int argc,char ** argv)73 main(int argc, char** argv)
74 {
75     osg::ArgumentParser arguments(&argc,argv);
76 
77     // help?
78     if ( arguments.read("--help") )
79         return usage(argv[0]);
80 
81     // create a viewer:
82     osgViewer::Viewer viewer(arguments);
83 
84     // Tell the database pager to not modify the unref settings
85     viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy( false, false );
86 
87     // thread-safe initialization of the OSG wrapper manager. Calling this here
88     // prevents the "unsupported wrapper" messages from OSG
89     osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper("osg::Image");
90 
91     // install our default manipulator (do this before calling load)
92     viewer.setCameraManipulator( new EarthManipulator(arguments) );
93 
94     // disable the small-feature culling
95     viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
96 
97     // set a near/far ratio that is smaller than the default. This allows us to get
98     // closer to the ground without near clipping. If you need more, use --logdepth
99     viewer.getCamera()->setNearFarRatio(0.0001);
100 
101 
102     // load an earth file, and support all or our example command-line options
103     // and earth file <external> tags
104     osg::Node* node = MapNodeHelper().load( arguments, &viewer );
105     if ( node )
106     {
107         viewer.setSceneData( node );
108 
109         // Set a custom ComputeRangeCallback on the MapNode
110         MapNode* mapNode = MapNode::findMapNode(node);
111         mapNode->getTerrainEngine()->setComputeRangeCallback( new MyComputeRangeCallback() );
112 
113 
114         while(!viewer.done())
115         {
116             viewer.frame();
117         }
118     }
119     else
120     {
121         return usage(argv[0]);
122     }
123 }
124