source: osgVisual/trunk/src/core/visual_core.cpp @ 214

Last change on this file since 214 was 214, checked in by Torben Dannhauer, 13 years ago

Now nodetracking can be called any time after object creation and all node tracker are focused to this node.

Todo: Rebuild visual:object to be a Node, to allow tracking of visual_objects, not only of their geometries if loaded.

File size: 18.6 KB
Line 
1/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
2 *
3 * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
9 * You have to aquire licenses for all used proprietary modules.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * OpenSceneGraph Public License for more details.
15*/
16
17
18#include <visual_core.h>
19
20using namespace osgVisual;
21
22visual_core::visual_core(osg::ArgumentParser& arguments_) : arguments(arguments_)
23{
24        OSG_NOTIFY( osg::ALWAYS ) << "visual_core instantiated." << std::endl;
25}
26
27visual_core::~visual_core(void)
28{
29        OSG_NOTIFY( osg::ALWAYS ) << "visual_core destroyed." << std::endl;
30}
31
32void visual_core::initialize()
33{
34        OSG_NOTIFY( osg::ALWAYS ) << "Initialize visual_core..." << std::endl;
35
36        // Check for config file to provide it to all modules during initialization.
37        if( arguments.read("-c", configFilename) || arguments.read("--config", configFilename) )
38        {
39                if( !osgDB::fileExists(configFilename) )
40                        configFilename = "";
41                else
42                        OSG_ALWAYS << "Using configuration file: " << configFilename << std::endl;
43        }
44
45        // Configure osg to use KdTrees
46        osgDB::Registry::instance()->setBuildKdTreesHint(osgDB::ReaderWriter::Options::BUILD_KDTREES);
47
48        // Setup pathes
49        osgDB::Registry::instance()->getDataFilePathList().push_back( "D:\\DA\\osgVisual\\models" );
50       
51        // Setup viewer
52        viewer = new osgViewer::Viewer(arguments);
53
54        // Setup coordinate system node
55        rootNode = new osg::CoordinateSystemNode;       // todo memleakf
56        rootNode->setEllipsoidModel(new osg::EllipsoidModel());
57
58        // Test memory leak (todo)
59        double* test = new double[1000];
60
61        #ifdef USE_SPACENAVIGATOR
62                mouse = NULL;
63        #endif
64
65        //osg::DisplaySettings::instance()->setNumOfDatabaseThreadsHint( 8 );
66
67        // Show model
68        viewer->setSceneData( rootNode );
69
70        osg::Group* distortedSceneGraph = NULL;
71#ifdef USE_DISTORTION
72        // Initialize distortion
73        distortion = new visual_distortion( viewer, arguments, configFilename );
74        distortedSceneGraph = distortion->initialize( rootNode, viewer->getCamera()->getClearColor() );
75#endif
76
77#ifdef USE_SKY_SILVERLINING
78        // Initialize sky
79        bool disabled = false;  // to ask if the skyp is disabled or enabled
80        sky = new visual_skySilverLining( viewer, configFilename, disabled );
81        if(disabled)
82                sky = NULL;
83        if(sky.valid())
84                sky->init(distortedSceneGraph, rootNode);       // Without distortion: distortedSceneGraph=NULL
85#endif
86
87        // Initialize DataIO interface
88        visual_dataIO::getInstance()->init(viewer, configFilename);
89
90        // Add manipulators for user interaction - after dataIO to be able to skip it in slaves rendering machines.
91        addManipulators();
92
93        // create the windows and run the threads.
94        viewer->realize();
95
96        loadTerrain(arguments);
97
98        // All modules are initialized - now check arguments for any unused parameter.
99        checkCommandlineArgumentsForFinalErrors();
100
101        // Run visual main loop
102        mainLoop();
103}
104
105void visual_core::mainLoop()
106{
107        int framestoScenerySetup = 5;
108        // run main loop
109        while( !viewer->done() )
110    {
111                // setup scenery
112                if(framestoScenerySetup-- == 0)
113                        setupScenery();
114
115                // next frame please....
116        viewer->advance();
117
118                /*double hat, hot, lat, lon, height;
119                util::getWGS84ofCamera( viewer->getCamera(), rootNode, lat, lon, height);
120                if (util::queryHeightOfTerrain( hot, rootNode, lat, lon) && util::queryHeightAboveTerrainInWGS84( hat, rootNode, lat, lon, height ) )
121                        OSG_NOTIFY( osg::ALWAYS ) << "HOT is: " << hot << ", HAT is: " << hat << std::endl;*/
122       
123                // perform all queued events
124                viewer->eventTraversal();
125
126                // update the scene by traversing it with the the update visitor which will
127        // call all node update callbacks and animations.
128        viewer->updateTraversal();
129               
130        // Render the Frame.
131        viewer->renderingTraversals();
132
133    }   // END WHILE
134}
135
136void visual_core::shutdown()
137{
138        OSG_NOTIFY( osg::ALWAYS ) << "Shutdown visual_core..." << std::endl;
139
140        // Shutdown Dbug HUD
141        if(hud.valid())
142                hud->shutdown();
143        // Unset scene data
144        viewer->setSceneData( NULL );
145
146#ifdef USE_SKY_SILVERLINING
147        // Shutdown sky
148        if( sky.valid() )
149                sky->shutdown();
150#endif
151
152#ifdef USE_DISTORTION
153        // Shutdown distortion
154        if( distortion.valid() )
155                distortion->shutdown();
156#endif
157
158        // Shutdown data
159        rootNode = NULL;
160
161        // Shutdown dataIO
162        visual_dataIO::getInstance()->shutdown();
163
164       
165#ifdef USE_SPACENAVIGATOR
166        //Delete SpaceMouse driver
167        if(mouse)
168        {
169                mouse->shutdown();
170                delete mouse;
171        }
172#endif
173
174        // Destroy osgViewer
175        viewer = NULL;
176}
177
178bool visual_core::loadTerrain(osg::ArgumentParser& arguments_)
179{
180        osg::ref_ptr<osg::Node> model = osgDB::readNodeFiles(util::getTerrainFromXMLConfig(configFilename));
181        if( model.valid() )
182        {
183        rootNode->addChild( model.get() );
184                return true;
185        }
186        else
187        {
188        OSG_NOTIFY( osg::FATAL ) << "Load terrain: No data loaded" << std::endl;
189        return false;
190    }   
191
192        return false;
193}
194
195void visual_core::addManipulators()
196{
197        if(!visual_dataIO::getInstance()->isSlave()) // set up the camera manipulators if not slave.
198    {
199        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
200
201        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
202        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
203        keyswitchManipulator->addMatrixManipulator( '3', "Terrain", new osgGA::TerrainManipulator() );
204                nt = new osgGA::NodeTrackerManipulator();
205                keyswitchManipulator->addMatrixManipulator( '4', "NodeTrackerManipulator", nt );
206               
207#ifdef USE_SPACENAVIGATOR
208                // SpaceNavigator manipulator
209                mouse = new SpaceMouse();
210                mouse->initialize();
211                mouseTrackerManip = new NodeTrackerSpaceMouse(mouse);
212                mouseTrackerManip->setTrackerMode(NodeTrackerSpaceMouse::NODE_CENTER);
213                mouseTrackerManip->setRotationMode(NodeTrackerSpaceMouse::ELEVATION_AZIM);
214                mouseTrackerManip->setAutoComputeHomePosition( true );
215                keyswitchManipulator->addMatrixManipulator( '5', "Spacemouse Node Tracker", mouseTrackerManip );
216                keyswitchManipulator->addMatrixManipulator( '6', "Spacemouse Free (Airplane)", new FreeManipulator(mouse) );
217#endif
218
219                // objectMounted Manipulator for Camera control by Nodes
220                objectMountedCameraManip = new objectMountedManipulator();
221                keyswitchManipulator->addMatrixManipulator( '7', "Object mounted Camera", objectMountedCameraManip );
222
223                // Animation path manipulator
224                std::string pathfile = util::getAnimationPathFromXMLConfig(configFilename);
225        char keyForAnimationPath = '8';
226                if( pathfile != "" )
227        {
228            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
229            if (apm || !apm->valid()) 
230            {
231                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
232                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
233                keyswitchManipulator->selectMatrixManipulator(num);
234                ++keyForAnimationPath;
235            }
236        }
237
238        viewer->setCameraManipulator( keyswitchManipulator.get() );
239    }   // If not Slave END
240
241    // add the state manipulator
242    viewer->addEventHandler( new osgGA::StateSetManipulator(rootNode->getOrCreateStateSet()) );
243   
244    // add the thread model handler
245    viewer->addEventHandler(new osgViewer::ThreadingHandler);
246
247    // add the window size toggle handler
248    viewer->addEventHandler(new osgViewer::WindowSizeHandler);
249       
250    // add the stats handler
251    viewer->addEventHandler(new osgViewer::StatsHandler);
252
253    // add the help handler
254    viewer->addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));
255
256    // add the record camera path handler
257    viewer->addEventHandler(new osgViewer::RecordCameraPathHandler);
258
259    // add the LOD Scale handler
260    viewer->addEventHandler(new osgViewer::LODScaleHandler);
261
262    // add the screen capture handler
263    viewer->addEventHandler(new osgViewer::ScreenCaptureHandler);
264}
265
266void visual_core::parseScenery(xmlNode* a_node)
267{
268        OSG_ALWAYS << "parseScenery()" << std::endl;
269
270        a_node = a_node->children;
271
272        for (xmlNode *cur_node = a_node; cur_node; cur_node = cur_node->next)
273        {
274                std::string node_name=reinterpret_cast<const char*>(cur_node->name);
275
276                // terrain is parsend seperately
277                // animationpath is parsend seperately
278
279                if(cur_node->type == XML_ELEMENT_NODE && node_name == "models")
280                {
281                        for (xmlNode *modelNode = cur_node->children; modelNode; modelNode = modelNode->next)
282                        {
283                                std::string name=reinterpret_cast<const char*>(modelNode->name);
284                                if(cur_node->type == XML_ELEMENT_NODE && name == "model")
285                                {
286                                        visual_object::createNodeFromXMLConfig(rootNode, modelNode);
287                                }
288                        }
289                }
290
291#ifdef USE_SKY_SILVERLINING
292                if(cur_node->type == XML_ELEMENT_NODE && node_name == "datetime")
293                {
294                        int hour, minute;
295                        int day=0,month=0,year=0;
296
297                        xmlAttr  *attr = cur_node->properties;
298                        while ( attr ) 
299                        { 
300                                std::string attr_name=reinterpret_cast<const char*>(attr->name);
301                                std::string attr_value=reinterpret_cast<const char*>(attr->children->content);
302                                if( attr_name == "day" )
303                                {
304                                        std::stringstream sstr(attr_value);
305                                        sstr >> day;
306                                }
307                                if( attr_name == "month" )
308                                {
309                                        std::stringstream sstr(attr_value);
310                                        sstr >> month;
311                                }
312                                if( attr_name == "year" )
313                                {
314                                        std::stringstream sstr(attr_value);
315                                        sstr >> year;
316                                }
317                                if( attr_name == "hour" )
318                                {
319                                        std::stringstream sstr(attr_value);
320                                        sstr >> hour;
321                                }
322                                if( attr_name == "minute" )
323                                {
324                                        std::stringstream sstr(attr_value);
325                                        sstr >> minute;
326                                }
327                                attr = attr->next; 
328                        }
329                        if(sky.valid())
330                        {
331                                if(day!=0 && month!=0 && year!=0)
332                                        sky->setDate(year, month, day);
333                                sky->setTime(hour,minute,00);
334                        }
335                }
336
337                if(cur_node->type == XML_ELEMENT_NODE && node_name == "visibility")
338                {
339                        float range = 50000, turbidity=2.2;
340                        xmlAttr  *attr = cur_node->properties;
341                        while ( attr ) 
342                        { 
343                                std::string attr_name=reinterpret_cast<const char*>(attr->name);
344                                std::string attr_value=reinterpret_cast<const char*>(attr->children->content);
345                                if( attr_name == "range" )
346                                {
347                                        std::stringstream sstr(attr_value);
348                                        sstr >> range;
349                                }
350                                if( attr_name == "turbidity" )
351                                {
352                                        std::stringstream sstr(attr_value);
353                                        sstr >> turbidity;
354                                }
355                                attr = attr->next; 
356                        }
357
358                        if(sky.valid())
359                        {
360                                sky->setVisibility( range );
361                                sky->setTurbidity( turbidity );
362                        }
363                }
364
365                if(cur_node->type == XML_ELEMENT_NODE && node_name == "clouds")
366                {
367                        if(sky.valid())
368                                sky->configureCloudlayerbyXML( cur_node );
369                }
370
371                if(cur_node->type == XML_ELEMENT_NODE && node_name == "windlayer")
372                {
373                        float bottom = 0.0, top=5000.0, speed=25.0, direction=0.0;
374                        xmlAttr  *attr = cur_node->properties;
375                        while ( attr ) 
376                        { 
377                                std::string attr_name=reinterpret_cast<const char*>(attr->name);
378                                std::string attr_value=reinterpret_cast<const char*>(attr->children->content);
379                                if( attr_name == "bottom" )
380                                {
381                                        std::stringstream sstr(attr_value);
382                                        sstr >> bottom;
383                                }
384                                if( attr_name == "top" )
385                                {
386                                        std::stringstream sstr(attr_value);
387                                        sstr >> top;
388                                }
389                                if( attr_name == "speed" )
390                                {
391                                        std::stringstream sstr(attr_value);
392                                        sstr >> speed;
393                                }
394                                if( attr_name == "direction" )
395                                {
396                                        std::stringstream sstr(attr_value);
397                                        sstr >> direction;
398                                }
399                                attr = attr->next; 
400                        }
401                        if(sky.valid())
402                        {
403                                sky->addWindVolume( bottom, top, speed, direction );
404                        }
405                }
406
407                // Track Node
408
409#endif
410        }// FOR all nodes END
411
412}
413
414bool visual_core::checkCommandlineArgumentsForFinalErrors()
415{
416        // Setup Application Usage
417        arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
418        arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the new FSD visualization tool, written by Torben Dannhauer");
419    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [OSG options] -c XML-Configurationfile");
420        arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
421        arguments.getApplicationUsage()->addCommandLineOption("-c or --config","XML configuration filename");
422
423
424    // if user request help write it out to cout.
425    if (arguments.read("-h") || arguments.read("--help"))
426    {
427        arguments.getApplicationUsage()->write(std::cout);
428                //cause the viewer to exit and shut down clean.
429        viewer->setDone(true);
430    }
431
432    // report any errors if they have occurred when parsing the program arguments.
433    if (arguments.errors())
434    {
435        arguments.writeErrorMessages(std::cout);
436                //cause the viewer to exit and shut down clean.
437        viewer->setDone(true);
438    }
439
440         // any option left unread are converted into errors to write out later.
441    arguments.reportRemainingOptionsAsUnrecognized();
442
443    // report any errors if they have occurred when parsing the program arguments.
444    if (arguments.errors())
445    {
446        arguments.writeErrorMessages(std::cout);
447        return false;
448    }
449        return true;
450}
451
452void visual_core::setupScenery()
453{
454        // Parse Scenery from Configuration file
455        xmlDoc* tmpDoc;
456        xmlNode* sceneryNode = util::getSceneryXMLConfig(configFilename, tmpDoc);
457        parseScenery(sceneryNode);
458        if(sceneryNode)
459        {
460                xmlFreeDoc(tmpDoc); xmlCleanupParser();
461        }
462
463
464
465        //testObj = new visual_object( rootNode, "testStab", objectMountedCameraManip );
466        //testObj->setNewPosition( osg::DegreesToRadians(47.7123), osg::DegreesToRadians(12.84088), 600 );
467        ///* using a huge cylinder to test position & orientation */
468        //testObj->setGeometry( util::getDemoCylinder(5000.0, 20.0 ) );
469        //testObj->addUpdater( new object_updater(testObj) );
470
471        //osg::ref_ptr<visual_object> testObj2 = new visual_object( rootNode, "neuschwanstein" );       // todo memleak
472        ////testObj2->setNewPosition( osg::DegreesToRadians(47.8123), osg::DegreesToRadians(12.94088), 600 );
473        //testObj2->setNewPosition( osg::DegreesToRadians(47.557523564234), osg::DegreesToRadians(10.749646398595), 950 );
474        //testObj2->loadGeometry( "../models/neuschwanstein.osgb" );
475        ////testObj2->addUpdater( new object_updater(testObj2) );       // todo memleak
476
477        //osg::ref_ptr<visual_object> testObj3 = new visual_object( rootNode, "SAENGER1" );     // todo memleak
478        //testObj3->setNewPosition( osg::DegreesToRadians(47.8123), osg::DegreesToRadians(12.94088), 600 );
479        //testObj3->loadGeometry( "../models/saenger1.flt" );
480        //testObj3->addUpdater( new object_updater(testObj3) ); // todo memleak
481        //
482
483        osg::ref_ptr<visual_object> testObj4 = new visual_object( rootNode, "SAENGER2" );       // todo memleak
484        testObj4->setNewPosition( osg::DegreesToRadians(47.8123), osg::DegreesToRadians(12.94088), 650 );
485        testObj4->loadGeometry( "../models/saenger2.flt" );
486        testObj4->addUpdater( new object_updater(testObj4) );   // todo memleak
487        testObj4->addLabel("testLabel", "LabelTest!!\nnächste Zeile :)",osg::Vec4(1.0f,0.25f,1.0f,1.0f));
488
489        //osg::ref_ptr<visual_object> testObj5 = new visual_object( rootNode, "SAENGER" );      // todo memleak
490        //testObj5->setNewPosition( osg::DegreesToRadians(47.8123), osg::DegreesToRadians(12.94088), 550 );
491        //testObj5->loadGeometry( "../models/saengerCombine.flt" );
492        ////testObj5->setScale( 2 );
493        //testObj5->addUpdater( new object_updater(testObj5) ); // todo memleak
494
495        trackNode( testObj4 );
496
497        // Load EDDF
498        //std::string filename = "D:\\DA\\EDDF_test\\eddf.ive";
499        //if( !osgDB::fileExists(filename) )
500        //{
501        //      OSG_NOTIFY(osg::ALWAYS) << "Warning: EDDF Model not loaded. File '" << filename << "' does not exist. Skipping.";
502        //}
503        //// read model
504        //osg::ref_ptr<osg::Node> tmpModel = osgDB::readNodeFile( filename );
505        //if (tmpModel.valid())
506        //      rootNode->addChild( tmpModel );
507       
508 
509        visual_draw2D::getInstance()->init( rootNode, viewer );
510        //osg::ref_ptr<visual_hud> hud = new visual_hud();
511        hud = new visual_debug_hud();
512        hud->init( viewer, rootNode );
513       
514       
515
516        //osg::ref_ptr<visual_draw3D> test = new visual_draw3D();
517        //test->init( rootNode, viewer );
518
519        //// Creating Testclasses
520        //osg::ref_ptr<osgVisual::dataIO_transportContainer> test = new osgVisual::dataIO_transportContainer();
521        //osg::ref_ptr<osgVisual::dataIO_executer> testEx = new osgVisual::dataIO_executer();
522        //osg::ref_ptr<osgVisual::dataIO_slot> testSlot = new osgVisual::dataIO_slot();
523        //test->setFrameID( 22 );
524        //test->setName("ugamoep");
525        //testEx->setexecuterID( osgVisual::dataIO_executer::IS_COLLISION );
526        //testSlot->setVariableName(std::string("HalloName"));
527        //testSlot->setdataDirection( osgVisual::dataIO_slot::TO_OBJ );
528        //testSlot->setvarType( osgVisual::dataIO_slot::DOUBLE );
529        //testSlot->setValue( 0.12345 );
530        //test->addExecuter( testEx );
531        //test->addSlot( testSlot );
532
533        visual_dataIO::getInstance()->setSlotData("TestSlot1", osgVisual::dataIO_slot::TO_OBJ, 0.12345);
534
535}
536
537void visual_core::trackNode( osg::Node* node_ )
538{
539        if(!node_)
540                return;
541
542        osg::Node* node = NULL;
543        // Check if tracked node is a visual_object
544        osgVisual::visual_object* trackedObject = dynamic_cast<osgVisual::visual_object*>(node_);
545        if(trackedObject)
546        {
547                if(trackedObject->getGeometry())
548                        node = trackedObject->getGeometry();
549                else
550                        node = trackedObject;
551
552                // Object mounted manipulator ( Only working with visual_object, not with osg::Node )
553                if (objectMountedCameraManip.valid())
554                        objectMountedCameraManip->setAttachedObject( trackedObject );
555        }
556        else
557                node = node_;
558
559        // Spacemouse Node Tracker
560#ifdef USE_SPACENAVIGATOR
561        if (mouseTrackerManip.valid())
562        {
563                mouseTrackerManip->setTrackNode( node );
564                mouseTrackerManip->setMinimumDistance( 100 );
565        }
566#endif
567
568        // Classical OSG Nodetracker
569        if(nt.valid())
570        {
571                osgGA::NodeTrackerManipulator::TrackerMode trackerMode = osgGA::NodeTrackerManipulator::NODE_CENTER;
572                osgGA::NodeTrackerManipulator::RotationMode rotationMode = osgGA::NodeTrackerManipulator::ELEVATION_AZIM;
573                nt->setTrackerMode(trackerMode);
574                nt->setRotationMode(rotationMode);
575                nt->setMinimumDistance( 100 );
576                nt->setTrackNode( node );
577                nt->setAutoComputeHomePosition( true );
578                nt->setDistance( 250 );
579        }
580}
Note: See TracBrowser for help on using the repository browser.