1 /* OpenSceneGraph example, osgimpostor.
2 *
3 *  Permission is hereby granted, free of charge, to any person obtaining a copy
4 *  of this software and associated documentation files (the "Software"), to deal
5 *  in the Software without restriction, including without limitation the rights
6 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 *  copies of the Software, and to permit persons to whom the Software is
8 *  furnished to do so, subject to the following conditions:
9 *
10 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16 *  THE SOFTWARE.
17 */
18 
19 #include <osg/Geometry>
20 #include <osg/Material>
21 #include <osg/MatrixTransform>
22 #include <osg/Quat>
23 #include <osg/Geode>
24 
25 #include <osgSim/Impostor>
26 #include <osgSim/InsertImpostorsVisitor>
27 
28 #include <osgDB/ReadFile>
29 #include <osgDB/WriteFile>
30 
31 #include <osgViewer/Viewer>
32 #include <osgViewer/ViewerEventHandlers>
33 
34 #include <osgGA/TrackballManipulator>
35 #include <osgGA/FlightManipulator>
36 #include <osgGA/DriveManipulator>
37 #include <osgGA/KeySwitchMatrixManipulator>
38 #include <osgGA/StateSetManipulator>
39 #include <osgGA/AnimationPathManipulator>
40 #include <osgGA/TerrainManipulator>
41 #include <osgGA/SphericalManipulator>
42 
43 #include "TestManipulator.h"
44 
45 
46 #include <iostream>
47 #include <list>
48 
49 
main(int argc,char ** argv)50 int main( int argc, char **argv )
51 {
52     // use an ArgumentParser object to manage the program arguments.
53     osg::ArgumentParser arguments(&argc,argv);
54 
55     // construct the viewer.
56     osgViewer::Viewer viewer;
57 
58     // set up the camera manipulators.
59     {
60         osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
61 
62         // add local test manipulator more suitable for testing impostors.
63         keyswitchManipulator->addMatrixManipulator( '0', "Test", new TestManipulator);
64 
65         keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
66         keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
67         keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
68         keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
69         keyswitchManipulator->addMatrixManipulator( '5', "Orbit", new osgGA::OrbitManipulator() );
70         keyswitchManipulator->addMatrixManipulator( '6', "FirstPerson", new osgGA::FirstPersonManipulator() );
71         keyswitchManipulator->addMatrixManipulator( '7', "Spherical", new osgGA::SphericalManipulator() );
72 
73         std::string pathfile;
74         double animationSpeed = 1.0;
75         while(arguments.read("--speed",animationSpeed) ) {}
76         char keyForAnimationPath = '8';
77         while (arguments.read("-p",pathfile))
78         {
79             osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
80             if (apm || !apm->valid())
81             {
82                 apm->setTimeScale(animationSpeed);
83 
84                 unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
85                 keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
86                 keyswitchManipulator->selectMatrixManipulator(num);
87                 ++keyForAnimationPath;
88             }
89         }
90 
91         viewer.setCameraManipulator( keyswitchManipulator.get() );
92     }
93 
94     viewer.addEventHandler(new osgViewer::StatsHandler);
95     viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
96 
97     std::string output_filename;
98     arguments.read("-o", output_filename);
99 
100 
101         // load the nodes from the commandline arguments.
102     osg::ref_ptr<osg::Node> model = osgDB::readRefNodeFiles(arguments);
103     if (!model)
104     {
105         OSG_NOTICE<<"No model loaded, please specify and model on the the command line"<<std::endl;
106         return 0;
107     }
108 
109 
110     // the osgSim::InsertImpostorsVisitor used lower down to insert impostors
111     // only operators on subclass of Group's, if the model top node is not
112     // a group then it won't be able to insert an impostor.  We therefore
113     // manually insert an impostor above the model.
114     if (dynamic_cast<osg::Group*>(model.get())==0)
115     {
116         const osg::BoundingSphere& bs = model->getBound();
117         if (bs.valid())
118         {
119 
120             osgSim::Impostor* impostor = new osgSim::Impostor;
121 
122             // standard LOD settings
123             impostor->addChild(model.get());
124             impostor->setRange(0,0.0f,1e7f);
125             impostor->setCenter(bs.center());
126 
127             // impostor specific settings.
128             impostor->setImpostorThresholdToBound(5.0f);
129 
130             model = impostor;
131 
132         }
133     }
134 
135     // we insert an impostor node above the model, so we keep a handle
136     // on the rootnode of the model, the is required since the
137     // InsertImpostorsVisitor can add a new root in automatically and
138     // we would know about it, other than by following the parent path
139     // up from model.  This is really what should be done, but I'll pass
140     // on it right now as it requires a getRoots() method to be added to
141     // osg::Node, and we're about to make a release so no new features!
142     osg::ref_ptr<osg::Group> rootnode = new osg::Group;
143     rootnode->addChild(model);
144 
145 
146     // now insert impostors in the model using the InsertImpostorsVisitor.
147     osgSim::InsertImpostorsVisitor ov;
148 
149     // traverse the model and collect all osg::Group's and osg::LOD's.
150     // however, don't traverse the rootnode since we want to keep it as
151     // the start of traversal, otherwise the insertImpostor could insert
152     // and Impostor above the current root, making it nolonger a root!
153     model->accept(ov);
154 
155     // insert the Impostors above groups and LOD's
156     ov.insertImpostors();
157 
158 
159     if (!output_filename.empty())
160     {
161         osgDB::writeNodeFile(*rootnode, output_filename);
162         return 1;
163     }
164 
165 
166 
167     // add model to viewer.
168     viewer.setSceneData(rootnode);
169 
170     return viewer.run();
171 }
172