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 <stdio.h>
15 #include <stdlib.h>
16
17 #include <osg/DeleteHandler>
18 #include <osg/io_utils>
19 #include <osg/TextureRectangle>
20 #include <osg/TextureCubeMap>
21
22 #include <osgUtil/RayIntersector>
23
24 #include <osgDB/Registry>
25 #include <osgDB/ReadFile>
26 #include <osgDB/WriteFile>
27 #include <osgGA/TrackballManipulator>
28
29 #include <osgViewer/Viewer>
30 #include <osgViewer/Renderer>
31 #include <osgViewer/CompositeViewer>
32
33 #include <osgViewer/config/SphericalDisplay>
34 #include <osgViewer/config/PanoramicSphericalDisplay>
35 #include <osgViewer/config/WoWVxDisplay>
36
37 #include <sstream>
38 #include <string.h>
39
40 using namespace osgViewer;
41
42
Viewer()43 Viewer::Viewer()
44 {
45 _viewerBase = this;
46
47 constructorInit();
48 }
49
Viewer(osg::ArgumentParser & arguments)50 Viewer::Viewer(osg::ArgumentParser& arguments)
51 {
52 _viewerBase = this;
53
54 constructorInit();
55
56 // Add help for command-line options read here
57 arguments.getApplicationUsage()->addCommandLineOption("--SingleThreaded","Select SingleThreaded threading model for viewer.");
58 arguments.getApplicationUsage()->addCommandLineOption("--CullDrawThreadPerContext","Select CullDrawThreadPerContext threading model for viewer.");
59 arguments.getApplicationUsage()->addCommandLineOption("--DrawThreadPerContext","Select DrawThreadPerContext threading model for viewer.");
60 arguments.getApplicationUsage()->addCommandLineOption("--CullThreadPerCameraDrawThreadPerContext","Select CullThreadPerCameraDrawThreadPerContext threading model for viewer.");
61 arguments.getApplicationUsage()->addCommandLineOption("--clear-color <color>","Set the background color of the viewer in the form \"r,g,b[,a]\".");
62 arguments.getApplicationUsage()->addCommandLineOption("--screen <num>","Set the screen to use when multiple screens are present.");
63 arguments.getApplicationUsage()->addCommandLineOption("--window <x y w h>","Set the position (x,y) and size (w,h) of the viewer window.");
64
65 arguments.getApplicationUsage()->addCommandLineOption("--run-on-demand","Set the run methods frame rate management to only rendering frames when required.");
66 arguments.getApplicationUsage()->addCommandLineOption("--run-continuous","Set the run methods frame rate management to rendering frames continuously.");
67 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.");
68 arguments.getApplicationUsage()->addCommandLineOption("--enable-object-cache","Enable caching of objects, images, etc.");
69
70 // FIXME: Uncomment these lines when the options have been documented properly
71 //arguments.getApplicationUsage()->addCommandLineOption("--3d-sd","");
72 //arguments.getApplicationUsage()->addCommandLineOption("--panoramic-sd","");
73 //arguments.getApplicationUsage()->addCommandLineOption("--radius","");
74 //arguments.getApplicationUsage()->addCommandLineOption("--collar","");
75 //arguments.getApplicationUsage()->addCommandLineOption("--im","");
76
77 if (arguments.read("--ico"))
78 {
79 setIncrementalCompileOperation(new osgUtil::IncrementalCompileOperation());
80 }
81
82 std::string filename;
83 bool readConfig = false;
84 while (arguments.read("-c",filename))
85 {
86 readConfig = readConfiguration(filename) || readConfig;
87 }
88
89 // Enable caching?
90 while (arguments.read("--enable-object-cache"))
91 {
92 if (osgDB::Registry::instance()->getOptions()==0) osgDB::Registry::instance()->setOptions(new osgDB::Options());
93 osgDB::Registry::instance()->getOptions()->setObjectCacheHint(osgDB::Options::CACHE_ALL);
94 }
95
96 while (arguments.read("--SingleThreaded")) setThreadingModel(SingleThreaded);
97 while (arguments.read("--CullDrawThreadPerContext")) setThreadingModel(CullDrawThreadPerContext);
98 while (arguments.read("--DrawThreadPerContext")) setThreadingModel(DrawThreadPerContext);
99 while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) setThreadingModel(CullThreadPerCameraDrawThreadPerContext);
100
101 osg::DisplaySettings::instance()->readCommandLine(arguments);
102 osgDB::readCommandLine(arguments);
103
104 std::string colorStr;
105 while (arguments.read("--clear-color",colorStr))
106 {
107 float r, g, b;
108 float a = 1.0f;
109 int cnt = sscanf( colorStr.c_str(), "%f,%f,%f,%f", &r, &g, &b, &a );
110 if( cnt==3 || cnt==4 )
111 {
112 getCamera()->setClearColor( osg::Vec4(r,g,b,a) );
113 }
114 else
115 {
116 OSG_WARN<<"Invalid clear color \""<<colorStr<<"\""<<std::endl;
117 }
118 }
119
120
121 while(arguments.read("--run-on-demand")) { setRunFrameScheme(ON_DEMAND); }
122 while(arguments.read("--run-continuous")) { setRunFrameScheme(CONTINUOUS); }
123
124 double runMaxFrameRate;
125 while(arguments.read("--run-max-frame-rate", runMaxFrameRate)) { setRunMaxFrameRate(runMaxFrameRate); }
126
127
128 int screenNum = -1;
129 while (arguments.read("--screen",screenNum)) {}
130
131 int x = -1, y = -1, width = -1, height = -1;
132 while (arguments.read("--window",x,y,width,height)) {}
133
134 bool ss3d = false;
135 bool wowvx20 = false;
136 bool wowvx42 = false;
137 if ((wowvx20=arguments.read("--wowvx-20")) || (wowvx42=arguments.read("--wowvx-42")) || arguments.read("--wowvx"))
138 {
139 osg::ref_ptr<WoWVxDisplay> wow = new WoWVxDisplay;
140
141 if (screenNum>=0) wow->setScreenNum(screenNum);
142 if (wowvx20) wow->WoWVx20();
143 if (wowvx42) wow->WoWVx42();
144
145 unsigned int c;
146 float v;
147 while (arguments.read("--wow-content",c)) { wow->setContent(c); }
148 while (arguments.read("--wow-factor",c)) { wow->setFactor(c); }
149 while (arguments.read("--wow-offset",c)) { wow->setOffset(c); }
150 while (arguments.read("--wow-zd",v)) { wow->setDisparityZD(v); }
151 while (arguments.read("--wow-vz",v)) { wow->setDisparityVZ(v); }
152 while (arguments.read("--wow-M",v)) { wow->setDisparityM(v); }
153 while (arguments.read("--wow-C",v)) { wow->setDisparityC(v); }
154
155 apply(wow.get());
156 }
157 else if ((ss3d=arguments.read("--3d-sd")) || arguments.read("--panoramic-sd"))
158 {
159 double radius = 1.0;
160 while (arguments.read("--radius",radius)) {}
161
162 double collar = 0.45;
163 while (arguments.read("--collar",collar)) {}
164
165 std::string intensityMapFilename;
166 while (arguments.read("--im",intensityMapFilename)) {}
167
168 osg::ref_ptr<osg::Image> intensityMap = intensityMapFilename.empty() ? 0 : osgDB::readRefImageFile(intensityMapFilename);
169
170 if (screenNum<0) screenNum = 0;
171
172 if (ss3d)
173 {
174 setThreadingModel(SingleThreaded);
175 setUpViewFor3DSphericalDisplay(radius, collar, screenNum, intensityMap.get());
176 }
177 else
178 {
179 setThreadingModel(SingleThreaded);
180 setUpViewForPanoramicSphericalDisplay(radius, collar, screenNum, intensityMap.get());
181 }
182 }
183 else if (width>0 && height>0)
184 {
185 if (screenNum>=0) setUpViewInWindow(x, y, width, height, screenNum);
186 else setUpViewInWindow(x,y,width,height);
187
188 }
189 else if (screenNum>=0)
190 {
191 setUpViewOnSingleScreen(screenNum);
192 }
193
194 }
195
Viewer(const osgViewer::Viewer & viewer,const osg::CopyOp & copyop)196 Viewer::Viewer(const osgViewer::Viewer& viewer, const osg::CopyOp& copyop):
197 osg::Object(true),
198 ViewerBase(viewer),
199 View(viewer,copyop)
200 {
201 _viewerBase = this;
202 }
203
constructorInit()204 void Viewer::constructorInit()
205 {
206 _eventVisitor = new osgGA::EventVisitor;
207 _eventVisitor->setActionAdapter(this);
208 _eventVisitor->setFrameStamp(_frameStamp.get());
209
210 _updateVisitor = new osgUtil::UpdateVisitor;
211 _updateVisitor->setFrameStamp(_frameStamp.get());
212
213 setViewerStats(new osg::Stats("Viewer"));
214 }
215
~Viewer()216 Viewer::~Viewer()
217 {
218 //OSG_NOTICE<<"Viewer::~Viewer()"<<std::endl;
219
220 Threads threads;
221 getAllThreads(threads);
222
223 OSG_INFO<<"Viewer::~Viewer():: start destructor getThreads = "<<threads.size()<<std::endl;
224
225 stopThreading();
226
227 if (_scene.valid() && _scene->getDatabasePager())
228 {
229 _scene->getDatabasePager()->cancel();
230 _scene->setDatabasePager(0);
231 }
232
233 Contexts contexts;
234 getContexts(contexts);
235
236 // clear out all the previously assigned operations
237 for(Contexts::iterator citr = contexts.begin();
238 citr != contexts.end();
239 ++citr)
240 {
241 (*citr)->close();
242 }
243
244 //OSG_NOTICE<<"finish Viewer::~Viewer()"<<std::endl;
245
246 getAllThreads(threads);
247
248 OSG_INFO<<"Viewer::~Viewer() end destructor getThreads = "<<threads.size()<<std::endl;
249 }
250
take(osg::View & rhs)251 void Viewer::take(osg::View& rhs)
252 {
253 osgViewer::View::take(rhs);
254
255 #if 1
256 osgViewer::Viewer* rhs_viewer = dynamic_cast<osgViewer::Viewer*>(&rhs);
257 if (rhs_viewer)
258 {
259 // variables left to take.
260 _done = rhs_viewer->_done;
261 _keyEventSetsDone = rhs_viewer->_keyEventSetsDone;
262 _quitEventSetsDone = rhs_viewer->_quitEventSetsDone;
263 _threadingModel = rhs_viewer->_threadingModel;
264 _threadsRunning = rhs_viewer->_threadsRunning;
265 _endBarrierPosition = rhs_viewer->_endBarrierPosition;
266 _startRenderingBarrier = rhs_viewer->_startRenderingBarrier;
267 _endRenderingDispatchBarrier = rhs_viewer->_endRenderingDispatchBarrier;
268 _endDynamicDrawBlock = rhs_viewer->_endDynamicDrawBlock;
269
270 _eventVisitor = rhs_viewer->_eventVisitor;
271 _eventVisitor->setActionAdapter(this);
272 _eventVisitor->setFrameStamp(_frameStamp.get());
273
274 _updateOperations = rhs_viewer->_updateOperations;
275 _updateVisitor = rhs_viewer->_updateVisitor;
276
277 _realizeOperation = rhs_viewer->_realizeOperation;
278 _currentContext = rhs_viewer->_currentContext;
279
280
281 // objects to clear
282 rhs_viewer->_done = true;
283 rhs_viewer->_startRenderingBarrier = 0;
284 rhs_viewer->_endRenderingDispatchBarrier = 0;
285 rhs_viewer->_endDynamicDrawBlock = 0;
286 rhs_viewer->_eventVisitor = 0;
287 rhs_viewer->_updateOperations = 0;
288 rhs_viewer->_updateVisitor = 0;
289 rhs_viewer->_realizeOperation = 0;
290 rhs_viewer->_currentContext = 0;
291
292 }
293 #endif
294 }
295
readConfiguration(const std::string & filename)296 bool Viewer::readConfiguration(const std::string& filename)
297 {
298 OSG_INFO<<"Viewer::readConfiguration("<<filename<<")"<<std::endl;
299
300 osg::ref_ptr<osg::Object> object = osgDB::readRefObjectFile(filename);
301 if (!object)
302 {
303 //OSG_NOTICE<<"Error: Unable to load configuration file \""<<filename<<"\""<<std::endl;
304 return false;
305 }
306
307 ViewConfig* config = dynamic_cast<ViewConfig*>(object.get());
308 if (config)
309 {
310 OSG_INFO<<"Using osgViewer::Config : "<<config->className()<<std::endl;
311
312 config->configure(*this);
313
314 //osgDB::writeObjectFile(*config,"test.osgt");
315
316 return true;
317 }
318
319
320 CompositeViewer* compositeViewer = dynamic_cast<CompositeViewer*>(object.get());
321 if (compositeViewer)
322 {
323 OSG_NOTICE<<"Error: Config file \""<<filename<<"\" containing CompositeViewer cannot be loaded by Viewer."<<std::endl;
324 return false;
325 }
326
327 View* view = dynamic_cast<osgViewer::View*>(object.get());
328 if (view)
329 {
330 take(*view);
331
332 return true;
333 }
334 else
335 {
336 OSG_NOTICE<<"Error: Config file \""<<filename<<"\" does not contain a valid Viewer configuration."<<std::endl;
337 return false;
338 }
339 }
340
isRealized() const341 bool Viewer::isRealized() const
342 {
343 Contexts contexts;
344 const_cast<Viewer*>(this)->getContexts(contexts);
345
346 unsigned int numRealizedWindows = 0;
347
348 // clear out all the previously assigned operations
349 for(Contexts::iterator citr = contexts.begin();
350 citr != contexts.end();
351 ++citr)
352 {
353 if ((*citr)->isRealized()) ++numRealizedWindows;
354 }
355
356 return numRealizedWindows > 0;
357 }
358
checkNeedToDoFrame()359 bool Viewer::checkNeedToDoFrame()
360 {
361 // check if any event handler has prompted a redraw
362 if (_requestRedraw) return true;
363 if (_requestContinousUpdate) return true;
364
365 // check if the database pager needs to update the scene
366 if (getDatabasePager()->requiresUpdateSceneGraph() || getDatabasePager()->getRequestsInProgress()) return true;
367
368 // check if there are camera update callbacks
369 if (_camera->getUpdateCallback()) return true;
370
371 // check if there are node update callbacks
372 if (getSceneData() != 0)
373 {
374 if (getSceneData()->getUpdateCallback() || (getSceneData()->getNumChildrenRequiringUpdateTraversal()>0) ) return true;
375 }
376
377 // check if events are available and need processing
378 if (checkEvents()) return true;
379
380 // and check again if any event handler has prompted a redraw
381 if (_requestRedraw) return true;
382 if (_requestContinousUpdate) return true;
383
384 return false;
385 }
386
checkEvents()387 bool Viewer::checkEvents()
388 {
389 // check events from any attached sources
390 for(Devices::iterator eitr = _eventSources.begin();
391 eitr != _eventSources.end();
392 ++eitr)
393 {
394 osgGA::Device* es = eitr->get();
395 if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS)
396 {
397 if (es->checkEvents()) return true;
398 }
399
400 }
401
402 // get events from all windows attached to Viewer.
403 Windows windows;
404 getWindows(windows);
405 for(Windows::iterator witr = windows.begin();
406 witr != windows.end();
407 ++witr)
408 {
409 if ((*witr)->checkEvents()) return true;
410 }
411
412 return false;
413 }
414
run()415 int Viewer::run()
416 {
417 if (!getCameraManipulator() && getCamera()->getAllowEventFocus())
418 {
419 setCameraManipulator(new osgGA::TrackballManipulator());
420 }
421
422 setReleaseContextAtEndOfFrameHint(false);
423
424 return ViewerBase::run();
425 }
426
setStartTick(osg::Timer_t tick)427 void Viewer::setStartTick(osg::Timer_t tick)
428 {
429 View::setStartTick(tick);
430
431 Contexts contexts;
432 getContexts(contexts,false);
433
434 getEventQueue()->setStartTick(_startTick);
435 for(Contexts::iterator citr = contexts.begin();
436 citr != contexts.end();
437 ++citr)
438 {
439 osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
440 if (gw)
441 {
442 gw->getEventQueue()->setStartTick(_startTick);
443 }
444 }
445 }
446
setReferenceTime(double time)447 void Viewer::setReferenceTime(double time)
448 {
449 osg::Timer_t tick = osg::Timer::instance()->tick();
450 double currentTime = osg::Timer::instance()->delta_s(_startTick, tick);
451 double delta_ticks = (time-currentTime)/(osg::Timer::instance()->getSecondsPerTick());
452 if (delta_ticks>=0) tick += osg::Timer_t(delta_ticks);
453 else tick -= osg::Timer_t(-delta_ticks);
454
455 // assign the new start tick
456 setStartTick(tick);
457 }
458
459
setSceneData(osg::Node * node)460 void Viewer::setSceneData(osg::Node* node)
461 {
462 setReferenceTime(0.0);
463
464 View::setSceneData(node);
465 }
466
setUpViewerAsEmbeddedInWindow(int x,int y,int width,int height)467 GraphicsWindowEmbedded* Viewer::setUpViewerAsEmbeddedInWindow(int x, int y, int width, int height)
468 {
469 setThreadingModel(SingleThreaded);
470 osgViewer::GraphicsWindowEmbedded* gw = new osgViewer::GraphicsWindowEmbedded(x,y,width,height);
471 getCamera()->setViewport(new osg::Viewport(0,0,width,height));
472 getCamera()->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(width)/static_cast<double>(height), 1.0f, 10000.0f);
473 getCamera()->setGraphicsContext(gw);
474 return gw;
475 }
476
realize()477 void Viewer::realize()
478 {
479 //OSG_INFO<<"Viewer::realize()"<<std::endl;
480
481 Contexts contexts;
482 getContexts(contexts);
483
484 if (contexts.empty())
485 {
486 OSG_INFO<<"Viewer::realize() - No valid contexts found, setting up view across all screens."<<std::endl;
487
488 // no windows are already set up so set up a default view
489
490 const char* ptr = 0;
491 if ((ptr = getenv("OSG_CONFIG_FILE")) != 0)
492 {
493 readConfiguration(ptr);
494 }
495 else
496 {
497 int screenNum = -1;
498 if ((ptr = getenv("OSG_SCREEN")) != 0)
499 {
500 if (strlen(ptr)!=0) screenNum = atoi(ptr);
501 else screenNum = -1;
502 }
503
504 int x = -1, y = -1, width = -1, height = -1;
505 if ((ptr = getenv("OSG_WINDOW")) != 0)
506 {
507 std::istringstream iss(ptr);
508 iss >> x >> y >> width >> height;
509 }
510
511 if (width>0 && height>0)
512 {
513 if (screenNum>=0) setUpViewInWindow(x, y, width, height, screenNum);
514 else setUpViewInWindow(x,y,width,height);
515 }
516 else if (screenNum>=0)
517 {
518 setUpViewOnSingleScreen(screenNum);
519 }
520 else
521 {
522 setUpViewAcrossAllScreens();
523 }
524 }
525
526 getContexts(contexts);
527 }
528
529 if (contexts.empty())
530 {
531 OSG_NOTICE<<"Viewer::realize() - failed to set up any windows"<<std::endl;
532 _done = true;
533 return;
534 }
535
536 // get the display settings that will be active for this viewer
537 osg::DisplaySettings* ds = _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance().get();
538 osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
539
540 // pass on the display settings to the WindowSystemInterface.
541 if (wsi && wsi->getDisplaySettings()==0) wsi->setDisplaySettings(ds);
542
543 unsigned int maxTexturePoolSize = ds->getMaxTexturePoolSize();
544 unsigned int maxBufferObjectPoolSize = ds->getMaxBufferObjectPoolSize();
545
546 for(Contexts::iterator citr = contexts.begin();
547 citr != contexts.end();
548 ++citr)
549 {
550 osg::GraphicsContext* gc = *citr;
551
552 if (ds->getSyncSwapBuffers()) gc->setSwapCallback(new osg::SyncSwapBuffersCallback);
553
554 // set the pool sizes, 0 the default will result in no GL object pools.
555 gc->getState()->setMaxTexturePoolSize(maxTexturePoolSize);
556 gc->getState()->setMaxBufferObjectPoolSize(maxBufferObjectPoolSize);
557
558 gc->realize();
559
560 if (_realizeOperation.valid() && gc->valid())
561 {
562 gc->makeCurrent();
563
564 (*_realizeOperation)(gc);
565
566 gc->releaseContext();
567 }
568 }
569
570 // attach contexts to _incrementalCompileOperation if attached.
571 if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts);
572
573 bool grabFocus = true;
574 if (grabFocus)
575 {
576 for(Contexts::iterator citr = contexts.begin();
577 citr != contexts.end();
578 ++citr)
579 {
580 osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
581 if (gw)
582 {
583 gw->grabFocusIfPointerInWindow();
584 }
585 }
586 }
587
588 // initialize the global timer to be relative to the current time.
589 osg::Timer::instance()->setStartTick();
590
591 // pass on the start tick to all the associated event queues
592 setStartTick(osg::Timer::instance()->getStartTick());
593
594 // configure threading.
595 setUpThreading();
596
597 if (osg::DisplaySettings::instance()->getCompileContextsHint())
598 {
599 int numProcessors = OpenThreads::GetNumberOfProcessors();
600 int processNum = 0;
601
602 for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i)
603 {
604 osg::GraphicsContext* gc = osg::GraphicsContext::getOrCreateCompileContext(i);
605
606 if (gc)
607 {
608 gc->createGraphicsThread();
609 gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors);
610 gc->getGraphicsThread()->startThread();
611
612 ++processNum;
613 }
614 }
615 }
616 #if 0
617 osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
618 if (getCamera()->getViewport())
619 {
620 osg::Viewport* viewport = getCamera()->getViewport();
621 eventState->setInputRange( viewport->x(), viewport->y(), viewport->x() + viewport->width(), viewport->y() + viewport->height());
622 }
623 else
624 {
625 eventState->setInputRange(-1.0, -1.0, 1.0, 1.0);
626 }
627 #endif
628 }
629
630
631
advance(double simulationTime)632 void Viewer::advance(double simulationTime)
633 {
634 if (_done) return;
635
636 double previousReferenceTime = _frameStamp->getReferenceTime();
637 unsigned int previousFrameNumber = _frameStamp->getFrameNumber();
638
639 _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1);
640
641 _frameStamp->setReferenceTime( osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()) );
642
643 if (simulationTime==USE_REFERENCE_TIME)
644 {
645 _frameStamp->setSimulationTime(_frameStamp->getReferenceTime());
646 }
647 else
648 {
649 _frameStamp->setSimulationTime(simulationTime);
650 }
651
652 if (getViewerStats() && getViewerStats()->collectStats("frame_rate"))
653 {
654 // update previous frame stats
655 double deltaFrameTime = _frameStamp->getReferenceTime() - previousReferenceTime;
656 getViewerStats()->setAttribute(previousFrameNumber, "Frame duration", deltaFrameTime);
657 getViewerStats()->setAttribute(previousFrameNumber, "Frame rate", 1.0/deltaFrameTime);
658
659 // update current frames stats
660 getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Reference time", _frameStamp->getReferenceTime());
661 }
662
663
664 if (osg::Referenced::getDeleteHandler())
665 {
666 osg::Referenced::getDeleteHandler()->flush();
667 osg::Referenced::getDeleteHandler()->setFrameNumber(_frameStamp->getFrameNumber());
668 }
669
670 }
671
generateSlavePointerData(osg::Camera * camera,osgGA::GUIEventAdapter & event)672 void Viewer::generateSlavePointerData(osg::Camera* camera, osgGA::GUIEventAdapter& event)
673 {
674 osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
675 if (!gw) return;
676
677 // What type of Camera is it?
678 // 1) Master Camera : do nothin extra
679 // 2) Slave Camera, Relative RF, Same scene graph as master : transform coords into Master Camera and add to PointerData list
680 // 3) Slave Camera, Relative RF, Different scene graph from master : do nothing extra?
681 // 4) Slave Camera, Absolute RF, Same scene graph as master : do nothing extra?
682 // 5) Slave Camera, Absolute RF, Different scene graph : do nothing extra?
683 // 6) Slave Camera, Absolute RF, Different scene graph but a distortion correction subgraph depending upon RTT Camera (slave or master)
684 // : 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.
685
686 // if camera isn't the master it must be a slave and could need reprojecting.
687 if (camera!=getCamera())
688 {
689 float x = event.getX();
690 float y = event.getY();
691
692 bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
693 if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
694
695 double master_min_x = -1.0;
696 double master_max_x = 1.0;
697 double master_min_y = -1.0;
698 double master_max_y = 1.0;
699
700 osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix();
701 if (getCamera()->getViewport())
702 {
703 osg::Viewport* viewport = getCamera()->getViewport();
704 master_min_x = viewport->x();
705 master_min_y = viewport->y();
706 master_max_x = viewport->x()+viewport->width();
707 master_max_y = viewport->y()+viewport->height();
708 masterCameraVPW *= viewport->computeWindowMatrix();
709 }
710
711 // slave Camera if it shares the same View
712 osg::View::Slave* slave = findSlaveForCamera(camera);
713 if (slave)
714 {
715 if (camera->getReferenceFrame()==osg::Camera::RELATIVE_RF && slave->_useMastersSceneData)
716 {
717 osg::Viewport* viewport = camera->getViewport();
718 osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
719 if (viewport)
720 {
721 localCameraVPW *= viewport->computeWindowMatrix();
722 }
723
724 osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW );
725 osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;
726 event.addPointerData(new osgGA::PointerData(getCamera(), new_coord.x(), master_min_x, master_max_x,
727 new_coord.y(), master_min_y, master_max_y));
728 }
729 else if (!slave->_useMastersSceneData)
730 {
731 // Are their any RTT Camera's that this Camera depends upon for textures?
732
733 osg::ref_ptr<osgUtil::RayIntersector> ray = new osgUtil::RayIntersector(osgUtil::Intersector::WINDOW, x,y);
734 osgUtil::IntersectionVisitor iv(ray.get());
735 camera->accept(iv);
736 if (ray->containsIntersections())
737 {
738 osg::Vec3 tc;
739 osg::Texture* texture = ray->getFirstIntersection().getTextureLookUp(tc);
740 if (texture)
741 {
742 // look up Texture in RTT Camera's.
743 for(unsigned int i=0; i<getNumSlaves();++i)
744 {
745 osg::Camera* slave_camera = getSlave(i)._camera.get();
746 if (slave_camera)
747 {
748 osg::Camera::BufferAttachmentMap::const_iterator ba_itr = slave_camera->getBufferAttachmentMap().find(osg::Camera::COLOR_BUFFER);
749 if (ba_itr != slave_camera->getBufferAttachmentMap().end())
750 {
751 if (ba_itr->second._texture == texture)
752 {
753 osg::TextureRectangle* tr = dynamic_cast<osg::TextureRectangle*>(ba_itr->second._texture.get());
754 osg::TextureCubeMap* tcm = dynamic_cast<osg::TextureCubeMap*>(ba_itr->second._texture.get());
755 if (tr)
756 {
757 event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, static_cast<float>(tr->getTextureWidth()),
758 tc.y(), 0.0f, static_cast<float>(tr->getTextureHeight())));
759 }
760 else if (tcm)
761 {
762 OSG_INFO<<" Slave has matched texture cubemap"<<ba_itr->second._texture.get()<<", "<<ba_itr->second._face<<std::endl;
763 }
764 else
765 {
766 event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, 1.0f,
767 tc.y(), 0.0f, 1.0f));
768 }
769 }
770 }
771 }
772 }
773 }
774 }
775 }
776 }
777 }
778 }
779
780
generatePointerData(osgGA::GUIEventAdapter & event)781 void Viewer::generatePointerData(osgGA::GUIEventAdapter& event)
782 {
783 osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
784 if (!gw) return;
785
786 float x = event.getX();
787 float y = event.getY();
788
789 bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
790 if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
791
792 event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width,
793 y, 0, gw->getTraits()->height));
794
795 event.setMouseYOrientationAndUpdateCoords(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
796
797 typedef std::vector<osg::Camera*> CameraVector;
798 CameraVector activeCameras;
799
800 osgViewer::View* this_view = dynamic_cast<osgViewer::View*>(this);
801 osg::GraphicsContext::Cameras& cameras = gw->getCameras();
802 for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
803 citr != cameras.end();
804 ++citr)
805 {
806 osg::Camera* camera = *citr;
807 if (camera->getView()==this_view &&
808 camera->getAllowEventFocus() &&
809 camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
810 {
811 osg::Viewport* viewport = camera ? camera->getViewport() : 0;
812 if (viewport &&
813 x >= viewport->x() && y >= viewport->y() &&
814 x <= (viewport->x()+viewport->width()) && y <= (viewport->y()+viewport->height()) )
815 {
816 activeCameras.push_back(camera);
817 }
818 }
819 }
820
821 std::sort(activeCameras.begin(), activeCameras.end(), osg::CameraRenderOrderSortOp());
822
823 osg::Camera* camera = activeCameras.empty() ? 0 : activeCameras.back();
824
825 if (camera)
826 {
827 osg::Viewport* viewport = camera ? camera->getViewport() : 0;
828
829 event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,
830 (y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));
831
832 // if camera isn't the master it must be a slave and could need reprojecting.
833 if (camera!=getCamera())
834 {
835 generateSlavePointerData(camera, event);
836 }
837 }
838 }
839
reprojectPointerData(osgGA::GUIEventAdapter & source_event,osgGA::GUIEventAdapter & dest_event)840 void Viewer::reprojectPointerData(osgGA::GUIEventAdapter& source_event, osgGA::GUIEventAdapter& dest_event)
841 {
842 osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(dest_event.getGraphicsContext());
843 if (!gw) return;
844
845 float x = dest_event.getX();
846 float y = dest_event.getY();
847
848 bool invert_y = dest_event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
849 if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
850
851 dest_event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width,
852 y, 0, gw->getTraits()->height));
853
854 dest_event.setMouseYOrientationAndUpdateCoords(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
855
856 osg::Camera* camera = (source_event.getNumPointerData()>=2) ? dynamic_cast<osg::Camera*>(source_event.getPointerData(1)->object.get()) : 0;
857 osg::Viewport* viewport = camera ? camera->getViewport() : 0;
858
859 if (!viewport) return;
860
861 dest_event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,
862 (y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));
863
864 // if camera isn't the master it must be a slave and could need reprojecting.
865 if (camera!=getCamera())
866 {
867 generateSlavePointerData(camera, dest_event);
868 }
869 }
870
eventTraversal()871 void Viewer::eventTraversal()
872 {
873 if (_done) return;
874
875 double cutOffTime = _frameStamp->getReferenceTime();
876
877 double beginEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
878
879 // OSG_NOTICE<<"Viewer::frameEventTraversal()."<<std::endl;
880
881 // need to copy events from the GraphicsWindow's into local EventQueue;
882 osgGA::EventQueue::Events events;
883
884 Contexts contexts;
885 getContexts(contexts);
886
887 // set done if there are no windows
888 checkWindowStatus(contexts);
889 if (_done) return;
890
891 osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
892
893 // get events from user Devices attached to Viewer.
894 for(Devices::iterator eitr = _eventSources.begin();
895 eitr != _eventSources.end();
896 ++eitr)
897 {
898 osgGA::Device* es = eitr->get();
899 if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS)
900 es->checkEvents();
901
902 // open question, will we need to reproject mouse coordinates into current view's coordinate frame as is down for GraphicsWindow provided events?
903 // for now assume now and just get the events directly without any reprojection.
904 es->getEventQueue()->takeEvents(events, cutOffTime);
905 }
906
907 // get events from all windows attached to Viewer.
908 for(Contexts::iterator citr = contexts.begin();
909 citr != contexts.end();
910 ++citr)
911 {
912 osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
913 if (gw)
914 {
915 gw->checkEvents();
916
917 osgGA::EventQueue::Events gw_events;
918 gw->getEventQueue()->takeEvents(gw_events, cutOffTime);
919
920 osgGA::EventQueue::Events::iterator itr;
921 for(itr = gw_events.begin();
922 itr != gw_events.end();
923 ++itr)
924 {
925 osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
926 if (!event) continue;
927
928 event->setGraphicsContext(gw);
929
930 switch(event->getEventType())
931 {
932 case(osgGA::GUIEventAdapter::PUSH):
933 case(osgGA::GUIEventAdapter::RELEASE):
934 case(osgGA::GUIEventAdapter::DOUBLECLICK):
935 case(osgGA::GUIEventAdapter::MOVE):
936 case(osgGA::GUIEventAdapter::DRAG):
937 {
938 if (event->getEventType()!=osgGA::GUIEventAdapter::DRAG ||
939 eventState->getGraphicsContext()!=event->getGraphicsContext() ||
940 eventState->getNumPointerData()<2)
941 {
942 generatePointerData(*event);
943 }
944 else
945 {
946 reprojectPointerData(*eventState, *event);
947 }
948
949
950 eventState->copyPointerDataFrom(*event);
951
952 break;
953 }
954 default:
955 event->copyPointerDataFrom(*eventState);
956 break;
957 }
958
959 events.push_back(event);
960 }
961
962 for(itr = gw_events.begin();
963 itr != gw_events.end();
964 ++itr)
965 {
966 osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
967 if (!event) continue;
968 switch(event->getEventType())
969 {
970 case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
971 {
972 bool wasThreading = areThreadsRunning();
973 if (wasThreading) stopThreading();
974
975 gw->close();
976 _currentContext = NULL;
977
978 if (wasThreading) startThreading();
979
980 break;
981 }
982 default:
983 break;
984 }
985 }
986
987 }
988 }
989
990 // create a frame event for the new frame.
991 {
992 osg::ref_ptr<osgGA::GUIEventAdapter> event = _eventQueue->frame( getFrameStamp()->getReferenceTime() );
993
994 if (!eventState || eventState->getNumPointerData()<2)
995 {
996 generatePointerData(*event);
997 }
998 else
999 {
1000 reprojectPointerData(*eventState, *event);
1001 }
1002 }
1003
1004 // OSG_NOTICE<<"mouseEventState Xmin = "<<eventState->getXmin()<<" Ymin="<<eventState->getYmin()<<" xMax="<<eventState->getXmax()<<" Ymax="<<eventState->getYmax()<<std::endl;
1005
1006 _eventQueue->takeEvents(events, cutOffTime);
1007
1008 // OSG_NOTICE<<"Events "<<events.size()<<std::endl;
1009
1010 if ((_keyEventSetsDone!=0) || _quitEventSetsDone)
1011 {
1012 for(osgGA::EventQueue::Events::iterator itr = events.begin();
1013 itr != events.end();
1014 ++itr)
1015 {
1016 osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
1017 if (!event) continue;
1018
1019 // ignore event if it's already been handled.
1020 if (event->getHandled()) continue;
1021
1022 switch(event->getEventType())
1023 {
1024 case(osgGA::GUIEventAdapter::KEYUP):
1025 if (_keyEventSetsDone && event->getKey()==_keyEventSetsDone) _done = true;
1026 break;
1027
1028 case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
1029 if (_quitEventSetsDone) _done = true;
1030 break;
1031
1032 default:
1033 break;
1034 }
1035 }
1036 }
1037
1038 if (_done) return;
1039
1040 if (_eventVisitor.valid() && getSceneData())
1041 {
1042 _eventVisitor->setFrameStamp(getFrameStamp());
1043 _eventVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());
1044
1045 for(osgGA::EventQueue::Events::iterator itr = events.begin();
1046 itr != events.end();
1047 ++itr)
1048 {
1049 osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
1050 if (!event) continue;
1051
1052 _eventVisitor->reset();
1053 _eventVisitor->addEvent( event );
1054
1055 getSceneData()->accept(*_eventVisitor);
1056
1057 // Do EventTraversal for slaves with their own subgraph
1058 for(unsigned int i=0; i<getNumSlaves(); ++i)
1059 {
1060 osg::View::Slave& slave = getSlave(i);
1061 osg::Camera* camera = slave._camera.get();
1062 if(camera && !slave._useMastersSceneData)
1063 {
1064 camera->accept(*_eventVisitor);
1065 }
1066 }
1067
1068
1069 // call any camera event callbacks, but only traverse that callback, don't traverse its subgraph
1070 // leave that to the scene update traversal.
1071 osg::NodeVisitor::TraversalMode tm = _eventVisitor->getTraversalMode();
1072 _eventVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
1073
1074 if (_camera.valid() && _camera->getEventCallback()) _camera->accept(*_eventVisitor);
1075
1076 for(unsigned int i=0; i<getNumSlaves(); ++i)
1077 {
1078 osg::View::Slave& slave = getSlave(i);
1079 osg::Camera* camera = slave._camera.get();
1080 if (camera && slave._useMastersSceneData && camera->getEventCallback())
1081 {
1082 camera->accept(*_eventVisitor);
1083 }
1084 }
1085
1086 _eventVisitor->setTraversalMode(tm);
1087
1088 }
1089 }
1090
1091
1092 for(osgGA::EventQueue::Events::iterator itr = events.begin();
1093 itr != events.end();
1094 ++itr)
1095 {
1096 osgGA::Event* event = itr->get();
1097 for(EventHandlers::iterator hitr = _eventHandlers.begin();
1098 hitr != _eventHandlers.end();
1099 ++hitr)
1100 {
1101 (*hitr)->handle( event, 0, _eventVisitor.get());
1102 }
1103
1104 }
1105
1106 for(osgGA::EventQueue::Events::iterator itr = events.begin();
1107 itr != events.end();
1108 ++itr)
1109 {
1110 osgGA::Event* event = itr->get();
1111 if (event && _cameraManipulator.valid())
1112 {
1113 _cameraManipulator->handle( event, 0, _eventVisitor.get());
1114 }
1115 }
1116
1117 if (getViewerStats() && getViewerStats()->collectStats("event"))
1118 {
1119 double endEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1120
1121 // update current frames stats
1122 getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal begin time", beginEventTraversal);
1123 getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal end time", endEventTraversal);
1124 getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal time taken", endEventTraversal-beginEventTraversal);
1125 }
1126
1127 }
1128
updateTraversal()1129 void Viewer::updateTraversal()
1130 {
1131 if (_done) return;
1132
1133 double beginUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1134
1135 _updateVisitor->reset();
1136 _updateVisitor->setFrameStamp(getFrameStamp());
1137 _updateVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());
1138
1139 _scene->updateSceneGraph(*_updateVisitor);
1140
1141 // if we have a shared state manager prune any unused entries
1142 if (osgDB::Registry::instance()->getSharedStateManager())
1143 osgDB::Registry::instance()->getSharedStateManager()->prune();
1144
1145 // update the Registry object cache.
1146 osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExternalReferences(*getFrameStamp());
1147 osgDB::Registry::instance()->removeExpiredObjectsInCache(*getFrameStamp());
1148
1149
1150 if (_updateOperations.valid())
1151 {
1152 _updateOperations->runOperations(this);
1153 }
1154
1155 if (_incrementalCompileOperation.valid())
1156 {
1157 // merge subgraphs that have been compiled by the incremental compiler operation.
1158 _incrementalCompileOperation->mergeCompiledSubgraphs(getFrameStamp());
1159 }
1160
1161 {
1162 // Do UpdateTraversal for slaves with their own subgraph
1163 for(unsigned int i=0; i<getNumSlaves(); ++i)
1164 {
1165 osg::View::Slave& slave = getSlave(i);
1166 osg::Camera* camera = slave._camera.get();
1167 if(camera && !slave._useMastersSceneData)
1168 {
1169 camera->accept(*_updateVisitor);
1170 }
1171 }
1172 }
1173
1174 {
1175 // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
1176 // leave that to the scene update traversal.
1177 osg::NodeVisitor::TraversalMode tm = _updateVisitor->getTraversalMode();
1178 _updateVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
1179
1180 if (_camera.valid() && _camera->getUpdateCallback()) _camera->accept(*_updateVisitor);
1181
1182 for(unsigned int i=0; i<getNumSlaves(); ++i)
1183 {
1184 osg::View::Slave& slave = getSlave(i);
1185 osg::Camera* camera = slave._camera.get();
1186 if (camera && slave._useMastersSceneData && camera->getUpdateCallback())
1187 {
1188 camera->accept(*_updateVisitor);
1189 }
1190 }
1191
1192 _updateVisitor->setTraversalMode(tm);
1193 }
1194
1195 if (_cameraManipulator.valid())
1196 {
1197 setFusionDistance( getCameraManipulator()->getFusionDistanceMode(),
1198 getCameraManipulator()->getFusionDistanceValue() );
1199
1200 _cameraManipulator->updateCamera(*_camera);
1201 }
1202
1203 updateSlaves();
1204
1205 if (getViewerStats() && getViewerStats()->collectStats("update"))
1206 {
1207 double endUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1208
1209 // update current frames stats
1210 getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal begin time", beginUpdateTraversal);
1211 getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal end time", endUpdateTraversal);
1212 getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal time taken", endUpdateTraversal-beginUpdateTraversal);
1213 }
1214 }
1215
getScenes(Scenes & scenes,bool)1216 void Viewer::getScenes(Scenes& scenes, bool /*onlyValid*/)
1217 {
1218 scenes.clear();
1219 scenes.push_back(_scene.get());
1220 }
1221
getViews(Views & views,bool)1222 void Viewer::getViews(Views& views, bool /*onlyValid*/)
1223 {
1224 views.clear();
1225 views.push_back(this);
1226 }
1227
getAllThreads(Threads & threads,bool onlyActive)1228 void Viewer::getAllThreads(Threads& threads, bool onlyActive)
1229 {
1230 threads.clear();
1231
1232 OperationThreads operationThreads;
1233 getOperationThreads(operationThreads);
1234
1235 for(OperationThreads::iterator itr = operationThreads.begin();
1236 itr != operationThreads.end();
1237 ++itr)
1238 {
1239 threads.push_back(*itr);
1240 }
1241
1242
1243 if (_scene.valid())
1244 {
1245 osgDB::DatabasePager* dp = _scene->getDatabasePager();
1246 if (dp)
1247 {
1248 for(unsigned int i=0; i<dp->getNumDatabaseThreads(); ++i)
1249 {
1250 osgDB::DatabasePager::DatabaseThread* dt = dp->getDatabaseThread(i);
1251 if (!onlyActive || dt->isRunning())
1252 {
1253 threads.push_back(dt);
1254 }
1255 }
1256 }
1257 }
1258 }
1259
1260
getOperationThreads(OperationThreads & threads,bool onlyActive)1261 void Viewer::getOperationThreads(OperationThreads& threads, bool onlyActive)
1262 {
1263 threads.clear();
1264
1265 Contexts contexts;
1266 getContexts(contexts);
1267 for(Contexts::iterator gcitr = contexts.begin();
1268 gcitr != contexts.end();
1269 ++gcitr)
1270 {
1271 osg::GraphicsContext* gc = *gcitr;
1272 if (gc->getGraphicsThread() &&
1273 (!onlyActive || gc->getGraphicsThread()->isRunning()) )
1274 {
1275 threads.push_back(gc->getGraphicsThread());
1276 }
1277 }
1278
1279 Cameras cameras;
1280 getCameras(cameras);
1281 for(Cameras::iterator citr = cameras.begin();
1282 citr != cameras.end();
1283 ++citr)
1284 {
1285 osg::Camera* camera = *citr;
1286 if (camera->getCameraThread() &&
1287 (!onlyActive || camera->getCameraThread()->isRunning()) )
1288 {
1289 threads.push_back(camera->getCameraThread());
1290 }
1291 }
1292
1293 }
1294
getContexts(Contexts & contexts,bool onlyValid)1295 void Viewer::getContexts(Contexts& contexts, bool onlyValid)
1296 {
1297 typedef std::set<osg::GraphicsContext*> ContextSet;
1298 ContextSet contextSet;
1299
1300 contexts.clear();
1301
1302 if (_camera.valid() &&
1303 _camera->getGraphicsContext() &&
1304 (_camera->getGraphicsContext()->valid() || !onlyValid))
1305 {
1306 contextSet.insert(_camera->getGraphicsContext());
1307 contexts.push_back(_camera->getGraphicsContext());
1308 }
1309
1310 for(unsigned int i=0; i<getNumSlaves(); ++i)
1311 {
1312 Slave& slave = getSlave(i);
1313 osg::GraphicsContext* sgc = slave._camera.valid() ? slave._camera->getGraphicsContext() : 0;
1314 if (sgc && (sgc->valid() || !onlyValid))
1315 {
1316 if (contextSet.count(sgc)==0)
1317 {
1318 contextSet.insert(sgc);
1319 contexts.push_back(sgc);
1320 }
1321 }
1322 }
1323 }
1324
getCameras(Cameras & cameras,bool onlyActive)1325 void Viewer::getCameras(Cameras& cameras, bool onlyActive)
1326 {
1327 cameras.clear();
1328
1329 if (_camera.valid() &&
1330 (!onlyActive || (_camera->getGraphicsContext() && _camera->getGraphicsContext()->valid())) ) cameras.push_back(_camera.get());
1331
1332 for(Slaves::iterator itr = _slaves.begin();
1333 itr != _slaves.end();
1334 ++itr)
1335 {
1336 if (itr->_camera.valid() &&
1337 (!onlyActive || (itr->_camera->getGraphicsContext() && itr->_camera->getGraphicsContext()->valid())) ) cameras.push_back(itr->_camera.get());
1338 }
1339 }
1340
1341
elapsedTime()1342 double Viewer::elapsedTime()
1343 {
1344 return osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1345 }
1346
1347
getUsage(osg::ApplicationUsage & usage) const1348 void Viewer::getUsage(osg::ApplicationUsage& usage) const
1349 {
1350 if (_cameraManipulator.valid())
1351 {
1352 _cameraManipulator->getUsage(usage);
1353 }
1354
1355 for(EventHandlers::const_iterator hitr = _eventHandlers.begin();
1356 hitr != _eventHandlers.end();
1357 ++hitr)
1358 {
1359 (*hitr)->getUsage(usage);
1360 }
1361 }
1362
1363