1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2  *
3  * This library is 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  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * OpenSceneGraph Public License for more details.
12 */
13 
14 #include <osg/GLExtensions>
15 #include <osg/TextureRectangle>
16 #include <osg/TextureCubeMap>
17 
18 #include <osgGA/TrackballManipulator>
19 #include <osgViewer/CompositeViewer>
20 #include <osgViewer/Renderer>
21 #include <osgDB/Registry>
22 #include <osgDB/ReadFile>
23 
24 #include <osg/io_utils>
25 
26 using namespace osgViewer;
27 
CompositeViewer()28 CompositeViewer::CompositeViewer()
29 {
30     constructorInit();
31 }
32 
CompositeViewer(const CompositeViewer & cv,const osg::CopyOp & copyop)33 CompositeViewer::CompositeViewer(const CompositeViewer& cv,const osg::CopyOp& copyop):
34     osg::Object(cv, copyop),
35     ViewerBase(cv)
36 {
37     constructorInit();
38 }
39 
CompositeViewer(osg::ArgumentParser & arguments)40 CompositeViewer::CompositeViewer(osg::ArgumentParser& arguments)
41 {
42     constructorInit();
43 
44     arguments.getApplicationUsage()->addCommandLineOption("--SingleThreaded","Select SingleThreaded threading model for viewer.");
45     arguments.getApplicationUsage()->addCommandLineOption("--CullDrawThreadPerContext","Select CullDrawThreadPerContext threading model for viewer.");
46     arguments.getApplicationUsage()->addCommandLineOption("--DrawThreadPerContext","Select DrawThreadPerContext threading model for viewer.");
47     arguments.getApplicationUsage()->addCommandLineOption("--CullThreadPerCameraDrawThreadPerContext","Select CullThreadPerCameraDrawThreadPerContext threading model for viewer.");
48 
49     arguments.getApplicationUsage()->addCommandLineOption("--run-on-demand","Set the run methods frame rate management to only rendering frames when required.");
50     arguments.getApplicationUsage()->addCommandLineOption("--run-continuous","Set the run methods frame rate management to rendering frames continuously.");
51     arguments.getApplicationUsage()->addCommandLineOption("--run-max-frame-rate","Set the run methods maximum permissible frame rate, 0.0 is default and switching off frame rate capping.");
52 
53 
54     std::string filename;
55     bool readConfig = false;
56     while (arguments.read("-c",filename))
57     {
58         readConfig = readConfiguration(filename) || readConfig;
59     }
60 
61     while (arguments.read("--SingleThreaded")) setThreadingModel(SingleThreaded);
62     while (arguments.read("--CullDrawThreadPerContext")) setThreadingModel(CullDrawThreadPerContext);
63     while (arguments.read("--DrawThreadPerContext")) setThreadingModel(DrawThreadPerContext);
64     while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) setThreadingModel(CullThreadPerCameraDrawThreadPerContext);
65 
66 
67     while(arguments.read("--run-on-demand")) { setRunFrameScheme(ON_DEMAND); }
68     while(arguments.read("--run-continuous")) { setRunFrameScheme(CONTINUOUS); }
69 
70     double runMaxFrameRate;
71     while(arguments.read("--run-max-frame-rate", runMaxFrameRate)) { setRunMaxFrameRate(runMaxFrameRate); }
72 
73 
74     osg::DisplaySettings::instance()->readCommandLine(arguments);
75     osgDB::readCommandLine(arguments);
76 }
77 
constructorInit()78 void CompositeViewer::constructorInit()
79 {
80     _endBarrierPosition = AfterSwapBuffers;
81     _startTick = 0;
82 
83     // make sure View is safe to reference multi-threaded.
84     setThreadSafeRefUnref(true);
85 
86     _frameStamp = new osg::FrameStamp;
87     _frameStamp->setFrameNumber(0);
88     _frameStamp->setReferenceTime(0);
89     _frameStamp->setSimulationTime(0);
90 
91     _eventVisitor = new osgGA::EventVisitor;
92     _eventVisitor->setFrameStamp(_frameStamp.get());
93 
94     _updateVisitor = new osgUtil::UpdateVisitor;
95     _updateVisitor->setFrameStamp(_frameStamp.get());
96 
97     setViewerStats(new osg::Stats("CompsiteViewer"));
98 }
99 
~CompositeViewer()100 CompositeViewer::~CompositeViewer()
101 {
102     OSG_INFO<<"CompositeViewer::~CompositeViewer()"<<std::endl;
103 
104     stopThreading();
105 
106     Scenes scenes;
107     getScenes(scenes);
108 
109     for(Scenes::iterator sitr = scenes.begin();
110         sitr != scenes.end();
111         ++sitr)
112     {
113         Scene* scene = *sitr;
114         if (scene->getDatabasePager())
115         {
116             scene->getDatabasePager()->cancel();
117             scene->setDatabasePager(0);
118         }
119     }
120 
121     Contexts contexts;
122     getContexts(contexts);
123 
124     // clear out all the previously assigned operations
125     for(Contexts::iterator citr = contexts.begin();
126         citr != contexts.end();
127         ++citr)
128     {
129         osg::GraphicsContext* gc = *citr;
130 
131         // Run destroy operation on each context before closing it
132         if (_cleanUpOperation.valid() && gc->valid())
133         {
134             gc->makeCurrent();
135 
136             (*_cleanUpOperation)(gc);
137 
138             gc->releaseContext();
139         }
140 
141         gc->close();
142     }
143 
144     OSG_INFO<<"finished CompositeViewer::~CompositeViewer()"<<std::endl;
145 }
146 
readConfiguration(const std::string & filename)147 bool CompositeViewer::readConfiguration(const std::string& filename)
148 {
149     OSG_NOTICE<<"CompositeViewer::readConfiguration("<<filename<<")"<<std::endl;
150     osg::ref_ptr<osg::Object> obj = osgDB::readRefObjectFile(filename);
151     osgViewer::View * view = dynamic_cast<osgViewer::View *>(obj.get());
152     if (view)
153     {
154         addView(view);
155         return true;
156     }
157     return false;
158 }
159 
160 
addView(osgViewer::View * view)161 void CompositeViewer::addView(osgViewer::View* view)
162 {
163     if (!view) return;
164 
165     bool alreadyRealized = isRealized();
166 
167     bool threadsWereRunning = _threadsRunning;
168     if (threadsWereRunning) stopThreading();
169 
170     _views.push_back(view);
171 
172     view->_viewerBase = this;
173 
174     if (view->getSceneData())
175     {
176         // make sure that existing scene graph objects are allocated with thread safe ref/unref
177         if (getThreadingModel()!=ViewerBase::SingleThreaded)
178         {
179             view->getSceneData()->setThreadSafeRefUnref(true);
180         }
181 
182         // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it.
183         view->getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts());
184     }
185 
186     view->setFrameStamp(_frameStamp.get());
187 
188     if (alreadyRealized)
189     {
190         Contexts contexts;
191         if (view->getCamera()->getGraphicsContext())
192         {
193             contexts.push_back(view->getCamera()->getGraphicsContext());
194         }
195         for(unsigned int i=0; i<view->getNumSlaves(); ++i)
196         {
197             if (view->getSlave(i)._camera->getGraphicsContext())
198             {
199                 contexts.push_back(view->getSlave(i)._camera->getGraphicsContext());
200             }
201         }
202 
203         for(Contexts::iterator itr = contexts.begin();
204             itr != contexts.end();
205             ++itr)
206         {
207             if (!((*itr)->isRealized()))
208             {
209                 (*itr)->realize();
210             }
211         }
212 
213     }
214 
215     if (threadsWereRunning) startThreading();
216 }
217 
removeView(osgViewer::View * view)218 void CompositeViewer::removeView(osgViewer::View* view)
219 {
220     for(RefViews::iterator itr = _views.begin();
221         itr != _views.end();
222         ++itr)
223     {
224         if (*itr == view)
225         {
226             bool threadsWereRunning = _threadsRunning;
227             if (threadsWereRunning) stopThreading();
228 
229             // clean up any attached contexts that are solely attached to this view
230             typedef std::map<osg::GraphicsContext*, int> ContextMap;
231             ContextMap contexts;
232 
233             if (view->getCamera()->getGraphicsContext())
234             {
235                 view->getCamera()->releaseGLObjects(view->getCamera()->getGraphicsContext()->getState());
236                 contexts[view->getCamera()->getGraphicsContext()]++;
237             }
238             for(unsigned int i=0; i<view->getNumSlaves(); ++i)
239             {
240                 if (view->getSlave(i)._camera->getGraphicsContext())
241                 {
242                     view->getSlave(i)._camera->releaseGLObjects(view->getSlave(i)._camera->getGraphicsContext()->getState());
243                     contexts[view->getSlave(i)._camera->getGraphicsContext()]++;
244                 }
245             }
246 
247             for(ContextMap::iterator citr = contexts.begin();
248                 citr != contexts.end();
249                 ++citr)
250             {
251                 osg::GraphicsContext* gc = citr->first;
252                 if (citr->second == gc->referenceCount())
253                 {
254                     if (_cleanUpOperation.valid())
255                     {
256                         gc->makeCurrent();
257 
258                         (*_cleanUpOperation)(gc);
259 
260                         gc->releaseContext();
261                     }
262 
263                     gc->close();
264                 }
265             }
266 
267             view->_viewerBase = 0;
268             _views.erase(itr);
269 
270             if (threadsWereRunning) startThreading();
271 
272             return;
273         }
274     }
275 }
276 
isRealized() const277 bool CompositeViewer::isRealized() const
278 {
279     Contexts contexts;
280     const_cast<CompositeViewer*>(this)->getContexts(contexts);
281 
282     unsigned int numRealizedWindows = 0;
283 
284     // clear out all the previously assigned operations
285     for(Contexts::iterator citr = contexts.begin();
286         citr != contexts.end();
287         ++citr)
288     {
289         if ((*citr)->isRealized()) ++numRealizedWindows;
290     }
291 
292     return numRealizedWindows > 0;
293 }
294 
checkNeedToDoFrame()295 bool CompositeViewer::checkNeedToDoFrame()
296 {
297     // check if any event handler has prompted a redraw
298     if (_requestRedraw) return true;
299     if (_requestContinousUpdate) return true;
300 
301     // check if any view needs to update the scene graph
302     for(RefViews::iterator itr = _views.begin();
303         itr != _views.end();
304         ++itr)
305     {
306         osgViewer::View* view = itr->get();
307         if (view && (view->requiresUpdateSceneGraph() || view->requiresRedraw())) return true;
308     }
309 
310     // check if events are available and need processing
311     if (checkEvents()) return true;
312 
313     // and check again if any event handler has prompted a redraw
314     if (_requestRedraw) return true;
315     if (_requestContinousUpdate) return true;
316 
317     return false;
318 }
319 
320 
checkEvents()321 bool CompositeViewer::checkEvents()
322 {
323     for(RefViews::iterator itr = _views.begin();
324         itr != _views.end();
325         ++itr)
326     {
327         osgViewer::View* view = itr->get();
328         if (view)
329         {
330             // check events from any attached sources
331             for(View::Devices::iterator eitr = view->getDevices().begin();
332                 eitr != view->getDevices().end();
333                 ++eitr)
334             {
335                 osgGA::Device* es = eitr->get();
336                 if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS)
337                 {
338                     if (es->checkEvents()) return true;
339                 }
340 
341             }
342         }
343     }
344 
345     // get events from all windows attached to Viewer.
346     Windows windows;
347     getWindows(windows);
348     for(Windows::iterator witr = windows.begin();
349         witr != windows.end();
350         ++witr)
351     {
352         if ((*witr)->checkEvents()) return true;
353     }
354 
355     return false;
356 }
357 
run()358 int CompositeViewer::run()
359 {
360     for(RefViews::iterator itr = _views.begin();
361         itr != _views.end();
362         ++itr)
363     {
364         osgViewer::View* view = itr->get();
365         if ((view->getCameraManipulator()==0) && view->getCamera()->getAllowEventFocus())
366         {
367             view->setCameraManipulator(new osgGA::TrackballManipulator());
368         }
369     }
370 
371     setReleaseContextAtEndOfFrameHint(false);
372 
373     return ViewerBase::run();
374 }
375 
setStartTick(osg::Timer_t tick)376 void CompositeViewer::setStartTick(osg::Timer_t tick)
377 {
378     _startTick = tick;
379 
380     for(RefViews::iterator vitr = _views.begin();
381         vitr != _views.end();
382         ++vitr)
383     {
384         (*vitr)->setStartTick(tick);
385     }
386 
387     Contexts contexts;
388     getContexts(contexts,false);
389 
390     for(Contexts::iterator citr = contexts.begin();
391         citr != contexts.end();
392         ++citr)
393     {
394         osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
395         if (gw)
396         {
397             gw->getEventQueue()->setStartTick(_startTick);
398         }
399     }
400 }
401 
402 
setReferenceTime(double time)403 void CompositeViewer::setReferenceTime(double time)
404 {
405     osg::Timer_t tick = osg::Timer::instance()->tick();
406     double currentTime = osg::Timer::instance()->delta_s(_startTick, tick);
407     double delta_ticks = (time-currentTime)/(osg::Timer::instance()->getSecondsPerTick());
408     if (delta_ticks>=0) tick += osg::Timer_t(delta_ticks);
409     else tick -= osg::Timer_t(-delta_ticks);
410 
411     // assign the new start tick
412     setStartTick(tick);
413 }
414 
415 
416 
viewerInit()417 void CompositeViewer::viewerInit()
418 {
419     OSG_INFO<<"CompositeViewer::init()"<<std::endl;
420 
421     for(RefViews::iterator itr = _views.begin();
422         itr != _views.end();
423         ++itr)
424     {
425         (*itr)->init();
426     }
427 }
428 
getContexts(Contexts & contexts,bool onlyValid)429 void CompositeViewer::getContexts(Contexts& contexts, bool onlyValid)
430 {
431     typedef std::set<osg::GraphicsContext*> ContextSet;
432     ContextSet contextSet;
433 
434     contexts.clear();
435 
436     for(RefViews::iterator vitr = _views.begin();
437         vitr != _views.end();
438         ++vitr)
439     {
440         osgViewer::View* view = vitr->get();
441         osg::GraphicsContext* gc = view->getCamera() ? view->getCamera()->getGraphicsContext() : 0;
442         if (gc && (gc->valid() || !onlyValid))
443         {
444             if (contextSet.count(gc)==0)
445             {
446                 contextSet.insert(gc);
447                 contexts.push_back(gc);
448             }
449         }
450 
451         for(unsigned int i=0; i<view->getNumSlaves(); ++i)
452         {
453             View::Slave& slave = view->getSlave(i);
454             osg::GraphicsContext* sgc = slave._camera.valid() ? slave._camera->getGraphicsContext() : 0;
455             if (sgc && (sgc->valid() || !onlyValid))
456             {
457                 if (contextSet.count(sgc)==0)
458                 {
459                     contextSet.insert(sgc);
460                     contexts.push_back(sgc);
461                 }
462             }
463         }
464     }
465 }
466 
getCameras(Cameras & cameras,bool onlyActive)467 void CompositeViewer::getCameras(Cameras& cameras, bool onlyActive)
468 {
469     cameras.clear();
470 
471     for(RefViews::iterator vitr = _views.begin();
472         vitr != _views.end();
473         ++vitr)
474     {
475         View* view = vitr->get();
476 
477         if (view->getCamera() &&
478             (!onlyActive || (view->getCamera()->getGraphicsContext() && view->getCamera()->getGraphicsContext()->valid())) ) cameras.push_back(view->getCamera());
479 
480         for(View::Slaves::iterator itr = view->_slaves.begin();
481             itr != view->_slaves.end();
482             ++itr)
483         {
484             if (itr->_camera.valid() &&
485                 (!onlyActive || (itr->_camera->getGraphicsContext() && itr->_camera->getGraphicsContext()->valid())) ) cameras.push_back(itr->_camera.get());
486         }
487     }
488 }
489 
getScenes(Scenes & scenes,bool onlyValid)490 void CompositeViewer::getScenes(Scenes& scenes, bool onlyValid)
491 {
492     scenes.clear();
493 
494     typedef std::set<osgViewer::Scene*> SceneSet;
495     SceneSet sceneSet;
496 
497     for(RefViews::iterator vitr = _views.begin();
498         vitr != _views.end();
499         ++vitr)
500     {
501         osgViewer::View* view = vitr->get();
502         if (view->getScene() && (!onlyValid || view->getScene()->getSceneData()))
503         {
504             if (sceneSet.count(view->getScene())==0)
505             {
506                 sceneSet.insert(view->getScene());
507                 scenes.push_back(view->getScene());
508             }
509         }
510     }
511 }
512 
getViews(Views & views,bool)513 void CompositeViewer::getViews(Views& views, bool /*onlyValid*/)
514 {
515     views.clear();
516 
517     for(RefViews::iterator vitr = _views.begin();
518         vitr != _views.end();
519         ++vitr)
520     {
521         views.push_back(vitr->get());
522     }
523 }
524 
getAllThreads(Threads & threads,bool onlyActive)525 void CompositeViewer::getAllThreads(Threads& threads, bool onlyActive)
526 {
527     threads.clear();
528 
529     OperationThreads operationThreads;
530     getOperationThreads(operationThreads);
531 
532     for(OperationThreads::iterator itr = operationThreads.begin();
533         itr != operationThreads.end();
534         ++itr)
535     {
536         threads.push_back(*itr);
537     }
538 
539     Scenes scenes;
540     getScenes(scenes);
541 
542     for(Scenes::iterator sitr = scenes.begin();
543         sitr != scenes.end();
544         ++sitr)
545     {
546         Scene* scene = *sitr;
547         osgDB::DatabasePager* dp = scene->getDatabasePager();
548         if (dp)
549         {
550             for(unsigned int i=0; i<dp->getNumDatabaseThreads(); ++i)
551             {
552                 osgDB::DatabasePager::DatabaseThread* dt = dp->getDatabaseThread(i);
553                 if (!onlyActive || dt->isRunning())
554                 {
555                     threads.push_back(dt);
556                 }
557             }
558         }
559     }
560 }
561 
562 
getOperationThreads(OperationThreads & threads,bool onlyActive)563 void CompositeViewer::getOperationThreads(OperationThreads& threads, bool onlyActive)
564 {
565     threads.clear();
566 
567     Contexts contexts;
568     getContexts(contexts);
569     for(Contexts::iterator gcitr = contexts.begin();
570         gcitr != contexts.end();
571         ++gcitr)
572     {
573         osg::GraphicsContext* gc = *gcitr;
574         if (gc->getGraphicsThread() &&
575             (!onlyActive || gc->getGraphicsThread()->isRunning()) )
576         {
577             threads.push_back(gc->getGraphicsThread());
578         }
579     }
580 
581     Cameras cameras;
582     getCameras(cameras);
583     for(Cameras::iterator citr = cameras.begin();
584         citr != cameras.end();
585         ++citr)
586     {
587         osg::Camera* camera = *citr;
588         if (camera->getCameraThread() &&
589             (!onlyActive || camera->getCameraThread()->isRunning()) )
590         {
591             threads.push_back(camera->getCameraThread());
592         }
593     }
594 
595 }
596 
realize()597 void CompositeViewer::realize()
598 {
599     //OSG_INFO<<"CompositeViewer::realize()"<<std::endl;
600 
601     setCameraWithFocus(0);
602 
603     if (_views.empty())
604     {
605         OSG_NOTICE<<"CompositeViewer::realize() - No views to realize."<<std::endl;
606         _done = true;
607         return;
608     }
609 
610     Contexts contexts;
611     getContexts(contexts);
612 
613     if (contexts.empty())
614     {
615         OSG_INFO<<"CompositeViewer::realize() - No valid contexts found, setting up view across all screens."<<std::endl;
616 
617         // no windows are already set up so set up a default view
618         _views[0]->setUpViewAcrossAllScreens();
619 
620         getContexts(contexts);
621     }
622 
623     if (contexts.empty())
624     {
625         OSG_NOTICE<<"CompositeViewer::realize() - failed to set up any windows"<<std::endl;
626         _done = true;
627         return;
628     }
629 
630     // get the display settings that will be active for this viewer
631     osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
632     osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
633 
634     // pass on the display settings to the WindowSystemInterface.
635     if (wsi && wsi->getDisplaySettings()==0) wsi->setDisplaySettings(ds);
636 
637     unsigned int maxTexturePoolSize = ds->getMaxTexturePoolSize();
638     unsigned int maxBufferObjectPoolSize = ds->getMaxBufferObjectPoolSize();
639 
640     for(Contexts::iterator citr = contexts.begin();
641         citr != contexts.end();
642         ++citr)
643     {
644         osg::GraphicsContext* gc = *citr;
645 
646         if (ds->getSyncSwapBuffers()) gc->setSwapCallback(new osg::SyncSwapBuffersCallback);
647 
648         // set the pool sizes, 0 the default will result in no GL object pools.
649         gc->getState()->setMaxTexturePoolSize(maxTexturePoolSize);
650         gc->getState()->setMaxBufferObjectPoolSize(maxBufferObjectPoolSize);
651 
652         gc->realize();
653 
654         if (_realizeOperation.valid() && gc->valid())
655         {
656             gc->makeCurrent();
657 
658             (*_realizeOperation)(gc);
659 
660             gc->releaseContext();
661         }
662     }
663 
664     // attach contexts to _incrementalCompileOperation if attached.
665     if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts);
666 
667     bool grabFocus = true;
668     if (grabFocus)
669     {
670         for(Contexts::iterator citr = contexts.begin();
671             citr != contexts.end();
672             ++citr)
673         {
674             osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
675             if (gw)
676             {
677                 gw->grabFocusIfPointerInWindow();
678             }
679         }
680     }
681 
682 
683     // initialize the global timer to be relative to the current time.
684     osg::Timer::instance()->setStartTick();
685 
686     // pass on the start tick to all the associated eventqueues
687     setStartTick(osg::Timer::instance()->getStartTick());
688 
689     // configure threading.
690     setUpThreading();
691 
692     if (osg::DisplaySettings::instance()->getCompileContextsHint())
693     {
694         for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i)
695         {
696             osg::GraphicsContext* gc = osg::GraphicsContext::getOrCreateCompileContext(i);
697 
698             if (gc)
699             {
700                 gc->createGraphicsThread();
701                 gc->getGraphicsThread()->startThread();
702             }
703         }
704     }
705 
706 }
707 
advance(double simulationTime)708 void CompositeViewer::advance(double simulationTime)
709 {
710     if (_done) return;
711 
712     double previousReferenceTime = _frameStamp->getReferenceTime();
713     unsigned int previousFrameNumber = _frameStamp->getFrameNumber();
714 
715 
716     _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1);
717 
718     _frameStamp->setReferenceTime( osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()) );
719 
720     if (simulationTime==USE_REFERENCE_TIME)
721     {
722         _frameStamp->setSimulationTime(_frameStamp->getReferenceTime());
723     }
724     else
725     {
726         _frameStamp->setSimulationTime(simulationTime);
727     }
728 
729 
730     if (getViewerStats() && getViewerStats()->collectStats("frame_rate"))
731     {
732         // update previous frame stats
733         double deltaFrameTime = _frameStamp->getReferenceTime() - previousReferenceTime;
734         getViewerStats()->setAttribute(previousFrameNumber, "Frame duration", deltaFrameTime);
735         getViewerStats()->setAttribute(previousFrameNumber, "Frame rate", 1.0/deltaFrameTime);
736 
737         // update current frames stats
738         getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Reference time", _frameStamp->getReferenceTime());
739     }
740 
741 }
742 
setCameraWithFocus(osg::Camera * camera)743 void CompositeViewer::setCameraWithFocus(osg::Camera* camera)
744 {
745     _cameraWithFocus = camera;
746 
747     if (camera)
748     {
749         for(RefViews::iterator vitr = _views.begin();
750             vitr != _views.end();
751             ++vitr)
752         {
753             View* view = vitr->get();
754             if (view->containsCamera(camera))
755             {
756                 _viewWithFocus = view;
757                 return;
758             }
759         }
760     }
761 
762     _viewWithFocus = 0;
763 }
764 
765 
generateSlavePointerData(osg::Camera * camera,osgGA::GUIEventAdapter & event)766 void CompositeViewer::generateSlavePointerData(osg::Camera* camera, osgGA::GUIEventAdapter& event)
767 {
768     osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
769     if (!gw) return;
770 
771     // What type of Camera is it?
772     // 1) Master Camera : do nothin extra
773     // 2) Slave Camera, Relative RF, Same scene graph as master : transform coords into Master Camera and add to PointerData list
774     // 3) Slave Camera, Relative RF, Different scene graph from master : do nothing extra?
775     // 4) Slave Camera, Absolute RF, Same scene graph as master : do nothing extra?
776     // 5) Slave Camera, Absolute RF, Different scene graph : do nothing extra?
777     // 6) Slave Camera, Absolute RF, Different scene graph but a distortion correction subgraph depending upon RTT Camera (slave or master)
778     //                              : project ray into RTT Camera's clip space, and RTT Camera's is Relative RF and sharing same scene graph as master then transform coords.
779 
780     // if camera isn't the master it must be a slave and could need reprojecting.
781 
782 
783     osgViewer::View* view = dynamic_cast<osgViewer::View*>(camera->getView());
784     if (!view) return;
785 
786     osg::Camera* view_masterCamera = view->getCamera();
787     if (camera!=view_masterCamera)
788     {
789         float x = event.getX();
790         float y = event.getY();
791 
792         bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
793         if (invert_y && gw->getTraits()) y = gw->getTraits()->height - 1 - y;
794 
795         double master_min_x = -1.0;
796         double master_max_x = 1.0;
797         double master_min_y = -1.0;
798         double master_max_y = 1.0;
799 
800         osg::Matrix masterCameraVPW = view_masterCamera->getViewMatrix() * view_masterCamera->getProjectionMatrix();
801         if (view_masterCamera->getViewport())
802         {
803             osg::Viewport* viewport = view_masterCamera->getViewport();
804             master_min_x = viewport->x();
805             master_min_y = viewport->y();
806             master_max_x = viewport->x() + viewport->width() - 1;
807             master_max_y = viewport->y() + viewport->height() - 1;
808             masterCameraVPW *= viewport->computeWindowMatrix();
809         }
810 
811         // slave Camera tahnks to sharing the same View
812         osg::View::Slave* slave = view->findSlaveForCamera(camera);
813         if (slave)
814         {
815             if (camera->getReferenceFrame()==osg::Camera::RELATIVE_RF && slave->_useMastersSceneData)
816             {
817                 osg::Viewport* viewport = camera->getViewport();
818                 osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
819                 if (viewport) localCameraVPW *= viewport->computeWindowMatrix();
820 
821                 osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW );
822                 osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;
823                 //OSG_NOTICE<<"    pointer event new_coord.x()="<<new_coord.x()<<" new_coord.y()="<<new_coord.y()<<std::endl;
824                 event.addPointerData(new osgGA::PointerData(view_masterCamera, new_coord.x(), master_min_x, master_max_x,
825                                                                                new_coord.y(), master_min_y, master_max_y));
826             }
827             else if (!slave->_useMastersSceneData)
828             {
829                 // Are their any RTT Camera's that this Camera depends upon for textures?
830 
831                 osg::ref_ptr<osgUtil::LineSegmentIntersector> ray = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x,y);
832                 osgUtil::IntersectionVisitor iv(ray.get());
833                 camera->accept(iv);
834                 if (ray->containsIntersections())
835                 {
836                     osg::Vec3 tc;
837                     osg::Texture* texture = ray->getFirstIntersection().getTextureLookUp(tc);
838                     if (texture)
839                     {
840                         // look up Texture in RTT Camera's.
841                         for(unsigned int i=0; i<view->getNumSlaves();++i)
842                         {
843                             osg::Camera* slave_camera = view->getSlave(i)._camera.get();
844                             if (slave_camera)
845                             {
846                                 osg::Camera::BufferAttachmentMap::const_iterator ba_itr = slave_camera->getBufferAttachmentMap().find(osg::Camera::COLOR_BUFFER);
847                                 if (ba_itr != slave_camera->getBufferAttachmentMap().end())
848                                 {
849                                     if (ba_itr->second._texture == texture)
850                                     {
851                                         osg::TextureRectangle* tr = dynamic_cast<osg::TextureRectangle*>(ba_itr->second._texture.get());
852                                         osg::TextureCubeMap* tcm = dynamic_cast<osg::TextureCubeMap*>(ba_itr->second._texture.get());
853                                         if (tr)
854                                         {
855                                             event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, static_cast<float>(tr->getTextureWidth()),
856                                                                                                            tc.y(), 0.0f, static_cast<float>(tr->getTextureHeight())));
857                                         }
858                                         else if (tcm)
859                                         {
860                                             OSG_INFO<<"  Slave has matched texture cubemap"<<ba_itr->second._texture.get()<<", "<<ba_itr->second._face<<std::endl;
861                                         }
862                                         else
863                                         {
864                                             event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, 1.0f,
865                                                                                                            tc.y(), 0.0f, 1.0f));
866                                         }
867                                     }
868                                 }
869                             }
870                         }
871                     }
872                 }
873             }
874         }
875     }
876 }
877 
generatePointerData(osgGA::GUIEventAdapter & event)878 void CompositeViewer::generatePointerData(osgGA::GUIEventAdapter& event)
879 {
880     osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
881     if (!gw) return;
882 
883     float x = event.getX();
884     float y = event.getY();
885 
886     bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
887     if (invert_y && gw->getTraits()) y = gw->getTraits()->height - 1 - y;
888 
889     event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width - 1,
890                                                     y, 0, gw->getTraits()->height - 1));
891 
892     event.setMouseYOrientationAndUpdateCoords(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
893 
894     typedef std::vector<osg::Camera*> CameraVector;
895     CameraVector activeCameras;
896 
897     osg::GraphicsContext::Cameras& cameras = gw->getCameras();
898     for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
899         citr != cameras.end();
900         ++citr)
901     {
902         osg::Camera* camera = *citr;
903         if (camera->getAllowEventFocus() &&
904             camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
905         {
906             osg::Viewport* viewport = camera->getViewport();
907             if (viewport &&
908                 x >= viewport->x() && y >= viewport->y() &&
909                 x < (viewport->x()+viewport->width()) && y < (viewport->y()+viewport->height()) )
910             {
911                 activeCameras.push_back(camera);
912             }
913         }
914     }
915 
916     std::sort(activeCameras.begin(), activeCameras.end(), osg::CameraRenderOrderSortOp());
917 
918     osg::Camera* camera = activeCameras.empty() ? 0 : activeCameras.back();
919 
920     if (camera)
921     {
922         osg::Viewport* viewport = camera->getViewport();
923 
924         event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/(viewport->width() - 1)*2.0f-1.0f, -1.0, 1.0,
925                                                             (y-viewport->y())/(viewport->height() - 1)*2.0f-1.0f, -1.0, 1.0));
926 
927         osgViewer::View* view = dynamic_cast<osgViewer::View*>(camera->getView());
928         osg::Camera* view_masterCamera = view ? view->getCamera() : 0;
929 
930         // if camera isn't the master it must be a slave and could need reprojecting.
931         if (view && camera!=view_masterCamera)
932         {
933             generateSlavePointerData(camera, event);
934         }
935     }
936 }
937 
reprojectPointerData(osgGA::GUIEventAdapter & source_event,osgGA::GUIEventAdapter & dest_event)938 void CompositeViewer::reprojectPointerData(osgGA::GUIEventAdapter& source_event, osgGA::GUIEventAdapter& dest_event)
939 {
940     osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(dest_event.getGraphicsContext());
941     if (!gw) return;
942 
943     float x = dest_event.getX();
944     float y = dest_event.getY();
945 
946     bool invert_y = dest_event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
947     if (invert_y && gw->getTraits()) y = gw->getTraits()->height - 1 - y;
948 
949     dest_event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width - 1,
950                                                          y, 0, gw->getTraits()->height - 1));
951 
952     dest_event.setMouseYOrientationAndUpdateCoords(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
953 
954     osg::Object* object = (source_event.getNumPointerData()>=2) ? source_event.getPointerData(1)->object.get() : 0;
955     osg::Camera* camera = object ? object->asCamera() : 0;
956     osg::Viewport* viewport = camera ? camera->getViewport() : 0;
957 
958     if (!viewport) return;
959 
960     dest_event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/(viewport->width() - 1)*2.0f-1.0f, -1.0, 1.0,
961                                                              (y-viewport->y())/(viewport->height() - 1)*2.0f-1.0f, -1.0, 1.0));
962 
963     osgViewer::View* view = dynamic_cast<osgViewer::View*>(camera->getView());
964     osg::Camera* view_masterCamera = view ? view->getCamera() : 0;
965 
966     // if camera isn't the master it must be a slave and could need reprojecting.
967     if (view && camera!=view_masterCamera)
968     {
969         generateSlavePointerData(camera, dest_event);
970     }
971 }
972 
973 struct SortEvents
974 {
operator ()SortEvents975     bool operator() (const osg::ref_ptr<osgGA::Event>& lhs,const osg::ref_ptr<osgGA::Event>& rhs) const
976     {
977         return lhs->getTime() < rhs->getTime();
978     }
979 };
980 
eventTraversal()981 void CompositeViewer::eventTraversal()
982 {
983     if (_done) return;
984 
985     if (_views.empty()) return;
986 
987     double cutOffTime = _frameStamp->getReferenceTime();
988 
989     double beginEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
990 
991     // need to copy events from the GraphicsWindow's into local EventQueue for each view;
992     typedef std::map<osgViewer::View*, osgGA::EventQueue::Events> ViewEventsMap;
993     ViewEventsMap viewEventsMap;
994 
995     Contexts contexts;
996     getContexts(contexts);
997 
998     // set done if there are no windows
999     checkWindowStatus(contexts);
1000     if (_done) return;
1001 
1002     osgGA::EventQueue::Events all_events;
1003 
1004     for(Contexts::iterator citr = contexts.begin();
1005         citr != contexts.end();
1006         ++citr)
1007     {
1008         osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
1009         if (gw)
1010         {
1011             gw->checkEvents();
1012 
1013             osgGA::EventQueue::Events gw_events;
1014             gw->getEventQueue()->takeEvents(gw_events, cutOffTime);
1015 
1016             for(osgGA::EventQueue::Events::iterator itr = gw_events.begin();
1017                 itr != gw_events.end();
1018                 ++itr)
1019             {
1020                 osgGA::GUIEventAdapter* ea = (*itr)->asGUIEventAdapter();
1021                 if (ea) ea->setGraphicsContext(gw);
1022             }
1023 
1024             all_events.insert(all_events.end(), gw_events.begin(), gw_events.end());
1025         }
1026     }
1027 
1028     // sort all the events in time order so we can make sure we pass them all on in the correct order.
1029     all_events.sort(SortEvents());
1030 
1031     // pass on pointer data onto non mouse events to keep the position data usable by all recipients of all events.
1032     for(osgGA::EventQueue::Events::iterator itr = all_events.begin();
1033         itr != all_events.end();
1034         ++itr)
1035     {
1036         osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
1037         if (!event) continue;
1038 
1039         enum EventClassification
1040         {
1041             EVENT_FOR_VIEW_ASSOCIATED_WITH_FOCUS,
1042             EVENT_FOR_VIEWS_ASSOCIATED_WITH_WINDOW,
1043             EVENT_FOR_ALL_VIEWS
1044         };
1045 
1046         EventClassification classification = EVENT_FOR_ALL_VIEWS;
1047 
1048         switch(event->getEventType())
1049         {
1050             case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
1051             case(osgGA::GUIEventAdapter::RESIZE):
1052                 classification = EVENT_FOR_VIEWS_ASSOCIATED_WITH_WINDOW;
1053                 break;
1054 
1055             case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
1056             case(osgGA::GUIEventAdapter::USER):
1057                 classification = EVENT_FOR_ALL_VIEWS;
1058                 break;
1059 
1060             case(osgGA::GUIEventAdapter::KEYDOWN):
1061             case(osgGA::GUIEventAdapter::KEYUP):
1062                 classification = EVENT_FOR_VIEW_ASSOCIATED_WITH_FOCUS;
1063                 if (_previousEvent.valid()) event->copyPointerDataFrom(*_previousEvent);
1064                 break;
1065 
1066             case(osgGA::GUIEventAdapter::PUSH):
1067             case(osgGA::GUIEventAdapter::RELEASE):
1068             case(osgGA::GUIEventAdapter::DOUBLECLICK):
1069             case(osgGA::GUIEventAdapter::MOVE):
1070             case(osgGA::GUIEventAdapter::DRAG):
1071             case(osgGA::GUIEventAdapter::SCROLL):
1072             {
1073                 if ((event->getEventType()!=osgGA::GUIEventAdapter::DRAG && event->getEventType()!=osgGA::GUIEventAdapter::RELEASE) ||
1074                     !_previousEvent ||
1075                     _previousEvent->getGraphicsContext()!=event->getGraphicsContext() ||
1076                     _previousEvent->getNumPointerData()<2)
1077                 {
1078                     generatePointerData(*event);
1079                 }
1080                 else
1081                 {
1082                     reprojectPointerData(*_previousEvent, *event);
1083                 }
1084 
1085                 _previousEvent = event;
1086 
1087                 classification = EVENT_FOR_VIEW_ASSOCIATED_WITH_FOCUS;
1088                 break;
1089             }
1090 
1091             default:
1092                 if (_previousEvent.valid()) event->copyPointerDataFrom(*_previousEvent);
1093                 break;
1094         }
1095 
1096         osgGA::PointerData* pd = event->getNumPointerData()>0 ? event->getPointerData(event->getNumPointerData()-1) : 0;
1097         osg::Object* object = pd ? pd->object.get() : 0;
1098         osg::Camera* camera = object ? object->asCamera() : 0;
1099         osgViewer::View* view = camera ? dynamic_cast<osgViewer::View*>(camera->getView()) : 0;
1100 
1101         if (!view)
1102         {
1103             if (_viewWithFocus.valid())
1104             {
1105                 OSG_INFO<<"Falling back to using _viewWithFocus"<<std::endl;
1106                 view = _viewWithFocus.get();
1107             }
1108             else if (!_views.empty())
1109             {
1110                 OSG_INFO<<"Falling back to using first view as one with focus"<<std::endl;
1111                 view = _views[0].get();
1112             }
1113         }
1114 
1115         // reassign view with focus
1116         if (_viewWithFocus != view)  _viewWithFocus = view;
1117 
1118         switch(classification)
1119         {
1120             case(EVENT_FOR_VIEW_ASSOCIATED_WITH_FOCUS):
1121             {
1122                 if (view)
1123                 {
1124                     OSG_INFO<<"Sending EVENT_FOR_VIEW_ASSOCIATED_WITH_FOCUS event "<<event<<" to view "<<view<<std::endl;
1125 
1126                     viewEventsMap[view].push_back( event );
1127 
1128                     osgGA::GUIEventAdapter* eventState = view->getEventQueue()->getCurrentEventState();
1129                     eventState->copyPointerDataFrom(*event);
1130                 }
1131                 break;
1132             }
1133             case(EVENT_FOR_VIEWS_ASSOCIATED_WITH_WINDOW):
1134             {
1135                 typedef std::set<View*> ViewSet;
1136                 ViewSet views;
1137                 osg::GraphicsContext* gc = event->getGraphicsContext();
1138                 if (gc)
1139                 {
1140                     osg::GraphicsContext::Cameras& cameras = gc->getCameras();
1141                     for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
1142                         citr != cameras.end();
1143                         ++citr)
1144                     {
1145                         osgViewer::View* camera_view = dynamic_cast<osgViewer::View*>((*citr)->getView());
1146                         if (camera_view) views.insert(camera_view);
1147                     }
1148                 }
1149                 for(ViewSet::iterator vitr=views.begin();
1150                     vitr!=views.end();
1151                     ++vitr)
1152                 {
1153                     OSG_INFO<<"Sending EVENT_FOR_VIEWS_ASSOCIATED_WITH_WINDOW event "<<event<<" to view "<<*vitr<<std::endl;
1154                     viewEventsMap[*vitr].push_back( event );
1155                 }
1156                 break;
1157             }
1158             case(EVENT_FOR_ALL_VIEWS):
1159             {
1160                 for(RefViews::iterator vitr=_views.begin();
1161                     vitr!=_views.end();
1162                     ++vitr)
1163                 {
1164                     OSG_INFO<<"Sending EVENT_FOR_ALL_VIEWS event "<<event<<" to view "<<vitr->get()<<std::endl;
1165                     viewEventsMap[vitr->get()].push_back( event );
1166                 }
1167                 break;
1168             }
1169         }
1170 
1171         _previousEvent = event;
1172     }
1173 
1174     // handle any close windows
1175     for(osgGA::EventQueue::Events::iterator itr = all_events.begin();
1176         itr != all_events.end();
1177         ++itr)
1178     {
1179         osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
1180         if (!event) continue;
1181 
1182         switch(event->getEventType())
1183         {
1184             case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
1185             {
1186                 bool wasThreading = areThreadsRunning();
1187                 if (wasThreading) stopThreading();
1188 
1189                 if (event->getGraphicsContext())
1190                 {
1191                     event->getGraphicsContext()->close();
1192                 }
1193 
1194                 if (wasThreading) startThreading();
1195 
1196                 break;
1197             }
1198             default:
1199                 break;
1200         }
1201     }
1202 
1203 
1204     for(RefViews::iterator vitr = _views.begin();
1205         vitr != _views.end();
1206         ++vitr)
1207     {
1208         View* view = vitr->get();
1209 
1210         // get events from user Devices attached to Viewer.
1211         for(osgViewer::View::Devices::iterator eitr = view->getDevices().begin();
1212             eitr != view->getDevices().end();
1213             ++eitr)
1214         {
1215             osgGA::Device* es = eitr->get();
1216             if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS)
1217                 es->checkEvents();
1218 
1219             // open question, will we need to reproject mouse coordinates into current view's coordinate frame as is down for GraphicsWindow provided events?
1220             // for now assume now and just get the events directly without any reprojection.
1221             es->getEventQueue()->takeEvents(viewEventsMap[view], cutOffTime);
1222         }
1223 
1224         // create a frame event for the new frame.
1225         {
1226             osg::ref_ptr<osgGA::GUIEventAdapter> event = view->getEventQueue()->frame( getFrameStamp()->getReferenceTime() );
1227 
1228             if (!_previousEvent || _previousEvent->getNumPointerData()<2)
1229             {
1230                 generatePointerData(*event);
1231             }
1232             else
1233             {
1234                 reprojectPointerData(*_previousEvent, *event);
1235             }
1236         }
1237 
1238 
1239         view->getEventQueue()->takeEvents(viewEventsMap[view], cutOffTime);
1240     }
1241 
1242     if ((_keyEventSetsDone!=0) || _quitEventSetsDone)
1243     {
1244         for(ViewEventsMap::iterator veitr = viewEventsMap.begin();
1245             veitr != viewEventsMap.end();
1246             ++veitr)
1247         {
1248             for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin();
1249                 itr != veitr->second.end();
1250                 ++itr)
1251             {
1252                 osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
1253                 if (!event) continue;
1254 
1255                 // ignore event if it's already been handled.
1256                 if (event->getHandled()) continue;
1257 
1258                 switch(event->getEventType())
1259                 {
1260                     case(osgGA::GUIEventAdapter::KEYUP):
1261                         if (_keyEventSetsDone && event->getKey()==_keyEventSetsDone) _done = true;
1262                         break;
1263 
1264                     case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
1265                         if (_quitEventSetsDone) _done = true;
1266                         break;
1267 
1268                     default:
1269                         break;
1270                 }
1271             }
1272         }
1273     }
1274 
1275     if (_done) return;
1276 
1277     if (_eventVisitor.valid())
1278     {
1279         _eventVisitor->setFrameStamp(getFrameStamp());
1280         _eventVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());
1281 
1282         for(ViewEventsMap::iterator veitr = viewEventsMap.begin();
1283             veitr != viewEventsMap.end();
1284             ++veitr)
1285         {
1286             View* view = veitr->first;
1287             _eventVisitor->setActionAdapter(view);
1288 
1289             if (view && view->getSceneData())
1290             {
1291                 for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin();
1292                     itr != veitr->second.end();
1293                     ++itr)
1294                 {
1295                     osgGA::Event* event = itr->get();
1296 
1297                     _eventVisitor->reset();
1298                     _eventVisitor->addEvent( event );
1299 
1300                     view->getSceneData()->accept(*_eventVisitor);
1301 
1302                     // Do EventTraversal for slaves with their own subgraph
1303                     for(unsigned int i=0; i<view->getNumSlaves(); ++i)
1304                     {
1305                         osg::View::Slave& slave = view->getSlave(i);
1306                         osg::Camera* camera = slave._camera.get();
1307                         if(camera && !slave._useMastersSceneData)
1308                         {
1309                             camera->accept(*_eventVisitor);
1310                         }
1311                     }
1312 
1313                     // call any camera event callbacks, but only traverse that callback, don't traverse its subgraph
1314                     // leave that to the scene update traversal.
1315                     osg::NodeVisitor::TraversalMode tm = _eventVisitor->getTraversalMode();
1316                     _eventVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
1317 
1318                     if (view->getCamera()) view->getCamera()->accept(*_eventVisitor);
1319 
1320                     for(unsigned int i=0; i<view->getNumSlaves(); ++i)
1321                     {
1322                         osg::View::Slave& slave = view->getSlave(i);
1323                         osg::Camera* camera = view->getSlave(i)._camera.get();
1324                         if (camera && slave._useMastersSceneData)
1325                         {
1326                             camera->accept(*_eventVisitor);
1327                         }
1328                     }
1329 
1330                     _eventVisitor->setTraversalMode(tm);
1331 
1332                 }
1333             }
1334         }
1335 
1336     }
1337 
1338     for(ViewEventsMap::iterator veitr = viewEventsMap.begin();
1339         veitr != viewEventsMap.end();
1340         ++veitr)
1341     {
1342         View* view = veitr->first;
1343         _eventVisitor->setActionAdapter(view);
1344 
1345         for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin();
1346             itr != veitr->second.end();
1347             ++itr)
1348         {
1349             osgGA::Event* event = itr->get();
1350             for(View::EventHandlers::iterator hitr = view->getEventHandlers().begin();
1351                 hitr != view->getEventHandlers().end();
1352                 ++hitr)
1353             {
1354                 (*hitr)->handle( event, view, _eventVisitor.get());
1355             }
1356         }
1357     }
1358 
1359     for(ViewEventsMap::iterator veitr = viewEventsMap.begin();
1360         veitr != viewEventsMap.end();
1361         ++veitr)
1362     {
1363         View* view = veitr->first;
1364         _eventVisitor->setActionAdapter(view);
1365 
1366         for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin();
1367             itr != veitr->second.end();
1368             ++itr)
1369         {
1370             osgGA::Event* event = itr->get();
1371             if (view->getCameraManipulator())
1372             {
1373                 view->getCameraManipulator()->handle( event, view, _eventVisitor.get());
1374             }
1375         }
1376     }
1377 
1378     if (getViewerStats() && getViewerStats()->collectStats("event"))
1379     {
1380         double endEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1381 
1382         // update current frames stats
1383         getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal begin time", beginEventTraversal);
1384         getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal end time", endEventTraversal);
1385         getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal time taken", endEventTraversal-beginEventTraversal);
1386     }
1387 }
1388 
updateTraversal()1389 void CompositeViewer::updateTraversal()
1390 {
1391     if (_done) return;
1392 
1393     double beginUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1394 
1395     _updateVisitor->reset();
1396     _updateVisitor->setFrameStamp(getFrameStamp());
1397     _updateVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());
1398 
1399     Scenes scenes;
1400     getScenes(scenes);
1401     for(Scenes::iterator sitr = scenes.begin();
1402         sitr != scenes.end();
1403         ++sitr)
1404     {
1405         Scene* scene = *sitr;
1406         scene->updateSceneGraph(*_updateVisitor);
1407     }
1408 
1409     // if we have a shared state manager prune any unused entries
1410     if (osgDB::Registry::instance()->getSharedStateManager())
1411         osgDB::Registry::instance()->getSharedStateManager()->prune();
1412 
1413     // update the Registry object cache.
1414     osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExternalReferences(*getFrameStamp());
1415     osgDB::Registry::instance()->removeExpiredObjectsInCache(*getFrameStamp());
1416 
1417 
1418     if (_incrementalCompileOperation.valid())
1419     {
1420         // merge subgraphs that have been compiled by the incremental compiler operation.
1421         _incrementalCompileOperation->mergeCompiledSubgraphs(getFrameStamp());
1422     }
1423 
1424     if (_updateOperations.valid())
1425     {
1426         _updateOperations->runOperations(this);
1427     }
1428 
1429     for(RefViews::iterator vitr = _views.begin();
1430         vitr != _views.end();
1431         ++vitr)
1432     {
1433         View* view = vitr->get();
1434 
1435         {
1436             // Do UpdateTraversal for slaves with their own subgraph
1437             for(unsigned int i=0; i<view->getNumSlaves(); ++i)
1438             {
1439                 osg::View::Slave& slave = view->getSlave(i);
1440                 osg::Camera* camera = slave._camera.get();
1441                 if(camera && !slave._useMastersSceneData)
1442                 {
1443                     camera->accept(*_updateVisitor);
1444                 }
1445             }
1446 
1447             // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
1448             // leave that to the scene update traversal.
1449             osg::NodeVisitor::TraversalMode tm = _updateVisitor->getTraversalMode();
1450             _updateVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
1451 
1452             if (view->getCamera()) view->getCamera()->accept(*_updateVisitor);
1453 
1454             for(unsigned int i=0; i<view->getNumSlaves(); ++i)
1455             {
1456                 osg::View::Slave& slave = view->getSlave(i);
1457                 osg::Camera* camera = slave._camera.get();
1458                 if (camera && slave._useMastersSceneData)
1459                 {
1460                     camera->accept(*_updateVisitor);
1461                 }
1462             }
1463 
1464             _updateVisitor->setTraversalMode(tm);
1465         }
1466 
1467 
1468         if (view->getCameraManipulator())
1469         {
1470             view->setFusionDistance( view->getCameraManipulator()->getFusionDistanceMode(),
1471                                     view->getCameraManipulator()->getFusionDistanceValue() );
1472 
1473             view->getCameraManipulator()->updateCamera(*(view->getCamera()));
1474 
1475         }
1476         view->updateSlaves();
1477 
1478     }
1479 
1480     if (getViewerStats() && getViewerStats()->collectStats("update"))
1481     {
1482         double endUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1483 
1484         // update current frames stats
1485         getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal begin time", beginUpdateTraversal);
1486         getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal end time", endUpdateTraversal);
1487         getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal time taken", endUpdateTraversal-beginUpdateTraversal);
1488     }
1489 
1490 }
1491 
elapsedTime()1492 double CompositeViewer::elapsedTime()
1493 {
1494     return osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1495 }
1496 
getUsage(osg::ApplicationUsage & usage) const1497 void CompositeViewer::getUsage(osg::ApplicationUsage& usage) const
1498 {
1499     for(RefViews::const_iterator vitr = _views.begin();
1500         vitr != _views.end();
1501         ++vitr)
1502     {
1503         const View* view = vitr->get();
1504         if (view->getCameraManipulator())
1505         {
1506             view->getCameraManipulator()->getUsage(usage);
1507         }
1508 
1509         for(View::EventHandlers::const_iterator hitr = view->_eventHandlers.begin();
1510             hitr != view->_eventHandlers.end();
1511             ++hitr)
1512         {
1513             (*hitr)->getUsage(usage);
1514         }
1515     }
1516 }
1517