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