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