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