root/OpenSceneGraph/trunk/src/osgViewer/CompositeViewer.cpp @ 13376

Revision 13376, 44.6 kB (checked in by robert, 4 days ago)

Added shaders to support experimental shader based displacement mapping technique osgTerrain::ShaderTerrain?.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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
26using namespace osgViewer;
27
28CompositeViewer::CompositeViewer()
29{
30    constructorInit();
31}
32
33CompositeViewer::CompositeViewer(const CompositeViewer& cv,const osg::CopyOp& copyop):
34    osg::Object(true),
35    ViewerBase(cv)
36{
37    constructorInit();
38}
39
40CompositeViewer::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 permissable 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
78void 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
100CompositeViewer::~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        (*citr)->close();
130    }
131
132    OSG_INFO<<"finished CompositeViewer::~CompositeViewer()"<<std::endl;
133}
134
135bool CompositeViewer::readConfiguration(const std::string& filename)
136{
137    OSG_NOTICE<<"CompositeViewer::readConfiguration("<<filename<<")"<<std::endl;
138    osg::ref_ptr<osg::Object> obj = osgDB::readObjectFile(filename);
139    osgViewer::View * view = dynamic_cast<osgViewer::View *>(obj.get());
140    if (view)
141    {
142        addView(view);
143        return true;
144    }
145    return false;
146}
147
148
149void CompositeViewer::addView(osgViewer::View* view)
150{
151    if (!view) return;
152
153    bool alreadyRealized = isRealized();
154
155    bool threadsWereRunning = _threadsRunning;
156    if (threadsWereRunning) stopThreading();
157
158    _views.push_back(view);
159
160    view->_viewerBase = this;
161
162    if (view->getSceneData())
163    {
164        // make sure that existing scene graph objects are allocated with thread safe ref/unref
165        if (getThreadingModel()!=ViewerBase::SingleThreaded)
166        {
167            view->getSceneData()->setThreadSafeRefUnref(true);
168        }
169
170        // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it.
171        view->getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts());
172    }
173
174    view->setFrameStamp(_frameStamp.get());
175
176    if (alreadyRealized)
177    {
178        Contexts contexts;
179        if (view->getCamera()->getGraphicsContext())
180        {
181            contexts.push_back(view->getCamera()->getGraphicsContext());
182        }
183        for(unsigned int i=0; i<view->getNumSlaves(); ++i)
184        {
185            if (view->getSlave(i)._camera->getGraphicsContext())
186            {
187                contexts.push_back(view->getSlave(i)._camera->getGraphicsContext());
188            }
189        }
190
191        for(Contexts::iterator itr = contexts.begin();
192            itr != contexts.end();
193            ++itr)
194        {
195            if (!((*itr)->isRealized()))
196            {
197                (*itr)->realize();
198            }
199        }
200
201    }
202
203    if (threadsWereRunning) startThreading();
204}
205
206void CompositeViewer::removeView(osgViewer::View* view)
207{
208    for(RefViews::iterator itr = _views.begin();
209        itr != _views.end();
210        ++itr)
211    {
212        if (*itr == view)
213        {
214            bool threadsWereRunning = _threadsRunning;
215            if (threadsWereRunning) stopThreading();
216
217            view->_viewerBase = 0;
218
219            _views.erase(itr);
220
221            if (threadsWereRunning) startThreading();
222
223            return;
224        }
225    }
226}
227
228bool CompositeViewer::isRealized() const
229{
230    Contexts contexts;
231    const_cast<CompositeViewer*>(this)->getContexts(contexts);
232
233    unsigned int numRealizedWindows = 0;
234
235    // clear out all the previously assigned operations
236    for(Contexts::iterator citr = contexts.begin();
237        citr != contexts.end();
238        ++citr)
239    {
240        if ((*citr)->isRealized()) ++numRealizedWindows;
241    }
242
243    return numRealizedWindows > 0;
244}
245
246bool CompositeViewer::checkNeedToDoFrame()
247{
248    if (_requestRedraw) return true;
249    if (_requestContinousUpdate) return true;
250
251    for(RefViews::iterator itr = _views.begin();
252        itr != _views.end();
253        ++itr)
254    {
255        osgViewer::View* view = itr->get();
256        if (view)
257        {
258            // If the database pager is going to update the scene the render flag is
259            // set so that the updates show up
260            if (view->getDatabasePager()->requiresUpdateSceneGraph() ||
261                view->getDatabasePager()->getRequestsInProgress()) return true;
262
263            // if there update callbacks then we need to do frame.
264            if (view->getCamera()->getUpdateCallback()) return true;
265            if (view->getSceneData()!=0 && view->getSceneData()->getNumChildrenRequiringUpdateTraversal()>0) return true;
266        }
267    }
268
269    // now do a eventTraversal to see if any events might require a new frame.
270    eventTraversal();
271
272    if (_requestRedraw) return true;
273    if (_requestContinousUpdate) return true;
274
275    return false;
276}
277
278int CompositeViewer::run()
279{
280    for(RefViews::iterator itr = _views.begin();
281        itr != _views.end();
282        ++itr)
283    {
284        osgViewer::View* view = itr->get();
285        if ((view->getCameraManipulator()==0) && view->getCamera()->getAllowEventFocus())
286        {
287            view->setCameraManipulator(new osgGA::TrackballManipulator());
288        }
289    }
290
291    setReleaseContextAtEndOfFrameHint(false);
292
293    return ViewerBase::run();
294}
295
296void CompositeViewer::setStartTick(osg::Timer_t tick)
297{
298    _startTick = tick;
299
300    for(RefViews::iterator vitr = _views.begin();
301        vitr != _views.end();
302        ++vitr)
303    {
304        (*vitr)->setStartTick(tick);
305    }
306
307    Contexts contexts;
308    getContexts(contexts,false);
309
310    for(Contexts::iterator citr = contexts.begin();
311        citr != contexts.end();
312        ++citr)
313    {
314        osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
315        if (gw)
316        {
317            gw->getEventQueue()->setStartTick(_startTick);
318        }
319    }
320}
321
322
323void CompositeViewer::setReferenceTime(double time)
324{
325    osg::Timer_t tick = osg::Timer::instance()->tick();
326    double currentTime = osg::Timer::instance()->delta_s(_startTick, tick);
327    double delta_ticks = (time-currentTime)*(osg::Timer::instance()->getSecondsPerTick());
328    if (delta_ticks>=0) tick += osg::Timer_t(delta_ticks);
329    else tick -= osg::Timer_t(-delta_ticks);
330
331    // assign the new start tick
332    setStartTick(tick);
333}
334
335
336
337void CompositeViewer::viewerInit()
338{
339    OSG_INFO<<"CompositeViewer::init()"<<std::endl;
340
341    for(RefViews::iterator itr = _views.begin();
342        itr != _views.end();
343        ++itr)
344    {
345        (*itr)->init();
346    }
347}
348
349void CompositeViewer::getContexts(Contexts& contexts, bool onlyValid)
350{
351    typedef std::set<osg::GraphicsContext*> ContextSet;
352    ContextSet contextSet;
353
354    contexts.clear();
355
356    for(RefViews::iterator vitr = _views.begin();
357        vitr != _views.end();
358        ++vitr)
359    {
360        osgViewer::View* view = vitr->get();
361        osg::GraphicsContext* gc = view->getCamera() ? view->getCamera()->getGraphicsContext() : 0;
362        if (gc && (gc->valid() || !onlyValid))
363        {
364            if (contextSet.count(gc)==0)
365            {
366                contextSet.insert(gc);
367                contexts.push_back(gc);
368            }
369        }
370
371        for(unsigned int i=0; i<view->getNumSlaves(); ++i)
372        {
373            View::Slave& slave = view->getSlave(i);
374            osg::GraphicsContext* sgc = slave._camera.valid() ? slave._camera->getGraphicsContext() : 0;
375            if (sgc && (sgc->valid() || !onlyValid))
376            {
377                if (contextSet.count(sgc)==0)
378                {
379                    contextSet.insert(sgc);
380                    contexts.push_back(sgc);
381                }
382            }
383        }
384    }
385}
386
387void CompositeViewer::getCameras(Cameras& cameras, bool onlyActive)
388{
389    cameras.clear();
390
391    for(RefViews::iterator vitr = _views.begin();
392        vitr != _views.end();
393        ++vitr)
394    {
395        View* view = vitr->get();
396
397        if (view->getCamera() &&
398            (!onlyActive || (view->getCamera()->getGraphicsContext() && view->getCamera()->getGraphicsContext()->valid())) ) cameras.push_back(view->getCamera());
399
400        for(View::Slaves::iterator itr = view->_slaves.begin();
401            itr != view->_slaves.end();
402            ++itr)
403        {
404            if (itr->_camera.valid() &&
405                (!onlyActive || (itr->_camera->getGraphicsContext() && itr->_camera->getGraphicsContext()->valid())) ) cameras.push_back(itr->_camera.get());
406        }
407    }
408}
409
410void CompositeViewer::getScenes(Scenes& scenes, bool onlyValid)
411{
412    scenes.clear();
413
414    typedef std::set<osgViewer::Scene*> SceneSet;
415    SceneSet sceneSet;
416
417    for(RefViews::iterator vitr = _views.begin();
418        vitr != _views.end();
419        ++vitr)
420    {
421        osgViewer::View* view = vitr->get();
422        if (view->getScene() && (!onlyValid || view->getScene()->getSceneData()))
423        {
424            if (sceneSet.count(view->getScene())==0)
425            {
426                sceneSet.insert(view->getScene());
427                scenes.push_back(view->getScene());
428            }
429        }
430    }
431}
432
433void CompositeViewer::getViews(Views& views, bool onlyValid)
434{
435    views.clear();
436
437    for(RefViews::iterator vitr = _views.begin();
438        vitr != _views.end();
439        ++vitr)
440    {
441        views.push_back(vitr->get());
442    }
443}
444
445void CompositeViewer::getAllThreads(Threads& threads, bool onlyActive)
446{
447    threads.clear();
448
449    OperationThreads operationThreads;
450    getOperationThreads(operationThreads);
451
452    for(OperationThreads::iterator itr = operationThreads.begin();
453        itr != operationThreads.end();
454        ++itr)
455    {
456        threads.push_back(*itr);
457    }
458
459    Scenes scenes;
460    getScenes(scenes);
461
462    for(Scenes::iterator sitr = scenes.begin();
463        sitr != scenes.end();
464        ++sitr)
465    {
466        Scene* scene = *sitr;
467        osgDB::DatabasePager* dp = scene->getDatabasePager();
468        if (dp)
469        {
470            for(unsigned int i=0; i<dp->getNumDatabaseThreads(); ++i)
471            {
472                osgDB::DatabasePager::DatabaseThread* dt = dp->getDatabaseThread(i);
473                if (!onlyActive || dt->isRunning())
474                {
475                    threads.push_back(dt);
476                }
477            }
478        }
479    }
480}
481
482
483void CompositeViewer::getOperationThreads(OperationThreads& threads, bool onlyActive)
484{
485    threads.clear();
486
487    Contexts contexts;
488    getContexts(contexts);
489    for(Contexts::iterator gcitr = contexts.begin();
490        gcitr != contexts.end();
491        ++gcitr)
492    {
493        osg::GraphicsContext* gc = *gcitr;
494        if (gc->getGraphicsThread() &&
495            (!onlyActive || gc->getGraphicsThread()->isRunning()) )
496        {
497            threads.push_back(gc->getGraphicsThread());
498        }
499    }
500
501    Cameras cameras;
502    getCameras(cameras);
503    for(Cameras::iterator citr = cameras.begin();
504        citr != cameras.end();
505        ++citr)
506    {
507        osg::Camera* camera = *citr;
508        if (camera->getCameraThread() &&
509            (!onlyActive || camera->getCameraThread()->isRunning()) )
510        {
511            threads.push_back(camera->getCameraThread());
512        }
513    }
514
515}
516
517void CompositeViewer::realize()
518{
519    //OSG_INFO<<"CompositeViewer::realize()"<<std::endl;
520
521    setCameraWithFocus(0);
522
523    if (_views.empty())
524    {
525        OSG_NOTICE<<"CompositeViewer::realize() - No views to realize."<<std::endl;
526        _done = true;
527        return;
528    }
529
530    Contexts contexts;
531    getContexts(contexts);
532
533    if (contexts.empty())
534    {
535        OSG_INFO<<"CompositeViewer::realize() - No valid contexts found, setting up view across all screens."<<std::endl;
536
537        // no windows are already set up so set up a default view
538        _views[0]->setUpViewAcrossAllScreens();
539
540        getContexts(contexts);
541    }
542
543    if (contexts.empty())
544    {
545        OSG_NOTICE<<"CompositeViewer::realize() - failed to set up any windows"<<std::endl;
546        _done = true;
547        return;
548    }
549
550    unsigned int maxTexturePoolSize = osg::DisplaySettings::instance()->getMaxTexturePoolSize();
551    unsigned int maxBufferObjectPoolSize = osg::DisplaySettings::instance()->getMaxBufferObjectPoolSize();
552
553    for(Contexts::iterator citr = contexts.begin();
554        citr != contexts.end();
555        ++citr)
556    {
557        osg::GraphicsContext* gc = *citr;
558
559        // set the pool sizes, 0 the default will result in no GL object pools.
560        gc->getState()->setMaxTexturePoolSize(maxTexturePoolSize);
561        gc->getState()->setMaxBufferObjectPoolSize(maxBufferObjectPoolSize);
562
563        gc->realize();
564
565        if (_realizeOperation.valid() && gc->valid())
566        {
567            gc->makeCurrent();
568
569            (*_realizeOperation)(gc);
570
571            gc->releaseContext();
572        }
573    }
574
575    // attach contexts to _incrementalCompileOperation if attached.
576    if (_incrementalCompileOperation) _incrementalCompileOperation->assignContexts(contexts);
577
578
579    bool grabFocus = true;
580    if (grabFocus)
581    {
582        for(Contexts::iterator citr = contexts.begin();
583            citr != contexts.end();
584            ++citr)
585        {
586            osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
587            if (gw)
588            {
589                gw->grabFocusIfPointerInWindow();
590            }
591        }
592    }
593
594
595    startThreading();
596
597    // initialize the global timer to be relative to the current time.
598    osg::Timer::instance()->setStartTick();
599
600    // pass on the start tick to all the associated eventqueues
601    setStartTick(osg::Timer::instance()->getStartTick());
602
603    if (osg::DisplaySettings::instance()->getCompileContextsHint())
604    {
605        int numProcessors = OpenThreads::GetNumberOfProcessors();
606        int processNum = 0;
607
608        for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i)
609        {
610            osg::GraphicsContext* gc = osg::GraphicsContext::getOrCreateCompileContext(i);
611
612            if (gc)
613            {
614                gc->createGraphicsThread();
615                gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors);
616                gc->getGraphicsThread()->startThread();
617
618                ++processNum;
619            }
620        }
621    }
622
623}
624
625void CompositeViewer::advance(double simulationTime)
626{
627    if (_done) return;
628
629    double previousReferenceTime = _frameStamp->getReferenceTime();
630    unsigned int previousFrameNumber = _frameStamp->getFrameNumber();
631
632
633    _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1);
634
635    _frameStamp->setReferenceTime( osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()) );
636
637    if (simulationTime==USE_REFERENCE_TIME)
638    {
639        _frameStamp->setSimulationTime(_frameStamp->getReferenceTime());
640    }
641    else
642    {
643        _frameStamp->setSimulationTime(simulationTime);
644    }
645
646
647    if (getViewerStats() && getViewerStats()->collectStats("frame_rate"))
648    {
649        // update previous frame stats
650        double deltaFrameTime = _frameStamp->getReferenceTime() - previousReferenceTime;
651        getViewerStats()->setAttribute(previousFrameNumber, "Frame duration", deltaFrameTime);
652        getViewerStats()->setAttribute(previousFrameNumber, "Frame rate", 1.0/deltaFrameTime);
653
654        // update current frames stats
655        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Reference time", _frameStamp->getReferenceTime());
656    }
657
658}
659
660void CompositeViewer::setCameraWithFocus(osg::Camera* camera)
661{
662    _cameraWithFocus = camera;
663
664    if (camera)
665    {
666        for(RefViews::iterator vitr = _views.begin();
667            vitr != _views.end();
668            ++vitr)
669        {
670            View* view = vitr->get();
671            if (view->containsCamera(camera))
672            {
673                _viewWithFocus = view;
674                return;
675            }
676        }
677    }
678
679    _viewWithFocus = 0;
680}
681
682
683void CompositeViewer::generateSlavePointerData(osg::Camera* camera, osgGA::GUIEventAdapter& event)
684{
685    osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
686    if (!gw) return;
687
688    // What type of Camera is it?
689    // 1) Master Camera : do nothin extra
690    // 2) Slave Camera, Relative RF, Same scene graph as master : transform coords into Master Camera and add to PointerData list
691    // 3) Slave Camera, Relative RF, Different scene graph from master : do nothing extra?
692    // 4) Slave Camera, Absolute RF, Same scene graph as master : do nothing extra?
693    // 5) Slave Camera, Absolute RF, Different scene graph : do nothing extra?
694    // 6) Slave Camera, Absolute RF, Different scene graph but a distortion correction subgraph depending upon RTT Camera (slave or master)
695    //                              : 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.
696
697    // if camera isn't the master it must be a slave and could need reprojecting.
698   
699   
700    osgViewer::View* view = dynamic_cast<osgViewer::View*>(camera->getView());
701    if (!view) return;
702   
703    osg::Camera* view_masterCamera = view->getCamera();
704    if (camera!=view_masterCamera)
705    {
706        float x = event.getX();
707        float y = event.getY();
708
709        bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
710        if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
711
712        osg::Matrix masterCameraVPW = view_masterCamera->getViewMatrix() * view_masterCamera->getProjectionMatrix();
713        if (view_masterCamera->getViewport())
714        {
715            osg::Viewport* viewport = view_masterCamera->getViewport();
716            masterCameraVPW *= viewport->computeWindowMatrix();
717        }
718
719        // slave Camera tahnks to sharing the same View
720        osg::View::Slave* slave = view ? view->findSlaveForCamera(camera) : 0;
721        if (slave)
722        {
723            if (camera->getReferenceFrame()==osg::Camera::RELATIVE_RF && slave->_useMastersSceneData)
724            {
725                osg::Viewport* viewport = camera->getViewport();
726                osg::Matrix localCameraVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
727                if (viewport) localCameraVPW *= viewport->computeWindowMatrix();
728
729                osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW );
730                osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;
731                //OSG_NOTICE<<"    pointer event new_coord.x()="<<new_coord.x()<<" new_coord.y()="<<new_coord.y()<<std::endl;
732                event.addPointerData(new osgGA::PointerData(view_masterCamera, new_coord.x(), -1.0, 1.0,
733                                                                               new_coord.y(), -1.0, 1.0));
734            }
735            else if (!slave->_useMastersSceneData)
736            {
737                // Are their any RTT Camera's that this Camera depends upon for textures?
738
739                osg::ref_ptr<osgUtil::LineSegmentIntersector> ray = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x,y);
740                osgUtil::IntersectionVisitor iv(ray.get());
741                camera->accept(iv);
742                if (ray->containsIntersections())
743                {
744                    osg::Vec3 tc;
745                    osg::Texture* texture = ray->getFirstIntersection().getTextureLookUp(tc);
746                    if (texture)
747                    {
748                        // look up Texture in RTT Camera's.
749                        for(unsigned int i=0; i<view->getNumSlaves();++i)
750                        {
751                            osg::Camera* slave_camera = view->getSlave(i)._camera;
752                            if (slave_camera)
753                            {
754                                osg::Camera::BufferAttachmentMap::const_iterator ba_itr = slave_camera->getBufferAttachmentMap().find(osg::Camera::COLOR_BUFFER);
755                                if (ba_itr != slave_camera->getBufferAttachmentMap().end())
756                                {
757                                    if (ba_itr->second._texture == texture)
758                                    {
759                                        osg::TextureRectangle* tr = dynamic_cast<osg::TextureRectangle*>(ba_itr->second._texture.get());
760                                        osg::TextureCubeMap* tcm = dynamic_cast<osg::TextureCubeMap*>(ba_itr->second._texture.get());
761                                        if (tr)
762                                        {
763                                            event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, static_cast<float>(tr->getTextureWidth()),
764                                                                                                           tc.y(), 0.0f, static_cast<float>(tr->getTextureHeight())));
765                                        }
766                                        else if (tcm)
767                                        {
768                                            OSG_NOTICE<<"  Slave has matched texture cubemap"<<ba_itr->second._texture.get()<<", "<<ba_itr->second._face<<std::endl;
769                                        }
770                                        else
771                                        {
772                                            event.addPointerData(new osgGA::PointerData(slave_camera, tc.x(), 0.0f, 1.0f,
773                                                                                                           tc.y(), 0.0f, 1.0f));
774                                        }
775                                    }
776                                }
777                            }
778                        }
779                    }
780                }
781            }
782        }
783    }
784}
785   
786   
787void CompositeViewer::generatePointerData(osgGA::GUIEventAdapter& event)
788{
789    osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(event.getGraphicsContext());
790    if (!gw) return;
791
792    float x = event.getX();
793    float y = event.getY();
794
795    bool invert_y = event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
796    if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
797   
798    event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width,
799                                                    y, 0, gw->getTraits()->height));
800
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->getAllowEventFocus() &&
808            camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
809        {
810            osg::Viewport* viewport = camera ? camera->getViewport() : 0;
811            if (viewport &&
812                x >= viewport->x() && y >= viewport->y() &&
813                x <= (viewport->x()+viewport->width()) && y <= (viewport->y()+viewport->height()) )
814            {
815                event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,
816                                                                    (y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));
817
818                osgViewer::View* view = dynamic_cast<osgViewer::View*>(camera->getView());
819                osg::Camera* view_masterCamera = view ? view->getCamera() : 0;
820
821                // if camera isn't the master it must be a slave and could need reprojecting.
822                if (view && camera!=view_masterCamera)
823                {
824                    generateSlavePointerData(camera, event);
825                }
826            }
827        }
828    }
829}
830
831void CompositeViewer::reprojectPointerData(osgGA::GUIEventAdapter& source_event, osgGA::GUIEventAdapter& dest_event)
832{
833    osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(dest_event.getGraphicsContext());
834    if (!gw) return;
835
836    float x = dest_event.getX();
837    float y = dest_event.getY();
838
839    bool invert_y = dest_event.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
840    if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
841
842    dest_event.addPointerData(new osgGA::PointerData(gw, x, 0, gw->getTraits()->width,
843                                                         y, 0, gw->getTraits()->height));
844
845    osg::Camera* camera = (source_event.getNumPointerData()>=2) ? dynamic_cast<osg::Camera*>(source_event.getPointerData(1)->object.get()) : 0;
846    osg::Viewport* viewport = camera ? camera->getViewport() : 0;
847
848    if (!viewport) return;
849   
850    dest_event.addPointerData(new osgGA::PointerData(camera, (x-viewport->x())/viewport->width()*2.0f-1.0f, -1.0, 1.0,
851                                                             (y-viewport->y())/viewport->height()*2.0f-1.0f, -1.0, 1.0));
852
853    osgViewer::View* view = dynamic_cast<osgViewer::View*>(camera->getView());
854    osg::Camera* view_masterCamera = view ? view->getCamera() : 0;
855
856    // if camera isn't the master it must be a slave and could need reprojecting.
857    if (view && camera!=view_masterCamera)
858    {
859        generateSlavePointerData(camera, dest_event);
860    }
861}
862
863struct SortEvents
864{
865    bool operator() (const osg::ref_ptr<osgGA::GUIEventAdapter>& lhs,const osg::ref_ptr<osgGA::GUIEventAdapter>& rhs) const
866    {
867        return lhs->getTime() < rhs->getTime();
868    }
869};
870
871void CompositeViewer::eventTraversal()
872{
873    if (_done) return;
874
875    if (_views.empty()) return;
876
877    double cutOffTime = (_runFrameScheme==ON_DEMAND) ? DBL_MAX : _frameStamp->getReferenceTime();
878
879    double beginEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
880
881    // need to copy events from the GraphicsWindow's into local EventQueue for each view;
882    typedef std::map<osgViewer::View*, osgGA::EventQueue::Events> ViewEventsMap;
883    ViewEventsMap viewEventsMap;
884
885    Contexts contexts;
886    getContexts(contexts);
887
888    // set done if there are no windows
889    checkWindowStatus(contexts);
890    if (_done) return;
891   
892    osgGA::EventQueue::Events all_events;
893   
894    for(Contexts::iterator citr = contexts.begin();
895        citr != contexts.end();
896        ++citr)
897    {
898        osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
899        if (gw)
900        {
901            gw->checkEvents();
902
903            osgGA::EventQueue::Events gw_events;
904            gw->getEventQueue()->takeEvents(gw_events, cutOffTime);
905
906            for(osgGA::EventQueue::Events::iterator itr = gw_events.begin();
907                itr != gw_events.end();
908                ++itr)
909            {
910                (*itr)->setGraphicsContext(gw);
911            }
912
913            all_events.insert(all_events.end(), gw_events.begin(), gw_events.end());
914        }
915    }
916
917    // sort all the events in time order so we can make sure we pass them all on in the correct order.
918    all_events.sort(SortEvents());
919   
920    // pass on pointer data onto non mouse events to keep the position data usable by all recipients of all events.
921    for(osgGA::EventQueue::Events::iterator itr = all_events.begin();
922        itr != all_events.end();
923        ++itr)
924    {
925        osgGA::GUIEventAdapter* event = itr->get();
926
927        switch(event->getEventType())
928        {
929            case(osgGA::GUIEventAdapter::PUSH):
930            case(osgGA::GUIEventAdapter::RELEASE):
931            case(osgGA::GUIEventAdapter::DOUBLECLICK):
932            case(osgGA::GUIEventAdapter::MOVE):
933            case(osgGA::GUIEventAdapter::DRAG):
934            {
935                if ((event->getEventType()!=osgGA::GUIEventAdapter::DRAG && event->getEventType()!=osgGA::GUIEventAdapter::RELEASE) ||
936                    !_previousEvent ||
937                    _previousEvent->getGraphicsContext()!=event->getGraphicsContext() ||
938                    _previousEvent->getNumPointerData()<2)
939                {
940                    generatePointerData(*event);
941                }
942                else
943                {
944                    reprojectPointerData(*_previousEvent, *event);
945                }
946
947#if 0               
948                // assign topmost PointeData settings as the events X,Y and InputRange
949                osgGA::PointerData* pd = event->getPointerData(event->getNumPointerData()-1);
950                event->setX(pd->x);
951                event->setY(pd->y);
952                event->setInputRange(pd->xMin, pd->yMin, pd->xMax, pd->yMax);
953                event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
954#else               
955                if (event->getMouseYOrientation()!=osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)
956                {
957                    event->setY((event->getYmax()-event->getY())+event->getYmin());
958                    event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
959                }
960#endif               
961
962                _previousEvent = event;
963               
964                break;
965            }
966            default:
967                if (_previousEvent.valid()) event->copyPointerDataFrom(*_previousEvent);
968                break;
969        }
970
971        osgGA::PointerData* pd = event->getNumPointerData()>0 ? event->getPointerData(event->getNumPointerData()-1) : 0;
972        osg::Camera* camera = pd ? dynamic_cast<osg::Camera*>(pd->object.get()) : 0;
973        osgViewer::View* view = camera ? dynamic_cast<osgViewer::View*>(camera->getView()) : 0;
974       
975        if (!view)
976        {
977            if (_viewWithFocus.valid())
978            {
979                // OSG_NOTICE<<"Falling back to using _viewWithFocus"<<std::endl;
980                view = _viewWithFocus.get();
981            }
982            else if (!_views.empty())
983            {
984                // OSG_NOTICE<<"Falling back to using first view as one with focus"<<std::endl;
985                view = _views[0].get();
986            }
987        }
988       
989        // reassign view with focus
990        if (_viewWithFocus != view)  _viewWithFocus = view;
991
992        if (view)
993        {
994            viewEventsMap[view].push_back( event );
995           
996            osgGA::GUIEventAdapter* eventState = view->getEventQueue()->getCurrentEventState();
997            eventState->copyPointerDataFrom(*event);
998        }
999
1000        _previousEvent = event;
1001    }
1002
1003    // handle any close windows
1004    for(osgGA::EventQueue::Events::iterator itr = all_events.begin();
1005        itr != all_events.end();
1006        ++itr)
1007    {
1008        osgGA::GUIEventAdapter* event = itr->get();
1009        switch(event->getEventType())
1010        {
1011            case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
1012            {
1013                bool wasThreading = areThreadsRunning();
1014                if (wasThreading) stopThreading();
1015
1016                if (event->getGraphicsContext())
1017                {
1018                    event->getGraphicsContext()->close();
1019                }
1020
1021                if (wasThreading) startThreading();
1022
1023                break;
1024            }
1025            default:
1026                break;
1027        }
1028    }
1029       
1030
1031    for(RefViews::iterator vitr = _views.begin();
1032        vitr != _views.end();
1033        ++vitr)
1034    {
1035        View* view = vitr->get();
1036
1037        // get events from user Devices attached to Viewer.
1038        for(osgViewer::View::Devices::iterator eitr = view->getDevices().begin();
1039            eitr != view->getDevices().end();
1040            ++eitr)
1041        {
1042            osgGA::Device* es = eitr->get();
1043            if (es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS)
1044                es->checkEvents();
1045
1046            // open question, will we need to reproject mouse coordinates into current view's coordinate frame as is down for GraphicsWindow provided events?
1047            // for now assume now and just get the events directly without any reprojection.
1048            es->getEventQueue()->takeEvents(viewEventsMap[view], cutOffTime);
1049        }
1050
1051        // generate frame event
1052        view->getEventQueue()->frame( getFrameStamp()->getReferenceTime() );
1053
1054        view->getEventQueue()->takeEvents(viewEventsMap[view], cutOffTime);
1055    }
1056
1057    if ((_keyEventSetsDone!=0) || _quitEventSetsDone)
1058    {
1059        for(ViewEventsMap::iterator veitr = viewEventsMap.begin();
1060            veitr != viewEventsMap.end();
1061            ++veitr)
1062        {
1063            for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin();
1064                itr != veitr->second.end();
1065                ++itr)
1066            {
1067                osgGA::GUIEventAdapter* event = itr->get();
1068                switch(event->getEventType())
1069                {
1070                    case(osgGA::GUIEventAdapter::KEYUP):
1071                        if (_keyEventSetsDone && event->getKey()==_keyEventSetsDone) _done = true;
1072                        break;
1073
1074                    case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
1075                        if (_quitEventSetsDone) _done = true;
1076                        break;
1077
1078                    default:
1079                        break;
1080                }
1081            }
1082        }
1083    }
1084
1085    if (_done) return;
1086
1087    if (_eventVisitor.valid())
1088    {
1089        _eventVisitor->setFrameStamp(getFrameStamp());
1090        _eventVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());
1091
1092        for(ViewEventsMap::iterator veitr = viewEventsMap.begin();
1093            veitr != viewEventsMap.end();
1094            ++veitr)
1095        {
1096            View* view = veitr->first;
1097
1098            if (view && view->getSceneData())
1099            {
1100                _eventVisitor->setActionAdapter(view);
1101
1102                for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin();
1103                    itr != veitr->second.end();
1104                    ++itr)
1105                {
1106                    osgGA::GUIEventAdapter* event = itr->get();
1107
1108                    _eventVisitor->reset();
1109                    _eventVisitor->addEvent( event );
1110
1111                    view->getSceneData()->accept(*_eventVisitor);
1112
1113                    // Do EventTraversal for slaves with their own subgraph
1114                    for(unsigned int i=0; i<view->getNumSlaves(); ++i)
1115                    {
1116                        osg::View::Slave& slave = view->getSlave(i);
1117                        osg::Camera* camera = slave._camera.get();
1118                        if(camera && !slave._useMastersSceneData)
1119                        {
1120                            camera->accept(*_eventVisitor);
1121                        }
1122                    }
1123
1124                    // call any camera event callbacks, but only traverse that callback, don't traverse its subgraph
1125                    // leave that to the scene update traversal.
1126                    osg::NodeVisitor::TraversalMode tm = _eventVisitor->getTraversalMode();
1127                    _eventVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
1128
1129                    if (view->getCamera() && view->getCamera()->getEventCallback()) view->getCamera()->accept(*_eventVisitor);
1130
1131                    for(unsigned int i=0; i<view->getNumSlaves(); ++i)
1132                    {
1133                        osg::View::Slave& slave = view->getSlave(i);
1134                        osg::Camera* camera = view->getSlave(i)._camera.get();
1135                        if (camera && slave._useMastersSceneData && camera->getEventCallback())
1136                        {
1137                            camera->accept(*_eventVisitor);
1138                        }
1139                    }
1140
1141                    _eventVisitor->setTraversalMode(tm);
1142
1143                }
1144            }
1145        }
1146
1147    }
1148
1149    for(ViewEventsMap::iterator veitr = viewEventsMap.begin();
1150        veitr != viewEventsMap.end();
1151        ++veitr)
1152    {
1153        View* view = veitr->first;
1154
1155        for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin();
1156            itr != veitr->second.end();
1157            ++itr)
1158        {
1159            osgGA::GUIEventAdapter* event = itr->get();
1160
1161            for(View::EventHandlers::iterator hitr = view->getEventHandlers().begin();
1162                hitr != view->getEventHandlers().end();
1163                ++hitr)
1164            {
1165                (*hitr)->handleWithCheckAgainstIgnoreHandledEventsMask( *event, *view, 0, _eventVisitor.get());
1166            }
1167        }
1168    }
1169
1170    for(ViewEventsMap::iterator veitr = viewEventsMap.begin();
1171        veitr != viewEventsMap.end();
1172        ++veitr)
1173    {
1174        View* view = veitr->first;
1175
1176        for(osgGA::EventQueue::Events::iterator itr = veitr->second.begin();
1177            itr != veitr->second.end();
1178            ++itr)
1179        {
1180            osgGA::GUIEventAdapter* event = itr->get();
1181
1182            if (view->getCameraManipulator())
1183            {
1184                view->getCameraManipulator()->handleWithCheckAgainstIgnoreHandledEventsMask( *event, *view);
1185            }
1186        }
1187    }
1188
1189    if (getViewerStats() && getViewerStats()->collectStats("event"))
1190    {
1191        double endEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1192
1193        // update current frames stats
1194        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal begin time", beginEventTraversal);
1195        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal end time", endEventTraversal);
1196        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal time taken", endEventTraversal-beginEventTraversal);
1197    }
1198}
1199
1200void CompositeViewer::updateTraversal()
1201{
1202    if (_done) return;
1203
1204    double beginUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1205
1206    _updateVisitor->reset();
1207    _updateVisitor->setFrameStamp(getFrameStamp());
1208    _updateVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());
1209
1210    Scenes scenes;
1211    getScenes(scenes);
1212    for(Scenes::iterator sitr = scenes.begin();
1213        sitr != scenes.end();
1214        ++sitr)
1215    {
1216        Scene* scene = *sitr;
1217        scene->updateSceneGraph(*_updateVisitor);
1218    }
1219
1220    // if we have a shared state manager prune any unused entries
1221    if (osgDB::Registry::instance()->getSharedStateManager())
1222        osgDB::Registry::instance()->getSharedStateManager()->prune();
1223
1224    // update the Registry object cache.
1225    osgDB::Registry::instance()->updateTimeStampOfObjectsInCacheWithExternalReferences(*getFrameStamp());
1226    osgDB::Registry::instance()->removeExpiredObjectsInCache(*getFrameStamp());
1227
1228
1229    if (_incrementalCompileOperation.valid())
1230    {
1231        // merge subgraphs that have been compiled by the incremental compiler operation.
1232        _incrementalCompileOperation->mergeCompiledSubgraphs(getFrameStamp());
1233    }
1234
1235    if (_updateOperations.valid())
1236    {
1237        _updateOperations->runOperations(this);
1238    }
1239
1240    for(RefViews::iterator vitr = _views.begin();
1241        vitr != _views.end();
1242        ++vitr)
1243    {
1244        View* view = vitr->get();
1245
1246        {
1247            // Do UpdateTraversal for slaves with their own subgraph
1248            for(unsigned int i=0; i<view->getNumSlaves(); ++i)
1249            {
1250                osg::View::Slave& slave = view->getSlave(i);
1251                osg::Camera* camera = slave._camera.get();
1252                if(camera && !slave._useMastersSceneData)
1253                {
1254                    camera->accept(*_updateVisitor);
1255                }
1256            }
1257
1258            // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
1259            // leave that to the scene update traversal.
1260            osg::NodeVisitor::TraversalMode tm = _updateVisitor->getTraversalMode();
1261            _updateVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
1262
1263            if (view->getCamera() && view->getCamera()->getUpdateCallback()) view->getCamera()->accept(*_updateVisitor);
1264
1265            for(unsigned int i=0; i<view->getNumSlaves(); ++i)
1266            {
1267                osg::View::Slave& slave = view->getSlave(i);
1268                osg::Camera* camera = slave._camera.get();
1269                if (camera && slave._useMastersSceneData && camera->getUpdateCallback())
1270                {
1271                    camera->accept(*_updateVisitor);
1272                }
1273            }
1274
1275            _updateVisitor->setTraversalMode(tm);
1276        }
1277
1278
1279        if (view->getCameraManipulator())
1280        {
1281            view->setFusionDistance( view->getCameraManipulator()->getFusionDistanceMode(),
1282                                    view->getCameraManipulator()->getFusionDistanceValue() );
1283           
1284            view->getCameraManipulator()->updateCamera(*(view->getCamera()));
1285           
1286        }
1287        view->updateSlaves();
1288
1289    }
1290
1291    if (getViewerStats() && getViewerStats()->collectStats("update"))
1292    {
1293        double endUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1294
1295        // update current frames stats
1296        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal begin time", beginUpdateTraversal);
1297        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal end time", endUpdateTraversal);
1298        getViewerStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal time taken", endUpdateTraversal-beginUpdateTraversal);
1299    }
1300
1301}
1302
1303double CompositeViewer::elapsedTime()
1304{
1305    return osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1306}
1307
1308void CompositeViewer::getUsage(osg::ApplicationUsage& usage) const
1309{
1310    for(RefViews::const_iterator vitr = _views.begin();
1311        vitr != _views.end();
1312        ++vitr)
1313    {
1314        const View* view = vitr->get();
1315        if (view->getCameraManipulator())
1316        {
1317            view->getCameraManipulator()->getUsage(usage);
1318        }
1319
1320        for(View::EventHandlers::const_iterator hitr = view->_eventHandlers.begin();
1321            hitr != view->_eventHandlers.end();
1322            ++hitr)
1323        {
1324            (*hitr)->getUsage(usage);
1325        }
1326    }
1327}
Note: See TracBrowser for help on using the browser.