root/OpenSceneGraph/trunk/examples/osgsimulation/osgsimulation.cpp @ 4722

Revision 4722, 12.7 kB (checked in by robert, 10 years ago)

Added release and flush of OpenGL objects after build of the terrain database to prevent
the build graphics context state leaking into the viewers graphics context set.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#ifdef WIN32
2/////////////////////////////////////////////////////////////////////////////
3// Disable unavoidable warning messages:
4
5//  4103: used #pragma pack to change alignment
6//  4114: same type qualifier used more than once
7//  4201: nonstandard extension used : nameless struct/union
8//  4237: "keyword" reserved for future use
9//  4251: class needs to have dll-interface to export class
10//  4275: non DLL-interface class used as base for DLL-interface class
11//  4290: C++ Exception Specification ignored
12//  4503: decorated name length exceeded, name was truncated
13//  4786: string too long - truncated to 255 characters
14
15#pragma warning(disable : 4103 4114 4201 4237 4251 4275 4290 4503 4335 4786)
16
17#endif // WIN32
18
19#include <osgProducer/Viewer>
20
21#include <osg/Group>
22#include <osg/Geode>
23#include <osg/ShapeDrawable>
24#include <osg/Texture2D>
25#include <osg/PositionAttitudeTransform>
26#include <osg/MatrixTransform>
27#include <osg/CoordinateSystemNode>
28
29#include <osgDB/FileUtils>
30#include <osgDB/ReadFile>
31
32#include <osgText/Text>
33
34#include <osgTerrain/DataSet>
35
36#include <osgSim/OverlayNode>
37
38#include <osgGA/NodeTrackerManipulator>
39
40class GraphicsContext {
41    public:
42        GraphicsContext()
43        {
44            rs = new Producer::RenderSurface;
45            rs->setWindowRectangle(0,0,1,1);
46            rs->useBorder(false);
47            rs->useConfigEventThread(false);
48            rs->realize();
49        }
50
51        virtual ~GraphicsContext()
52        {
53        }
54       
55    private:
56        Producer::ref_ptr<Producer::RenderSurface> rs;
57};
58
59osg::Node* createEarth()
60{
61    osg::ref_ptr<osg::Node> scene;
62   
63    {
64        std::string filename = osgDB::findDataFile("Images/land_shallow_topo_2048.jpg");
65
66        // make osgTerrain::DataSet quieter..
67        osgTerrain::DataSet::setNotifyOffset(1);
68
69        osg::ref_ptr<osgTerrain::DataSet> dataSet = new osgTerrain::DataSet;
70
71        // register the source imagery
72        {
73            osgTerrain::DataSet::Source* source = new osgTerrain::DataSet::Source(osgTerrain::DataSet::Source::IMAGE, filename);
74
75            source->setCoordinateSystemPolicy(osgTerrain::DataSet::Source::PREFER_CONFIG_SETTINGS);
76            source->setCoordinateSystem(osgTerrain::DataSet::coordinateSystemStringToWTK("WGS84"));
77
78            source->setGeoTransformPolicy(osgTerrain::DataSet::Source::PREFER_CONFIG_SETTINGS_BUT_SCALE_BY_FILE_RESOLUTION);
79            source->setGeoTransformFromRange(-180.0, 180.0, -90.0, 90.0);
80
81            dataSet->addSource(source);
82        }
83
84        // set up destination database paramters.
85        dataSet->setDatabaseType(osgTerrain::DataSet::LOD_DATABASE);
86        dataSet->setConvertFromGeographicToGeocentric(true);
87        dataSet->setDestinationName("test.osg");
88
89        // load the source data and record sizes.
90        dataSet->loadSources();
91
92        GraphicsContext context;
93        dataSet->createDestination(30);
94
95        if (dataSet->getDatabaseType()==osgTerrain::DataSet::LOD_DATABASE) dataSet->buildDestination();
96        else dataSet->writeDestination();
97       
98        scene = dataSet->getDestinationRootNode();
99       
100        // now we must get rid of all the old OpenGL objects before we start using the scene graph again
101        // otherwise it'll end up in an inconsistent state.
102        scene->releaseGLObjects(dataSet->getState());
103        osg::Texture::flushAllDeletedTextureObjects(0);
104        osg::Drawable::flushAllDeletedDisplayLists(0);
105    }
106       
107    return scene.release();
108   
109}
110
111
112class ModelPositionCallback : public osg::NodeCallback
113{
114public:
115
116    ModelPositionCallback():
117        _latitude(0.0),
118        _longitude(0.0),
119        _height(100000.0)
120    {
121        _rotation.makeRotate(osg::DegreesToRadians(90.0),0.0,0.0,1.0);
122    }
123   
124    void updateParameters()
125    {
126        _longitude += ((2.0*osg::PI)/360.0)/20.0;
127    }
128
129
130    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
131    {
132        updateParameters();
133       
134        osg::NodePath nodePath = nv->getNodePath();
135
136        osg::MatrixTransform* mt = nodePath.empty() ? 0 : dynamic_cast<osg::MatrixTransform*>(nodePath.back());
137        if (mt)
138        {
139            osg::CoordinateSystemNode* csn = 0;
140
141            // find coordinate system node from our parental chain
142            unsigned int i;
143            for(i=0; i<nodePath.size() && csn==0; ++i)
144            {
145                csn = dynamic_cast<osg::CoordinateSystemNode*>(nodePath[i]);
146            }
147           
148            if (csn)
149            {
150
151
152                osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
153                if (ellipsoid)
154                {
155                    osg::Matrixd matrix;
156                    for(i+=1; i<nodePath.size()-1; ++i)
157                    {
158                        osg::Transform* transform = nodePath[i]->asTransform();
159                        if (transform) transform->computeLocalToWorldMatrix(matrix, nv);
160                    }
161
162                    //osg::Matrixd matrix;
163                    ellipsoid->computeLocalToWorldTransformFromLatLongHeight(_latitude,_longitude,_height,matrix);
164                    matrix.preMult(osg::Matrixd::rotate(_rotation));
165                   
166                    mt->setMatrix(matrix);
167                }
168
169            }       
170        }
171           
172        traverse(node,nv);
173    }   
174   
175    double                  _latitude;
176    double                  _longitude;
177    double                  _height;
178    osg::Quat               _rotation;
179};
180
181
182class FindNamedNodeVisitor : public osg::NodeVisitor
183{
184public:
185    FindNamedNodeVisitor(const std::string& name):
186        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
187        _name(name) {}
188   
189    virtual void apply(osg::Node& node)
190    {
191        if (node.getName()==_name)
192        {
193            _foundNodes.push_back(&node);
194        }
195        traverse(node);
196    }
197   
198    typedef std::vector< osg::ref_ptr<osg::Node> > NodeList;
199
200    std::string _name;
201    NodeList _foundNodes;
202};
203
204
205int main(int argc, char **argv)
206{
207    // use an ArgumentParser object to manage the program arguments.
208    osg::ArgumentParser arguments(&argc,argv);
209   
210    // set up the usage document, in case we need to print out how to use this program.
211    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of particle systems.");
212    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] image_file_left_eye image_file_right_eye");
213    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
214   
215
216    // construct the viewer.
217    osgProducer::Viewer viewer(arguments);
218
219    // set up the value with sensible default event handlers.
220    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
221
222    viewer.getCullSettings().setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
223    viewer.getCullSettings().setNearFarRatio(0.00001f);
224
225    // get details on keyboard and mouse bindings used by the viewer.
226    viewer.getUsage(*arguments.getApplicationUsage());
227
228    osg::Quat rotation;
229    osg::Vec4 vec4;
230    while (arguments.read("--rotate-model",vec4[0],vec4[1],vec4[2],vec4[3]))
231    {
232        osg::Quat local_rotate;
233        local_rotate.makeRotate(osg::DegreesToRadians(vec4[0]),vec4[1],vec4[2],vec4[3]);
234       
235        rotation = rotation * local_rotate;
236    }
237
238    osg::NodeCallback* nc = 0;
239    std::string flightpath_filename;
240    while (arguments.read("--flight-path",flightpath_filename))
241    {
242        std::ifstream fin(flightpath_filename.c_str());
243        if (fin)
244        {
245            osg::AnimationPath* path = new osg::AnimationPath;
246            path->read(fin);
247            nc = new osg::AnimationPathCallback(path);
248        }
249    }
250   
251    osgGA::NodeTrackerManipulator::TrackerMode trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER_AND_ROTATION;
252    std::string mode;
253    while (arguments.read("--tracker-mode",mode))
254    {
255        if (mode=="NODE_CENTER_AND_ROTATION") trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER_AND_ROTATION;
256        else if (mode=="NODE_CENTER_AND_AZIM") trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER_AND_AZIM;
257        else if (mode=="NODE_CENTER") trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER;
258        else
259        {
260            std::cout<<"Unrecognized --tracker-mode option "<<mode<<", valid options are:"<<std::endl;
261            std::cout<<"    NODE_CENTER_AND_ROTATION"<<std::endl;
262            std::cout<<"    NODE_CENTER_AND_AZIM"<<std::endl;
263            std::cout<<"    NODE_CENTER"<<std::endl;
264            return 1;
265        }
266    }
267   
268   
269    osgGA::NodeTrackerManipulator::RotationMode rotationMode = osgGA::NodeTrackerManipulator::TRACKBALL;
270    while (arguments.read("--rotation-mode",mode))
271    {
272        if (mode=="TRACKBALL") rotationMode = osgGA::NodeTrackerManipulator::TRACKBALL;
273        else if (mode=="ELEVATION_AZIM") rotationMode = osgGA::NodeTrackerManipulator::ELEVATION_AZIM;
274        else
275        {
276            std::cout<<"Unrecognized --rotation-mode option "<<mode<<", valid options are:"<<std::endl;
277            std::cout<<"    TRACKBALL"<<std::endl;
278            std::cout<<"    ELEVATION_AZIM"<<std::endl;
279            return 1;
280        }
281    }
282
283    // if user request help write it out to cout.
284    if (arguments.read("-h") || arguments.read("--help"))
285    {
286        arguments.getApplicationUsage()->write(std::cout);
287        return 1;
288    }
289
290    // any option left unread are converted into errors to write out later.
291    arguments.reportRemainingOptionsAsUnrecognized();
292
293    // report any errors if they have occured when parsing the program aguments.
294    if (arguments.errors())
295    {
296        arguments.writeErrorMessages(std::cout);
297        return 1;
298    }
299   
300    // read the scene from the list of file specified commandline args.
301    osg::ref_ptr<osg::Node> root = osgDB::readNodeFiles(arguments);
302
303    if (!root) root = createEarth();
304   
305    if (!root) return 0;
306
307    // add a viewport to the viewer and attach the scene graph.
308    viewer.setSceneData(root.get());
309
310    osg::CoordinateSystemNode* csn = dynamic_cast<osg::CoordinateSystemNode*>(root.get());
311    if (csn)
312    {
313
314        bool insertOverlayNode = true;
315        osg::ref_ptr<osgSim::OverlayNode> overlayNode;
316        if (insertOverlayNode)
317        {
318       
319            overlayNode = new osgSim::OverlayNode;
320           
321            // insert the OverlayNode between the coordinate system node and its children.
322            for(unsigned int i=0; i<csn->getNumChildren(); ++i)
323            {
324                overlayNode->addChild( csn->getChild(i) );
325            }
326
327            csn->removeChild(0, csn->getNumChildren());
328            csn->addChild(overlayNode.get());
329           
330            // tell the overlay node to continously update its overlay texture
331            // as we know we'll be tracking a moving target.
332            overlayNode->setContinousUpdate(true);
333        }
334       
335       
336        osg::Node* cessna = osgDB::readNodeFile("cessna.osg");
337        if (cessna)
338        {
339            double s = 200000.0 / cessna->getBound().radius();
340       
341            osg::MatrixTransform* scaler = new osg::MatrixTransform;
342            scaler->addChild(cessna);
343            scaler->setMatrix(osg::Matrixd::scale(s,s,s)*osg::Matrixd::rotate(rotation));
344            scaler->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL,osg::StateAttribute::ON);       
345       
346            osg::MatrixTransform* mt = new osg::MatrixTransform;
347            mt->addChild(scaler);
348
349
350            if (!nc) nc = new ModelPositionCallback;
351
352            mt->setUpdateCallback(nc);
353
354            csn->addChild(mt);
355           
356            // if we are using an overaly node, use the cessna subgraph as the overlay subgraph
357            if (overlayNode.valid())
358            {
359                overlayNode->setOverlaySubgraph(mt);
360            }
361
362            osgGA::NodeTrackerManipulator* tm = new osgGA::NodeTrackerManipulator;
363            tm->setTrackerMode(trackerMode);
364            tm->setRotationMode(rotationMode);
365            tm->setTrackNode(scaler);
366
367            unsigned int num = viewer.addCameraManipulator(tm);
368            viewer.selectCameraManipulator(num);
369        }
370        else
371        {
372             std::cout<<"Failed to read cessna.osg"<<std::endl;
373        }
374       
375    }   
376
377       
378
379    // create the windows and run the threads.
380    viewer.realize();
381
382    while( !viewer.done() )
383    {
384        // wait for all cull and draw threads to complete.
385        viewer.sync();
386
387        // update the scene by traversing it with the the update visitor which will
388        // call all node update callbacks and animations.
389        viewer.update();
390         
391        // fire off the cull and draw traversals of the scene.
392        viewer.frame();
393       
394    }
395   
396    // wait for all cull and draw threads to complete before exit.
397    viewer.sync();
398
399    return 0;
400}
Note: See TracBrowser for help on using the browser.